(Three.js) 正确自定义网格 UV 显示纹理 [英] (Three.js) Custom Mesh UV Display Texture Properly

查看:101
本文介绍了(Three.js) 正确自定义网格 UV 显示纹理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我基于平面几何为 Three.js 创建了一个自定义几何函数.一切正常,只是我不知道如何正确显示 UV.我每个正方形使用 4 个三角形,而 THREE.PlaneGeometry 每个正方形只使用 2 个三角形.

I have created a custom Geometry function for Three.js, based on the Plane Geometry. Everything works fine, except that I don't know how to make the UV display correctly. I use 4 triangles per Square, while the THREE.PlaneGeometry is only using 2 triangles per square.

PlaneGeometry UV 的代码如下所示:

The code for PlaneGeometry UV's looks like this:

var uva = new THREE.Vector2( ix / gridX, 1 - iz / gridZ );
var uvb = new THREE.Vector2( ix / gridX, 1 - ( iz + 1 ) / gridZ );
var uvc = new THREE.Vector2( ( ix + 1 ) / gridX, 1 - ( iz + 1 ) / gridZ );
var uvd = new THREE.Vector2( ( ix + 1 ) / gridX, 1 - iz / gridZ );

以及我在源代码中的代码:

And my Code in the Source Code:

var uva = new THREE.Vector2( a );
var uvb = new THREE.Vector2( b );
var uvc = new THREE.Vector2( c );
var uvd = new THREE.Vector2( d );
var uve = new THREE.Vector2( e );

显然这是错误的.但是我尝试使用 PlaneGeometry 代码,但我得到了奇怪的扭曲,我不知道如何计算正确的位置.这:

Obviously that is wrong. But I have tried to use the PlaneGeometry code, and I get odd distortions, and I am not sure how to calculate the proper positions. This:

var uva = new THREE.Vector2( ix / gridX, 1 - iz / gridZ );
var uvb = new THREE.Vector2( ix / gridX, 1 - ( iz + 1 ) / gridZ );
var uvc = new THREE.Vector2( ( ix + 1 ) / gridX, 1 - ( iz + 1 ) / gridZ );
var uvd = new THREE.Vector2( (( ix ) / gridX) + gridX, 1 - iz / gridZ );
var uve = new THREE.Vector2( ( ix + 1 ) / gridX, 1 - iz / gridZ );

给我这个:坏紫外线

我在THREE.JS聊天室得到了一些答案,但我没看懂,那个人也没有详细说明...

I got some sort of answer in the THREE.JS ChatRoom, but I did not understand it, and the person did not elaborate...

(Q) 那么.. UV 的 Vector2 不应该与顶点位于相同的位置吗?

(Q) So.. are the Vector2 for UV's not supposed to be the same position as the verticies ?

(A) 没有 UV 是映射到纹理的向量,如果你有一个 512x512 的纹理和一个 [0.25, 0.75] 的 UV,它将映射到纹理中 256、768 处的像素每个顶点都有一个 uv这意味着这个顶点像上面解释的那样映射到纹理中这是为顶点的每个面完成的,以及然后使用这三个 uv 对人脸进行插值

(A) no an UV is a vector that maps into a texture if you have a 512x512 texture, and an UV with [0.25, 0.75], it would map to the pixel in the texture at 256, 768 each vertex has an uv this means that this vertex maps into the texture like explained above this is done for each face of a vertex, and all fragments in the face are then interpolated using those three uvs

所以这并没有消除我的困惑..我不明白 [0.25, 0.75] 部分.或者每个顶点都有一个纹理.一个点怎么会有纹理.

So that did not remove my confusion.. I did not understand the [0.25, 0.75] part. Or that every vertex has a texture. How can a point have a texture.

有人能指出我正确的方向吗?我只需要知道 UV 是如何定位的.但是一个例子会很棒.

Could someone point me in the right direction please ? All I need is to know how the UV is positioned. But an example would be great.

如果您想看一看,这里是来源:

Here is the source if you would like to take a look:

THREE.DiamondGeometry = function ( width, height, widthSegments, heightSegments ) {

    THREE.Geometry.call( this );

    this.width = width;
    this.height = height;

    this.widthSegments = widthSegments || 1;
    this.heightSegments = heightSegments || 2;

    var long_row = this.widthSegments + 1;
    var short_row = this.widthSegments;
    // First Row is the long_row, the ternary statement will toggle this.
    var current_row = short_row;
    var gridY = 0;
    var vX = width / 2, vY = height / 2;

    var ix, iz;
    var width_half = width / 2;
    var height_half = height / 2;

    var gridX = this.widthSegments;
    var gridZ = this.heightSegments;

    var gridX1 = gridX + 1;
    var gridZ1 = gridZ + ( gridZ - 2) + 1;

    var segment_width = this.width / gridX;
    var segment_height = this.height / gridZ;

    var normal = new THREE.Vector3( 0, 0, 1 );
                     // Height Segments Verticies
    for ( iz = 0; iz < (gridZ1 + 1) * 2; iz ++ ) {
        // Ternary Operator:
        current_row === long_row ? (current_row = short_row, vX = width_half - (segment_width / 2) ) : (current_row = long_row, vX = width_half );
                        // Width Segment Verticies
        for ( ix = 0; ix < current_row; ix ++ ) {

            var x = ix * segment_width - vX ;
            var y = (iz * segment_height - vY) / 2 - (vY / 2);

            this.vertices.push( new THREE.Vector3( x, - y, 0 ) );
        }
    }

    for ( iz = 0; iz < gridZ ; iz ++ ) {

            for ( ix = 0; ix < gridX; ix ++ ) {
                var a = ix + gridX * iz + (iz * gridX1) ;
                var b = a + 1;
                var c = a  + gridX1;
                var d = c + gridX;
                var e = d + 1;

                // THIS IS THE BAD PART THAT I NEED TO CALCULATE THE UV POSITIONS FOR:
                var uva = new THREE.Vector2( a );
                var uvb = new THREE.Vector2( b );
                var uvc = new THREE.Vector2( c );
                var uvd = new THREE.Vector2( d );
                var uve = new THREE.Vector2( e );



                // UP
                var face = new THREE.Face3( c, b, a );
                face.normal.copy( normal );
                face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );

                this.faces.push( face );
                this.faceVertexUvs[ 0 ].push( [ uva, uvb, uvc ] );

                // DOWN
                face = new THREE.Face3( e, c, d );
                face.normal.copy( normal );
                face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );

                this.faces.push( face );
                this.faceVertexUvs[ 0 ].push( [ uvd, uvc.clone(), uve ] );

                // LEFT
                face = new THREE.Face3( d, c, a );
                face.normal.copy( normal );
                face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );

                this.faces.push( face );
                this.faceVertexUvs[ 0 ].push( [ uva.clone(), uvc.clone(), uvd.clone() ] );

                // RIGHT
                face = new THREE.Face3( e, b, c );
                face.normal.copy( normal );
                face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );

                this.faces.push( face );
                this.faceVertexUvs[ 0 ].push( [ uvc.clone(), uvb.clone(), uve.clone() ] );

            }

    }

    this.computeCentroids();

};

THREE.DiamondGeometry.prototype = Object.create( THREE.Geometry.prototype );

推荐答案

查看此图片:http://cgkit.sourceforge.net/tutorials/_images/uvmap.png如上所述,对于没有纹理重复的 1 个纹理,UV 坐标在 (0,0) 到 (1,1) 的范围内.如果您有一个四边形平面并将 UV 分配给图像中的顶点,则整个纹理将显示在四边形上.如果您添加边缘循环/细分您的四边形,例如在 4 个较小的四边形中,但仍希望完全显示纹理而不重复,则需要计算顶点在 UV 空间中的位置之间的值.例如中间的顶点(由您的镶嵌产生)现在是 UV (0.5, 0.5)中间顶部的那个是 (0, 0.5).看看PlaneGeometry是如何做到的,并尝试从中学习^^

see this image: http://cgkit.sourceforge.net/tutorials/_images/uvmap.png As noted there, for 1 texture without texture repeat, UV coordinates are in the range from (0,0) to (1,1). If you have a quad-plane and assign the UVs to the vertices as in the image, the whole texture gets displayed on the quad. if you add edge loops/ tesselate your quad for example in 4 smaller quads but still want to have the texture compeltely displayed without repetition, you need to calculate values in between for where the vertices are in UV-space. for example the vertex in the middle (resulting from your tesselation) is now UV (0.5, 0.5) and the one at the top in the middl is (0, 0.5). See how PlaneGeometry does it and try to learn from it^^

这篇关于(Three.js) 正确自定义网格 UV 显示纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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