如何减少和增加对象上的图像大小 - ThreeJS

Kat*_*a24 8 three.js

我正在使用该THREE.ImageUtils.loadTexture函数加载图像,然后将其粘贴到场景中的每个对象上,如下所示:

_.forEach(bags, (bag) => {
  if(bag['children'][0] && bag['children'][0].material) {
    let material = new THREE.MeshPhongMaterial({map: tex});
    bag['children'][0].material = material;
  }
});
Run Code Online (Sandbox Code Playgroud)

我已经调查了tex.scale.x,tex.scale.y&tex.offset.x,tex.offset.y但这些似乎不是我需要的.这是目前物体的样子

在此输入图像描述

但是我对每一方都有更严格的定位.像这样的东西(伪代码)会将左上角放在那个位置的所需边上.

sideA.image.setSize(x,y);
Run Code Online (Sandbox Code Playgroud)

有没有人有这方面的例子?

编辑

感谢您到目前为止的反馈.@Martin我已经设置了一个基本的PlaneGeometry形状来测试它.所以这个形状的脸是基本的两个三角形相互连接; 我附上了你发布的uv设置的图片:

在此输入图像描述

所以从你所说的我不能扩展其中一个三角形,因为这会打破使用的几何体,所以我需要操纵两个三角形来正确地移动图像.正确?

Mar*_*fuß 5

不幸的是,在three.js中没有简单的方法可以做到这一点.

为了正确控制非平凡网格的纹理,您可能需要先对模型进行一些UV展开.这应该通常由提供网格的人来完成,因为在诸如blender,3dstudio,cinema4d等工具中更容易做到这一点.

但是,我假设您由于某种原因没有该人可用,并且需要在javascript中执行此操作.这种方式更有趣.让我们进一步假设,我们只想将图像映射到包的正面和背面,内部和边缘不会被纹理化.

在three.js和大多数其他3D应用程序中,纹理的精确映射通过为每个面提供每个顶点的纹理坐标(也称为UV坐标)来实现.这些UV坐标(范围从0到1)指定纹理中属于顶点的位置.该点(0, 0)是图像的左下角和(1, 1)右上角,与图像的纵横比无关.

所以,对于一个由两个三角形组成的简单四边形,这将是这样的:

const geometry = new THREE.Geometry();
const vertices = [
   // the four vertices ABCD
   [0,0,0], [0,1,0], [1,0,0], [1,1,0]
].map(v => new THREE.Vector3(...v));

// setup two triangles ADB and ACD:
//
// B---D
// | / |
// A---C

const normal = new THREE.Vector3(0,0,1);
const faces = [
  new THREE.Face3(0, 3, 1, normal),
  new THREE.Face3(0, 2, 3, normal)
];

geometry.vertices = vertices;
geometry.faces = faces;
Run Code Online (Sandbox Code Playgroud)

所以,这只是几何本身,但重要的是要知道它是如何为下一步构建的 - UV坐标:

const uvs = geometry.faceVertexUvs[0];
const vertexUvs = [
  [0,0], [0,1], [1,0], [1,1]
].map(p => new THREE.Vector2(...p));

// we need to set the UV-coordinates for both faces separately, using 
// the same scheme as before:
uvs[0] = [vertexUvs[0], vertexUvs[3], vertexUvs[1]];
uvs[1] = [vertexUvs[0], vertexUvs[2], vertexUvs[3]];
Run Code Online (Sandbox Code Playgroud)

这基本上就是这样.这大致是THREE.PlaneGeometry做什么的.关于这一点的更多要点:

  • three.js能够处理两组不同的uv坐标,这就是为什么有这样的geometry.faceVertexUvs[0].
  • 该数组中的索引对应于faces-array中的索引,uvs[0]第一个面和uvs[1]第二个面也是如此.
  • 其中每一个都是长度为3的数组,对应于该面的顶点.

现在,对于你的行李箱,应该可以找出哪两个面是正面和背面的部分.您需要找到它们并编辑它们的UV坐标以匹配您想要看到的图像中的位置(我不知道这些模型究竟是什么样的,所以我在这里无法帮助您).所有其他的UV坐标都可以设置为某个安全值,例如(0, 0),不是前面或后面的所有内容都将具有纹理左下角像素的颜色.

如果你想要对它们进行纹理化,你应该考虑在适当的3D编辑软件中进行纹理贴图.

编辑(2017-01-15)

使用角度徽标查看图像,左上角三角形被翻转.这是因为three.js使用的是与我的示例中不同的面或顶点顺序.

如果您只是在浏览器控制台或调试器中使用它(这就是我刚才所做的),那么理解这些东西会有很大帮助.据此,来自three.js的平面几何结构具有以下结构:

// A---B
// | / |
// C---D

vertices = [A, B, C, D]
faces = [Face3(A, C, B), Face3(C, B, D)]
Run Code Online (Sandbox Code Playgroud)

值得注意的是,无论出于何种原因,第一面是逆时针方向,第二面是顺时针方向(我认为这是一种不好的做法,三角形应该始终是逆时针方向).看一下几何的faceVertexUV,看看这种情况应该是什么样子(只需输入new THREE.PlaneGeometry(1,1).faceVertexUvs[0]浏览器控制台)

现在换另一点,缩放纹理.您可以尝试的一件事是为顶点使用大于1的UV值.这将导致纹理绘制得更小.但是,这只会在以下情况下正常工作

  • 纹理包装模式是夹到边(texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;)
  • 所有纹理都有1px宽的边框,中性色

否则(这是我推荐的方式)你应该使用画布作为纹理并在实际使用之前准备图像.我在这里做了一个简单的例子:http://codepen.io/usefulthink/pen/GrjmrM?editors = 0010