Barn Demo

This file has the minimal code to create a working Three.js application, using the TW object to set up the camera for us. Because the canvas does not take the entire window, there is space for some ordinary HTML like this.

Code

Here is the code that produced the program above:

  1.  
  2. // We always need a scene.
  3. var scene = new THREE.Scene();
  4.  
  5. // ====================================================================
  6.  
  7. /* Next, we create objects in our scene. Here, the classic
  8. barn. The front left bottom vertex of the barn is the origin, so, for
  9. example, the x coordinates go from 0 to 20. */
  10.  
  11. var barnWidth = 20;
  12. var barnHeight = 30;
  13. var barnDepth = 40;
  14.  
  15. var barnGeometry = TW.createBarn( barnWidth, barnHeight, barnDepth );
  16.  
  17. // the createMesh function adds a "demo" material to the geometry
  18.  
  19. var barnMesh = TW.createMesh( barnGeometry );
  20.  
  21. // the scene is the set of things to render, so add the barn.
  22.  
  23. scene.add(barnMesh);
  24.  
  25. // ================================================================
  26. //
  27. // We always need a renderer
  28.  
  29. var renderer = new THREE.WebGLRenderer();
  30.  
  31. TW.mainInit(renderer,scene);
  32.  
  33. /* We always need a camera; here we'll use a default orbiting camera. The
  34. third argument are the ranges for the coordinates, to help with setting up
  35. the placement of the camera. They need not be perfectly accurate, but if
  36. they are way off, your camera might not see anything, and you'll get a
  37. blank canvas. */
  38.  
  39. TW.cameraSetup(renderer,
  40. scene,
  41. {minx: 0, maxx: 20,
  42. miny: 0, maxy: 30, // a bit low
  43. minz: -40, maxz: 0});

As you can see, it's very short. The TW.cameraSetup() function does the work of setting up a useful default camera for you, so that you can look at your scene from all sides. All you have to do is give it a general idea of where your scene is, using the {} object with properties like minx.

Barn Code

Now, we need to understand the barn, at least a little. Here is the code for TW.createBarn():

  1. function(width, height, length) {
  2. var w = width, h = height, len = length;
  3. var barnGeometry = new THREE.Geometry();
  4. // add the front
  5. barnGeometry.vertices.push(new THREE.Vector3(0, 0, 0)); // vertex 0
  6. barnGeometry.vertices.push(new THREE.Vector3(w, 0, 0)); // vertex 1
  7. barnGeometry.vertices.push(new THREE.Vector3(w, h, 0)); // vertex 2
  8. barnGeometry.vertices.push(new THREE.Vector3(0, h, 0)); // vertex 3
  9. barnGeometry.vertices.push(new THREE.Vector3(0.5 * w, h + 0.5 * w, 0)); // 4
  10.  
  11. // just add the back also manually
  12. barnGeometry.vertices.push(new THREE.Vector3(0, 0, -len)); // vertex 5
  13. barnGeometry.vertices.push(new THREE.Vector3(w, 0, -len)); // vertex 6
  14. barnGeometry.vertices.push(new THREE.Vector3(w, h, -len)); // vertex 7
  15. barnGeometry.vertices.push(new THREE.Vector3(0, h, -len)); // vertex 8
  16. barnGeometry.vertices.push(new THREE.Vector3(0.5 * w, h + 0.5 * w, -len)); // 9
  17.  
  18. // now that we've got the vertices we need to define the faces.
  19. // front faces
  20. barnGeometry.faces.push(new THREE.Face3(0, 1, 2)); // 0
  21. barnGeometry.faces.push(new THREE.Face3(0, 2, 3));
  22. barnGeometry.faces.push(new THREE.Face3(3, 2, 4));
  23.  
  24. // back faces
  25. barnGeometry.faces.push(new THREE.Face3(5, 7, 6)); // 3
  26. barnGeometry.faces.push(new THREE.Face3(5, 8, 7));
  27. barnGeometry.faces.push(new THREE.Face3(7, 8, 9));
  28.  
  29. // roof faces.
  30. barnGeometry.faces.push(new THREE.Face3(3, 4, 8)); // 6
  31. barnGeometry.faces.push(new THREE.Face3(4, 9, 8));
  32. barnGeometry.faces.push(new THREE.Face3(2, 7, 9)); // 8
  33. barnGeometry.faces.push(new THREE.Face3(4, 2, 9));
  34.  
  35. // side faces
  36. barnGeometry.faces.push(new THREE.Face3(6, 2, 1)); // 10
  37. barnGeometry.faces.push(new THREE.Face3(7, 2, 6));
  38. barnGeometry.faces.push(new THREE.Face3(0, 3, 5)); // 12
  39. barnGeometry.faces.push(new THREE.Face3(3, 8, 5));
  40.  
  41. // floor faces
  42. barnGeometry.faces.push(new THREE.Face3(0, 5, 1)); // 14
  43. barnGeometry.faces.push(new THREE.Face3(5, 6, 1));
  44.  
  45. // calculate the normals for shading
  46. barnGeometry.computeFaceNormals();
  47. // barnGeometry.computeVertexNormals(true); only for "rounded" objects
  48.  
  49. return barnGeometry;
  50. }

The code creates a generic THREE.Geometry object, which is a collection of vertices and faces. Two attributes defined for every THREE.Geometry object are arrays named vertices and faces. The vertices array stores THREE.Vector3 objects that each hold the (x,y,z) coordinates for a single vertex. Each call to the push() method adds a new vertex onto the end of the array. You can think of the indices of the array as the numerical labels of the vertices. The faces array stores THREE.Face3 objects that represent a triangle built from three vertices, using the corresponding indices of the vertices array to specify which vertices to use. Each call to the push() method adds a new face onto the end of the faces array.

Each face, of course, has two sides, just like a coin. One of these is the front and the other is the back. The (default) technical definition of the front is the side where the vertices are in counter-clockwise order. Here, each face is defined from the front, and we use the convention that the front of each face corresponds to the outside of the barn.

Each face also has an associated vector that is perpendicular to the face, which mathematicians and computer graphics people call the normal vector. We'll learn that these are crucial in lighting computations.

Each vertex also has an associated vector which is the average of the normal vectors of all the faces that contain the vertex. These can also be used in lighting computations.

The last two lines of this function, one of which is commented out, compute these sets of vectors.