如何减小和增加对象上图像的大小 - ThreeJS [英] How to decrease and increase the size of an image on an object - ThreeJS

查看:44
本文介绍了如何减小和增加对象上图像的大小 - ThreeJS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm making use of the THREE.ImageUtils.loadTexture function to load an image and then paste it onto each of the objects in my scene like so:

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

我研究了 tex.scale.x,tex.scale.y &tex.offset.x, tex.offset.y 但这些似乎不是我需要的.这是该对象此刻的样子

I've looked into tex.scale.x,tex.scale.y & tex.offset.x, tex.offset.y but these don't seem to be what I need. Here's what the object looks like at the moment

但我在每一边都追求更严格的定位.像这样的东西(伪代码),它将把左上角放在那个位置所需的一侧.

but I'm after stricter positioning on each side. Something like this (pseudocode) which would place the top-left corner on that required side at that position.

sideA.image.setSize(x,y);

有人有这方面的例子吗?

Does anyone have any examples of this?

编辑

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

Thanks for the feedback so far guys. @Martin I've setup a basic PlaneGeometry shape to test this out. So this shapes face is basic two triangles attached to each other; I've attached an image of what the uv settings that you posted do:

因此,根据您的说法,我无法扩展其中一个三角形,因为这会破坏所使用的几何形状,因此我需要操纵这两个三角形以正确移动图像.正确吗?

So from what you said I can't extend one of the triangles as that would break the geometry used so I need to manipulate both the triangles to move the image around properly. Correct?

推荐答案

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

Unfortunately, there is no easy way to do this in three.js.

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

In order to get proper control over the texturing of non-trivial meshes, you will probably need to do some UV-unwrapping of the model first. This should™ normally be done by the person providing the meshes, because it is way easier to do it in tools like blender, 3dstudio, cinema4d and the likes.

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

However, I assume that you don't have that person available for some reason and need to do this in javascript. It's more fun this way. Let's further assume, that we just want to map the image to the front- and backside of the bag, the inside and edges will not be textured.

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

In three.js and most other 3D-applications, the exact mapping of the texture happens by providing texture-coordinates (aka UV-coordinates) for each vertex for every face. These UV-coordinates (ranged from 0 to 1) specify the position in the texture that belongs to the vertex. The point (0, 0) is the bottom-left corner of the image and (1, 1) the top-right corner, independent of the image's aspect-ratio.

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

So, for a simple quad made from two triangles this would be something like this:

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;

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

So, this is just the geometry itself, but it's important to know how it was built for the next step - the UV-coordinates:

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]];

基本上就是这样.这大致就是 THREE.PlaneGeometry 所做的.关于这一点还有几点:

And that's it basically. This is roughly what THREE.PlaneGeometry does. Some more points about that:

  • three.js 能够处理两组不同的 uv 坐标,这就是 geometry.faceVertexUvs[0] 的原因.
  • 该数组中的索引对应于 faces-array 中的索引,所以 uvs[0] 是第一个面,uvs[1] 是第二个.
  • 每一个都是一个长度为 3 的数组,对应于该面的顶点.
  • three.js is able to handle two different sets of uv-coordinates, that's why there is the geometry.faceVertexUvs[0].
  • the indices within that array correspond to the indices in the faces-array, so uvs[0] is the first face and uvs[1] the second.
  • each of those is again an array of length 3 corresponding to the vertices of that face.

现在就您的包而言,应该可以找出哪两个面是正面和背面的部分.您将需要找到它们并编辑它们的 UV 坐标以匹配您想要查看的图像中的位置(我不知道这些模型的确切外观,因此我无法在这里为您提供更多帮助).所有其他 UV 坐标都可以设置为某个安全值,例如 (0, 0),然后所有不是正面或背面的颜色都将具有左下角像素的颜色你的质地.

Now in the case of your bags it should be possible to find out which two faces are the front-facing and back-facing part. You will need to find them and edit their UV-coordinates to match the positions in the image you want to see (I don't know how exactly those models look, so I can't help you much further here). All the other UV-coordinates could be set to some safe value, like (0, 0), then everything that is not the front- or back-side will have the color of the bottom-left pixel of your texture.

如果您还想对它们进行纹理处理,您真的应该考虑在适当的 3d 编辑软件中制作纹理贴图.

If you want to texture them as well, you should really consider doing the texture-map in proper 3d-editing software.

编辑 (2017-01-15)

查看带有 angular-logo 的图像,左上角的三角形被翻转了.这是因为three.js 使用了与我在示例中不同的面或顶点顺序.

Looking at the image with the angular-logo, the top-left triangle is flipped. This is because three.js is using a different face- or vertex-order than I did in my example.

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

It helps a lot to understand these things if you just play around with it in the browser-console or debugger (this is what i just did). According to that, the plane-geometry from three.js has the following structure:

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

vertices = [A, B, C, D]
faces = [Face3(A, C, B), Face3(C, B, D)]

这里值得注意的是,无论出于何种原因,第一个面是逆时针方向,第二个面是顺时针方向(我认为这是一种不好的做法,三角形应该始终是逆时针方向).查看几何体的 faceVertexUVs 以了解它在这种情况下的外观(只需在浏览器控制台中键入 new THREE.PlaneGeometry(1,1).faceVertexUvs[0])

Notable is here that, for whatever reason, the first face is counterclockwise and the second face in clockwise-order (i believe that is kind of bad practice and triangles should always be counterclockwise). Have a look at the faceVertexUVs for the geometry to see how it should look like for this case (just type new THREE.PlaneGeometry(1,1).faceVertexUvs[0] into the browser-console)

现在是另一点,缩放纹理.您可以尝试的一件事是对顶点使用大于 1 的 UV 值.这将导致纹理绘制得更小.但是,这只有在

Now for the other point, scaling the textures. One thing you could try is to use UV-values greater than 1 for the vertices. This would cause the texture to be drawn smaller. However, this will only work properly if

  • 纹理环绕模式是夹边(texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;)
  • 所有纹理都有一个 1px 宽的中性色边框

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

Otherwise (and this is the way I would recommend) you should use a canvas as texture and prepare the image before actually using it. I made a simple example here: http://codepen.io/usefulthink/pen/GrjmrM?editors=0010

这篇关于如何减小和增加对象上图像的大小 - ThreeJS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆