(Three.js) Custom Mesh UV Display Texture Properly

末鹿安然 提交于 2020-01-14 01:34:05

问题


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.

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

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

Gives me this: BAD UV

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

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

(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

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.

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

回答1:


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^^



来源:https://stackoverflow.com/questions/19798637/three-js-custom-mesh-uv-display-texture-properly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!