1
votes

I'm trying to apply a texture on an Object3D with a custom geometry that consists of multiple faces. From the user's point of view this should be a single surface and the texture should stretch ideally keeping the sides ratio. I've tried various texture settings but so far no luck.

The top image is what I'm getting and the bottom one what I'm trying to achieve: https://dl.dropboxusercontent.com/u/20925853/combined.jpg

I've extracted a sample code to JsFiddle: http://jsfiddle.net/Immugio/Lg5vbzot/

function render() {            

        renderer.render(scene, camera);
    };       

    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);       

    var light = new THREE.DirectionalLight(0xffffff);
    light.intensity = 0.5;
    light.position.set(0, 1, 1).normalize();
    scene.add(light);
    var ambient = new THREE.AmbientLight(0x777777);        
    scene.add(ambient);

    var controls = new THREE.OrbitControls(camera);
    controls.damping = 0.2;
    controls.addEventListener('change', render);     

    var renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    THREE.ImageUtils.crossOrigin = '';
    var textureMaterial = new THREE.MeshPhongMaterial({
        map: THREE.ImageUtils.loadTexture('https://dl.dropboxusercontent.com/u/20925853/crate.jpg', null, function() {
            render();
        })
    });

    var geo = new THREE.Geometry();
    geo.vertices = [
        new THREE.Vector3(0, 0, 0),
        new THREE.Vector3(0, 4, 0),
        new THREE.Vector3(4, 4, 0),
        new THREE.Vector3(4, 0, 0),

        new THREE.Vector3(1, 4, 0),
        new THREE.Vector3(1, 6, 0),
        new THREE.Vector3(3, 6, 0),
        new THREE.Vector3(3, 4, 0)
    ];
    geo.faces = [
        new THREE.Face3(0, 1, 2),
        new THREE.Face3(0, 2, 3),
        new THREE.Face3(4, 5, 6),
        new THREE.Face3(4, 6, 7)
    ];

    var faceuv = [
                new THREE.Vector2(0, 1),
                new THREE.Vector2(1, 1),
                new THREE.Vector2(1, 0),
                new THREE.Vector2(0, 0)
        ];

    geo.faceVertexUvs[0] = [];
    geo.faceVertexUvs[0][0] = [faceuv[0], faceuv[1], faceuv[2]];
    geo.faceVertexUvs[0][1] = [faceuv[0], faceuv[2], faceuv[3]];
    geo.faceVertexUvs[0][2] = [faceuv[0], faceuv[1], faceuv[2]];
    geo.faceVertexUvs[0][3] = [faceuv[0], faceuv[2], faceuv[3]];              

    geo.computeFaceNormals();
    var mesh = new THREE.Mesh(geo, textureMaterial);

    mesh.rotation.x = Math.PI / 180 * 135;
    mesh.rotation.z = Math.PI / 180 * 135;
    scene.add(mesh); 

    camera.position.z = 10;
1
The code in your post is using RepeatWrapping. That requires power-of-two textures. Resize image to 256 x 256 and try again.WestLangley
@WestLangley thanks for pointing that out. The 'RepeatWrapping' bit got there by mistake. I've corrected the code sample to match the one on jsfiddle.Immugio

1 Answers

3
votes

In order to strech the texture you need to map the UV accros yours multiple faces.

JsFiddle :http://jsfiddle.net/Lg5vbzot/1/

Replacing with the following code

        var faceuv = [
                new THREE.Vector2(0, 0),
                new THREE.Vector2(0, 0.66),
                new THREE.Vector2(1, 0.66),
                new THREE.Vector2(1, 0),
                new THREE.Vector2(0.25, 0.66),
                new THREE.Vector2(0.25, 1),
                new THREE.Vector2(0.75, 1),
                new THREE.Vector2(0.75, 0.66)
        ];

    geo.faceVertexUvs[0] = [];
    geo.faceVertexUvs[0][0] = [faceuv[0], faceuv[1], faceuv[2]];
    geo.faceVertexUvs[0][1] = [faceuv[0], faceuv[2], faceuv[3]];
    geo.faceVertexUvs[0][2] = [faceuv[4], faceuv[5], faceuv[6]];
    geo.faceVertexUvs[0][3] = [faceuv[4], faceuv[6], faceuv[7]];