Lesson 10 - Specifying 3D Structures

 

Introduction

This lesson is very simple, almost trivial. It was written in the days when writing any simple 3D game that involved moving from place to place was new and different. Today, with the far more complex types of games and other 3D adventures, this example seems pretty trivial. Nonetheless, it is part of the NeHe demos, so we include it here.

The Model

The demo consists of the datafile which specifies a series of triangles that form a very simple structure that resembles nothing more than house of cards. Each of the "walls" and floor and ceiling consist of a pair of triangles, expressed as a JavaScript array. Here is the floor:

var world = 	
[	  	 
    // Floor 
    [-3.0, 0.0, -3.0, 0.0, 6.0],
    [-3.0, 0.0,  3.0, 0.0, 0.0],
    [ 3.0, 0.0,  3.0, 6.0, 0.0],
    [-3.0, 0.0, -3.0, 0.0, 6.0],
    [ 3.0, 0.0, -3.0, 6.0, 6.0],
    [ 3.0, 0.0,  3.0, 6.0, 0.0],
    etc.
]

First we read in the image and create a texture we will apply to the resulting triangles. Note that we map the texture onto both sides of each object. The original demo used a mud-like image of the original author's face I liked my puppy better (sadly Sammy developed cancer in January 2017 and had to be put to sleep. RIP Sammy), but you can get the original texture swapping "mud" for "sammy" in the code.

var texture = new THREE.ImageUtils.loadTexture("Data/Sammy.jpg");
var material = new THREE.MeshBasicMaterial( { map: texture, side:THREE.DoubleSide } );

Loading the Model

The JS array is then simply read via a link and automatically instantiated. The number of triangles is computed from the length of the array. Then the code simply loops through the array fetching three rows at a time (being the three verticies) and creates a plain Geometry and pushes the verticies into it, creating a triangular mesh.

var i1 = i * 3;
var i2 = i * 3 + 1;
var i3 = i * 3 + 2; 
					
var triGeom = new THREE.Geometry();
triGeom.vertices.push(new THREE.Vector3(world[i1][V_X],world[i1][V_Y],world[i1][V_Z]));
triGeom.vertices.push(new THREE.Vector3(world[i2][V_X],world[i2][V_Y],world[i2][V_Z]));
triGeom.vertices.push(new THREE.Vector3(world[i3][V_X],world[i3][V_Y],world[i3][V_Z]));

Create a new Face3, whose indices point into the vertices we created above

triGeom.faces.push( new THREE.Face3( 0, 1, 2 ) );

Then we need to create the mapping between our texture and the two triangles that comprise the faces (just like the previous lesson).

var uvs = [];
if ((i & 1) == 1) {				
    uvs.push( new THREE.Vector2( 0.0, 1.0 ) );
    uvs.push( new THREE.Vector2( 1.0, 1.0 ) );
    uvs.push( new THREE.Vector2( 1.0, 0.0 ) );
}
else {
    uvs.push( new THREE.Vector2( 0.0, 1.0 ) );
    uvs.push( new THREE.Vector2( 0.0, 0.0 ) );
    uvs.push( new THREE.Vector2( 1.0, 0.0 ) );					
}

Then set corresponding UV vertices, re-compute the normals, create the actual mesh, and add it to the scene.

triGeom.faceVertexUvs[ 0 ].push( [ uvs[0], uvs[1], uvs[2] ] );
					
triGeom.computeFaceNormals();
triGeom.computeVertexNormals();

var mesh = new THREE.Mesh( triGeom, material);
gfxScene.add(mesh);

Do this for each triangle and that's it. And that's it! Click on this link to see the "House of Sammy" in all his glory!

As always, the original sources are on github here.



About Us | Contact Us | ©2017 Geo-F/X