Three.js Efficiently Mapping Uvs to Plane

4.4k views Asked by At

I'm working on a game where there are many walls of the same texture but at different lengths/heights. Currently I am cloning a base texture and setting the repeat values for each wall. This creates to many textures in memory.

What I want to do is to alter the planes uvs to fit the textures properly. I took a stab at this a came up with some meh results.

            var X = 2000;
            var Y = 1000;

            var seg = Math.ceil(X/Y);

            var wallgeo = new THREE.PlaneGeometry(X,Y,seg,1);

            var uvs = [];
            for(var i=0,len=wallgeo.faces.length;i<len;i+=2){
                uvs.push([new THREE.Vector2(0,1),new THREE.Vector2(0,0),new THREE.Vector2(1,1)]);
                uvs.push([new THREE.Vector2(0,0),new THREE.Vector2(1,0),new THREE.Vector2(1,1)]);               
            }       

            wallgeo.faceVertexUvs = [uvs];
            wallgeo.uvsNeedUpdate = true;

            var walltex = DDSLoader.load('materialmaptextures/21_2048.dds');
            var wallmat = new THREE.MeshPhongMaterial({map:walltex, transparent:true, wireframe:false});
            wall = new THREE.Mesh(wallgeo,wallmat);
            wall.position.set(0,Y/2,-300);

            scene.add(wall);

The problems with this as you can probably tell are that for one additional faces are created, not a huge deal but I would really like to avoid this. Most importantly if the planes length is not evenly divisible by its height the texture will stretch/compress. Also, the planes height segments in this are fixed causing restrictions.

I'm not so much concerned with creating additional faces. Is this necessary? Can one face have more than one uv per triangle? Does it need to?

I am new to messing with Uv's, there has got to be an efficient way to make my walls not look absurd without blowing up memory, right?

Demo: http://www.titansoftime.com/uv.php

1

There are 1 answers

1
WestLangley On BEST ANSWER

You want to be able to modify the UVs of a PlaneGeometry so a repeated texture always renders the same size, regardless of the dimensions of the plane. This is an alternative to setting texture.repeat values.

Here is the pattern to follow:

// geometry
var width = 20;  // width of plane in world units
var height = 10; // height of plane in world units
var size = 5;    // texture block size in world units

var w = width / size;
var h = height / size;
var geometry = new THREE.PlaneGeometry( width, height, 1, 1 );

var uvs = geometry.faceVertexUvs[ 0 ];
uvs[ 0 ][ 0 ].set( 0, h );
uvs[ 0 ][ 1 ].set( 0, 0 );
uvs[ 0 ][ 2 ].set( w, h );
uvs[ 1 ][ 0 ].set( 0, 0 );
uvs[ 1 ][ 1 ].set( w, 0 );
uvs[ 1 ][ 2 ].set( w, h );

// texture
var texture = THREE.ImageUtils.loadTexture( "..." );
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;

three.js r.69