view raw
GalileoVerma GalileoVerma - 11 months ago 385
Javascript Question

mapping of image on sphere using three.js

I am new to three.js and I trying to UV map a cube-map texture onto a sphere. I have tried to Map a cube-map onto a cube and it was pretty easy. I had this image which was mapped onto the cube as follows:
Click here to open image

This is the final output (with a different image, of same type)Click here to open the Output

This is how I carried out the UV mapping for the aforementioned task:

var geometry = new THREE.CubeGeometry( 10, 10, 10);

var material = new THREE.MeshPhongMaterial( { map:THREE.ImageUtils.loadTexture('images/texture-atlas.jpg') } );


geometry.faceVertexUvs[0] = [];

geometry.faceVertexUvs[0][0] = [ bricks[0], bricks[1], bricks[3] ];
geometry.faceVertexUvs[0][1] = [ bricks[1], bricks[2], bricks[3] ];

geometry.faceVertexUvs[0][2] = [ clouds[0], clouds[1], clouds[3] ];
geometry.faceVertexUvs[0][3] = [ clouds[1], clouds[2], clouds[3] ];

geometry.faceVertexUvs[0][4] = [ crate[0], crate[1], crate[3] ];
geometry.faceVertexUvs[0][5] = [ crate[1], crate[2], crate[3] ];

geometry.faceVertexUvs[0][6] = [ stone[0], stone[1], stone[3] ];
geometry.faceVertexUvs[0][7] = [ stone[1], stone[2], stone[3] ];

geometry.faceVertexUvs[0][8] = [ water[0], water[1], water[3] ];
geometry.faceVertexUvs[0][9] = [ water[1], water[2], water[3] ];

geometry.faceVertexUvs[0][10] = [ wood[0], wood[1], wood[3] ];
geometry.faceVertexUvs[0][11] = [ wood[1], wood[2], wood[3] ];

mesh = new THREE.Mesh(geometry, material);
mesh.position.z = -50;
scene.add( mesh );

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

window.addEventListener( 'resize', onWindowResize, false );

render();


}

Now, I want to map the cube-map (as shown in the first image) onto a sphere using UV mapping. Please have a look at this image to understand how it looks geometrically: http://i.stack.imgur.com/Ja4xB.jpg.

There are few things that I found in OpenGL, but almost nothing for Three.js

If you can come up with anything that'll help me in executing this, it'll be a great help. If possible, please show me how to map one image onto corresponding part of the sphere and I'll do it for the rest of them.

Thanks!

Answer

A SphereGeometry does not have vertices in the correct locations to achieve the mapping you want. However, you can easily create a suitable geometry by morphing BoxGeometry into a sphere.

// geometry
var geometry = new THREE.BoxGeometry( 10, 10, 10, 8, 8, 8 );

// morph box into a sphere
for ( var i = 0; i < geometry.vertices.length; i ++ ) {

    geometry.vertices[ i ].normalize().multiplyScalar( 10 ); // or whatever size you want

}

// texture is a collage; set offset/repeat per material index
var repeat = new THREE.Vector2( 1/3, 1/2 );
var offsets = [ 
    new THREE.Vector2( 0, 0 ),
    new THREE.Vector2( 0, 1/2 ),
    new THREE.Vector2( 1/3, 0 ),
    new THREE.Vector2( 1/3, 1/2 ),
    new THREE.Vector2( 2/3, 0 ),
    new THREE.Vector2( 2/3, 1/2 )
];

// redefine vertex normals consistent with a sphere; reset UVs
for ( var i = 0; i < geometry.faces.length; i ++ ) {

    var face = geometry.faces[ i ];

    face.vertexNormals[ 0 ].copy( geometry.vertices[ face.a ] ).normalize();
    face.vertexNormals[ 1 ].copy( geometry.vertices[ face.b ] ).normalize();
    face.vertexNormals[ 2 ].copy( geometry.vertices[ face.c ] ).normalize();

    var uvs = geometry.faceVertexUvs[ 0 ];

    for ( var j = 0; j < 3; j ++ ) {

        uvs[ i ][ j ].multiply( repeat ).add( offsets[ face.materialIndex ] );

    }

    // face.normal - will not be used; don't worry about it

}

var loader = new THREE.TextureLoader();
var texture = loader.load( 'texture.jpg' );

// mesh
var mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { map: texture } ) );
scene.add( mesh );

three.js r.77