Page 7-7: The CS559 Framework Code (GraphicsTown)

Page 7-7: The CS559 Framework Code (GraphicsTown)

Box 1: Prelude to Graphics Town

For the remaining parts of the workbook (two exercises), you will work with some framework code we have created for this class. Learning to work with the Framework code is important practically (you will use it on all of the assignments from here on), but also pedagogically. In the real world, you often have to work with code that someone else wrote.

The framework code allows you to focus on creating graphics objects and defining their behavior (for animation). You don't need to worry about setting up a user interface, or the basic stuff of the world. It will give you "good enough" defaults that you can focus on the parts of the assignment you care about. For example, in this assignment, you can focus on making hierarchical objects. For Workbook 8 you can focus on making appearances (just wait).

The framework provides a "thin wrapper" around THREE.JS - you still program using THREE.JS, but you put your objects inside of wrapper objects, and define their behaviors as methods of these objects.

WARNING: The framework code will evolve over the next few assignments. In the next assignments you will be given newer versions that add new features.

The best documentation for the framework is the code itself, and the examples that we give you. The code is designed to be (reasonably) self-documenting. I am trying to structure the comments to automatically produce a documentation web (using jsdoc), but that only gets some of the information. The web of documentation is included in the workbook (start here).

For Spring 2019, the framework is being re-written from scratch. It is based on the version written in 2015 (which served graphics classes for 3 years).

The framework is really helpful for small exercises where we simply want you to make an object. It will let you put the object on the screen with simple lighting and a simple UI with very little code. However, the real point of the framework is to allow you make a world with lots of objects that are all defined independently. This will let you make much more complex worlds. It also lets you add objects that we give you (or even to share objects with other students).

The framework will allow us to build "Graphics Town" - where you will create a world with lots of "living" stuff in it. The last workbooks/assignments of the semester will ask you to do this. The new few assignments will ask you to make some objects and put them into simpler "worlds". However, the objects you create can be re-used later in later assignments.

If you're wondering where the "fancy features" of the framework are (shadows, multi-pass rendering, or other fancy things)... Just wait. As we learn things in class, the framework will be extended to support these kinds of things.

Box 2: Modern JavaScript

Learning about features of "modern" JavaScript is a learning goal of this assignment.

The framework code uses "modern" JavaScript. That includes modules and classes. We've actually had some of that in prior assignments, but this time you will see more of it. You will not be able to avoid writing a class or figuring out how to export from a module. Fortunately, we will provide a lot of examples, so you can always do things by modifying something we've given you to start with. However, we do recommend that you take some time to actually understand what is going on with the code.

If you want to learn about JavaScript classes (and other modern features), most up-to-date books discuss it. See the course JavaScript page for suggestions. One specific recommendation: Exploring JavaScript Chapter 15 has a nice introduction before it starts a deep-dive into some gory details and tricks to do fancy stuff.

Box 3: Getting Started with a simple example

Here's the spinning cube example (from page 3 and the previous workbook and lecture). This time in the framework:

Everything is pretty much the default - except that I made the groundplane gray, not its usual green, since the cube is green. We got some lighting, a camera, orbit controls, an animation loop, and some other stuff "for free". It may not be exactly what we want, but we get a reasonable default and can always change things.

The code is in 7-simplespin.js. I'll include the key parts here:

// define a special kind of cube that spins
class SpinCube extends GrCube {
    constructor() {
        super({color:"green"});
    }
    advance(ms,daytime) {
        // this used to be .01 per step
        // however, we want to advance things based on the frame rate
        // if we get 60fps, that's 16 miliseconds
        this.objects[0].rotation.x += 0.01 * ms / 16;
        this.objects[0].rotation.y += 0.01 * ms / 16;
    }
}

function go() {
    let world = new GrWorld({groundplanecolor:"gray",
                             where:document.getElementById("simplespin")});

    let cube = new SpinCube();
    world.add(cube);
    // we need to place the cube above the ground
    cube.objects[0].position.y = 1;

    world.go();
}
onWindowOnload(go);

Walking through this...

  1. The main thing we do is define a new object type, a spinning cube. We create a class SpinCube that subclasses the built-in Cube type. The super call in the constructor runs the constructor of the base class (giving it an option that tells us the color).
  2. The main thing we do in the new object is to define its behavior by overriding the advance method. The advance method gets called every frame and tells the object to update itself. The first parameter (ms) gives an estimate of how long it has been since the last redraw. This way we can adapt the speed in case our frame rate drops, rather than assuming our computer keeps up with 60 frames per second (16 milliseconds per frame).
  3. Inside the advance method we do the same angle increments we did in the original program. Two things to note:
    • First, since we need access to the THREE Object3D, we have to look inside the list of objects that are "owned" by the SpinCube GrObject. I took advantage of the fact that I know that a GrCube has only one Object3D.
    • Second, notice how I scale the spin rate by the time.
  4. In the main program (the function go that is called on window load), all we need to do is:
    • create the world (making the new GrWorld)
    • make objects and add them to the world
    • start the animation loop
    • We could do more (add more objects, adjust things), but we don't have to. We get reasonable defaults.
  5. When I create the GrWorld I tell it where to put the DOM element that THREE creates for us. Here, I find the simplespin html element (it's a div). If I don't tell GrWorld where to put the element, it will just stick it at the end of the page.
  6. Since there is a ground, I needed to raise the cube above the ground. Again, this means accessing the internal Object3D.

For a simple example like this one, the framework isn't that much easier than just writing the code from scratch using THREE.js directly. It does save me from having to remember to turn the lights on and point the camera the right way.

In the simple example, I re-used a basic object (a cube). Just as when we use THREE directly, usually we will make more interesting objects. You'll see that on the next pages.

Box 4: Another Simple Example

The first example showed how to make a simple animation. Here is a different example, inspired by the EulerToy demo on page 2. This time, rather than animating the cube, we control it with sliders. The nice thing: the framework will make the sliders for us!

The code for this one is in 7-simpleslider.js. This defines a different subclass of cube:

class RotCube extends GrCube {
    constructor() {
        super({color:"green"},
            [ ["X",-Math.PI/2,Math.PI/2,0],
              ["Y",-Math.PI/2,Math.PI/2,0],
              ["Z",-Math.PI/2,Math.PI/2,0]
            ]);
        }
        update(vec) {
            this.objects[0].rotation.x = vec[0];
            this.objects[0].rotation.y = vec[1];
            this.objects[0].rotation.z = vec[2];
        }
}

The big difference here is that when I created the cube subclass, I defined a set of "parameters" (the X, Y, Z) for rotation. They each range from to . Since these are defined (with a name, range, and default value), the AutoUI code can make a control panel for it. Also notice how rather than defining an advance method, I provided an update method that takes the slider values as its argument.

The main body of the code created the UI - but all this required was telling AutoUI to do its job.

Again, this is a really simple case where I extend the cube. Under normal circumstances, I would extend the base class GrObject and populate it with THREE objects myself.

Box 5: The Framework Code Ground Rules

Some ground rules about the Framework Code:

  1. You are welcome to (required to!) read the framework code. The code is meant to be somewhat self-documenting (with comments and type declarations).
  2. Please avoid changing the framework code. Do not edit the files in the Framework directory unless we give you explicit instructions to do so. If you feel like you want to make your own version of something, copy the code into your own file and make changes. (be sure to give the code proper attribution)
  3. If you find a bug in the framework code, please notify the instructors by Piazza.
  4. We appreciate suggestions on how to make it better - this includes things we could document better, or functionality that we might want to add. The framework code will most likely be used by many classes, so suggestions may help many future students.
  5. You are strongly encouraged to use the framework code. Learning to work within someone else's (imperfect) code is part of the learning goals of the assignments. However, if you choose to implement things yourself, you will be responsible for providing all of the functionality that the framework provides.

Summary: The Graphics Town Framework Code

The main way to learn about the Framework code is to read the code and its documentation. But the most important thing to do is to try it out and do things with it. You'll get to do that in the next two exercises.

First, we'll go make Graphics Park on the next page.