Course Links

Resources

External

In this homework you will create a 3D world, and view it through the eyes of a person walking around in this world. We will get used to working with WebGL and Three.js, in addition to gaining experience with perspective cameras, 3D geometry, decomposing code into functions, and randomness. Randomness is very important in computer graphics, since it can give a realistic look to features that would otherwise be extremely time consuming to do by hand (hair, fur, snow, rain, grass, etc).

For the animation part, you may be best off waiting to start after the lab on Thursday, but building the scene can start right away.

For this assignment, you are welcome to work with a partner if you follow the pair-programming guidelines. Remember: If you choose to pair-program, turn in your code under ONE partners name, and clearly state the names in the pair as a comment at the top of your code. (The other partner may turn in a short text file with their partner's name and any personal reflections.)

Pyramid function

Begin with the code from Lab 6 that creates a pyramid. The first step is to put the creation of this pyramid inside a function.

function makePyramid(cx,cy,cz,size) {...}

This function should add the pyramid to the scene (it does not necessarily need to return anything). The first three parameters are the coordinates of the center of the bottom face of the pyramid, and the fourth is the size (length of a side, and distance from the center point to the peak). If you wish, you may split size into two values (height & side) so that you can have short wide pyramids and tall skinny pyramids. You could also add an argument for the color of the pyramid.

A world of pyramids

Using your pyramid function, create several pyramids in a loop, using the Math.random() function to determine their positions and size within some reasonable range. An example is shown below, and also more information about how to adjust the raw output of the random number generator:

var r = Math.random();                    // returns a number in [0,1)
var s = Math.ceil(Math.random()*10)+10;   // integer between 11 and 20

More about generating random numbers in JavaScript

Test our your method to make sure it is working correctly. It's okay if the pyramids overlap.

Create the ground

To make this world more realistic, we will create a plane, and then adjust the position of all the pyramids so that they sit on the plane. In Three.js, there is a built-in function for creating a plane, which works like this:

// arguments are width along the x-axis, then width along y-axis
var geometry = new THREE.PlaneGeometry( 50, 50 );
var material = new THREE.MeshBasicMaterial({color: 0xffff00, side: THREE.DoubleSide});
var plane = new THREE.Mesh( geometry, material );
scene.add( plane );
 

PlaneGeometry Documentation

By default this plane is created in the xy plane, and the camera is looking down on it from somewhere high on the z axis. If we want our animation to look like we're moving around on the ground, we need to move the camera close to the ground plane and rotate it so it is looking along either the x or y axis. (Which axis should we rotate it about? What angle should we use? -- answer) If you try to move and rotate the camera all at once but get it wrong, you may see nothing at all in your view. If that happens, back up to a version where you see something, and make small changes in the direction you think you should be moving. By looking at how the camera's view changes with a small adjustment, you can decide if a bigger change is warranted.

There's another problem, with the pyramids. If you followed the instructions in the lab, your pyramid's base will be in the X plane. This means that the pyramids won't sit on the ground plane; instead they'll seem balanced on edge. You can solve this either by changing all the pyramid vertex coordinates so that the base is in the XY plane (this sounds like a lot of work!) or you can apply a rotation each pyramid as well. Either way, the pyramids should sit with their bases on the ground plane. (Hint: one of the position coordinates will be 0. Which one?) The height of the camera above the plane should be less than the height of the pyramids, so that it looks like the viewer is standing among them.

(Another alternative to the above would have been to leave the camera where it was and rotate the plane towards it, matching the base of the pyramids. But this seems less intuitive because it is natural to move through our landscape in x and y, and leave z as a vertical dimension.)

Test out some different camera positions (especially moving the camera up and down a bit) to make sure your plane is working and everything looks all right. Make sure that the pyramids sit directly on the plane. For now, we'll consider a finite plane which will define the world. An example image is shown below. The boundaries of your plane might not be visible from every camera angle. (If you like, putting a line of pyramids at the edge of the plane will give your scene a more natural edge.)

plane

Complete a suitable scene according to the directions above to satisfy the bronze level criterion.

Walking around

Animation: now for the animation. Using a rendering loop similar to the one below (see Lab 7), move the camera around the scene to simulate a person walking around your world.

function render() {
    // things that change (camera motions) go here:
    // FILL IN

    // here we draw the scene and set up the next frame:
    renderer.render(scene, camera);
    requestAnimationFrame( render );
}

Specifically, use both rotation and translation to make the observer move randomly. Motion should alternate every few seconds between rotating and translating, using a counter. The camera's z-coordinate (height) shouldn't change since it is supposed to be moving around the xy plane). It's okay if the observer walks through some pyramids. When moving, the camera should point in the direction of forward motion (as if you are walking forward). For a silver solution, it suffices to implement a fixed route. The animation may stop after at least ten seconds including a total of four or more distinct motions, or you can design a circuit that repeats forever. Because you are using randomness, the scene should be different each time you load the page, but the route may be the same unless you implement the randomiazation option below.

Extensions

For a gold solution, please choose one extension below.

Note: extra credit is possible for a combination of extensions or a very outstanding/realistic/creative submission (at instructor's discretion).

Submit

Submit your HTML file and a representative screenshot of your world (if you worked in a pair, only one person needs to submit, but both names should be in the header comment).

/* */