Friday, September 13, 2013

What Did That Set-Up Code Do? (part 2)

.... Continued from part 1
06 var geometry = new THREE.CubeGeometry(1,1,1);
06 To see anything in our newly created scene, we have to create some game objects.    Again, we use the 'var' keyword and pick a name for our object, in this case it is called 'geometry'.  We then fill it with '= new' and a call to THREE.CubeGeometry(1,1,1).  Have you noticed a pattern yet?  The pattern is:
 var name = new THREE.something();  -  (where 'name' is the name you pick, and '.something' is the name of the helper function you are calling from the Three.js graphics library.
Get used to this pattern because you will see a LOT of instances of it throughout our code, especially the THREE.something part.  Moving on, '.CubeGeometry()' is a function of the Three.js library that creates a cube or box shape.  The 3 parameters inside the parentheses() give the dimensions of the cube in order: (width, height,depth).  So to create a box or cube with 1 unit of length on all sides, you would type (1,1,1) and that is indeed what we have done in the proceeding code.  Just for example, you could make a really tall box by typing (1,20,1) because remember that the second number represents how high the cube/box is.  One thing to note: we have created the shape or blueprint of a cube, but not the entire cube yet.  If you try to render 'geometry', it won't show anything because it doesn't have a skin or outer-material yet.  

07 var material = new THREE.MeshBasicMaterial({ color: 'rgb(0,255,0)' });
07 Now we create a skin or outer-material for our 'geometry' (the cube we just created).  Using our famous pattern, we type the 'var' keyword followed by our name for the material, in this case 'material', and fill it with '= new' and a call to THREE.MeshBasicMaterial();  The Three.js library offers us different kinds of materials for different texture and lighting situations and in the future we will explore these different materials.  But to keep things simple for now, we will just stick to 'MeshBasicMaterial'.  If you are new to 3D game development, you might be wondering about that word 'Mesh'.  Think of 'Mesh' as a mesh or combination of a geometric shape and its skin.  A wooden crate would be a mesh of a Cube geometry and a dull, wood material.  A crystal ball would be a mesh of a Sphere geometry and a glassy, transparent material.  A money safe would be a mesh of a Cube geometry and a metallic, slightly reflective material, etc.  Meshes could also be the combination of a really complex geometric shape, like the blueprint for a car or a human, and their skins (metal/rubber/plastic for the car, and complex fleshy/hairy material for the human).  But we will stick to basic shapes and their materials for now.
Next you'll notice that the THREE.MeshBasicMaterial() has parameters inside its parentheses.  You'll also notice that this is the first time we've seen the curly braces { } used.  The curly braces { } help to isolate a block of code from other statements.  In this case we wrap the { } tightly around the color: 'rgb(0,255,0)' part.  This is needed because the parameters require what is known as a 'key: value' pair in JavaScript. The correct language syntax is
key: 'value'
The key is a property you would like to set.  In this case it is the color property so we type color:  , then we have to assign a value to this color property and whatever you choose must be enclosed in single quotes ' '. In our example, we fill the color property with an RGB code.  RGB stands for Red, Green, and Blue.  So we write rgb(red,green,blue) where red, green, and blue must be a number between 0 and 255  (0 being the darkest for that color, and 255 being the brightest).  So if we have 'rgb(0,255,0)' for our value, you guessed it - we get the brightest green, which is indeed the color of our example cube.  One of our first experiments in the near future will be changing these numbers and seeing what happens to the color.

08 var cube = new THREE.Mesh(geometry, material);
08 Because we know what a mesh is now, this line of code should be pretty self-explanatory.   But just in case: We use our trusty pattern of the 'var' keyword, then a user-defined name for the completed mesh, in this case 'cube', followed by '= new'  and then fill it with a call to THREE.Mesh().  THREE.Mesh takes two parameters inside its parentheses - the name you chose for the geometry blueprint, and the name you chose for the skin material.  So in our case we type (geometry, material).  Under the hood, this function magically wraps the skin (material) around the object blueprint (geometry) to create a finished product.  And since we made a material of green skin, that is what we get; a green-skinned cube.

09 scene.add(cube);
09 Think of the scene object as the world in which the players and game objects exist and move around.  To see our newly-minted beautiful green cube, we need to make it exist in the game world.  So we add it to the scene.  We don't need the 'var' keyword or the 'new' keyword now because we already created a scene object on line 01.  We now call a function on itself - named .add(finishedObject) where finishedObject is the mesh that was just created.  Since we named it 'cube', we type scene.add(cube);  Our green cube now populates the scene world.  I can imagine on the outskirts of town a sign reading: 
Welcome to the town of scene
population: 1   (ha ha) :-)

10 camera.position.z = 5;
10 Remember that the camera is like our eyes.  Now that we've created a camera, we can move it around and rotate it all around to be able to look at the scene world.  We are just going to move it for now, because rotating is a little more involved (but we WILL do that, I promise).  The camera object has a function called position so if we want to move our camera around we type camera.position - but wait, the program needs more information than that.  Position can be described as x, y, and z coordinates.  Positive x goes to your right, negative x goes to your left, positive y goes up in the air, negative y goes down through the ground, positive z goes into your computer screen and negative z goes behind you.  What line 10 does is move the camera backwards 5 units (behind you) along the z axis.  We type camera.position.z and then the = sign tells the program we are about to fill 'z' with a value, and that value is 5.  To move the camera left we would type 
camera.position.x = -5;  
Remember that negative x goes left.
Why is this line 10 even here?  Well, when you add objects such as cubes, players, cameras, lights, etc, to your scene world, by default it places them in the middle of the world which is x=0, y=0, and z=0.  Problem with that is if our camera is already at that spot and we then add our new green cube, it will be right on top of us and we won't be able to see anything (remember the discussion about 'near clipping' planes earlier?).  So this line of code picks up the camera and moves it back 5 paces so we can get a better view of our green cube, which is at the center of the world (yeah, the cube can be kind of selfish).

11 renderer.render(scene, camera);
11 Now with this line, the magic of Three.js and WebGL happens.  If you didn't have this line, nothing would be displayed.  We use our renderer that we created earlier on line 03 and call a function on itself named render (the word render means draw the graphics).  So we type renderer.render().  The function render actually colors and draws the pixels of your world to your display screen.  Notice that this function takes 2 parameters - the scene that you wish to draw, and the camera that you want to view it with.  Since we named our scene 'scene' and our camera 'camera' (I know, real original right?), we type (scene, camera) inside the parentheses.  Don't forget the semicolon (;) after every statement!

Whew - we made it through the explanation!  If you've used any kind of 3D programs before like SketchUp, 3DS Max, Blender, Maya, etc., most of these concepts of camera, mesh, position and rendering should be familiar.  If you are totally new to all this, hang in there!  Soon we will start tinkering with small bits of code and you will immediately see what happens to the display, and therefore gain a better understanding of 3D game programming and the Three.js library.

In the next post, we will rotate and animate the green cube so that it shows us its true 3D depth.  You won't want to miss this part!  Till next time...