In this lab we will see how hierarchical models can be useful for creating nested movement. Homework 7 will build on the concepts from Labs 8 and 9.
Introduction
Fork a copy of the starter code and take a look at it. When you run the file, you should see something like this:
This cube will eventually become the lower part of a robotic arm.
Scale and Translate
First, we will scale this cube and translate it so that the end of the arm is at the origin (by default the center is at the origin). Fill in the question marks below to get a picture like the one below.
lowerArm.scale.set(?,?,?); // scale in the x,y,z directions lowerArm.position.x = ?; // translate in the x direction
Rotate the lower arm
Begin by applying a rotation directly to lowerArm itself. You will do this inside the rendering loop, incrementing the z rotation angle of the lowerArm by a small amount. You should end up with the lowerArm spinning about its origin, which is at the center of the object. That's not quite what we want!
Notice that at the top of our code there are two global variables named shoulder and elbow. These will be virtual objects that we can use to rotate the visible body parts around a pivot of our choice. When we apply a rotation to the shoulder variable it will move the entire arm, and when we rotate the elbow it will move just the lower arm portion.
Begin with elbow. Add the code below inside createWorld() to initialize the virtual object and add it to the scene. The last line replaces the line where we added lowerArm to the scene, so that it has elbow as its parent instead.
// Initialize the elbow and add it to the scene elbow = new THREE.Object3D(); scene.add(elbow); elbow.add(lowerArm); // replaces previous call to scene.add(lowerArm)
Finally, change the animation loop so that it is rotating elbow instead of lowerArm.
So far we have rearranged the hierarchy of the scene without making any changes to the visual result. We're still spinning around the center of the shape. Now it's time to take advantage of the new arrangement. Move the position of lowerArm by half the length you stretched it to, so that one of its ends is at the elbow. The arm segment should now appear to be rotating around its end.
Step 3: Adding the upper arm
Now let's add an upperArm to the scene, connected to a virtual shoulder. These will be arranged exactly like lowerArm and elbow, respectively. In the animation loop, give the shoulder a different update amount from the elbow so that they move independently. You should end up with something that looks a little like the arms of a crazy clock.
So far the two segments of the arm have been entirely separate. The last step is to put them into the same hierarchy, with the elbow attached to the shoulder as its parent. Change your program so that elbow is a child of shoulder instead of scene. How does that change the animation (if at all)? Next move the position of elbow so that it sits at the end of the upper arm that is opposite to the shoulder point. Our animation may be a little unrealistic for a robot arm (the two parts can pass through each other at times) but we've got the right sort of articulation.
Using the Keyboard
Instead of stopping with a continuous animation, we will explore user input as a different type of control. The goal of this step is to move the arm clockwise/counter-clockwise when the user presses the left/right arrow keys, and to move the lowerArm clockwise/counter-clockwise when the user presses the down/up arrow keys. For this purpose we will need another library, KeyboardState.js, which has already been added to the project.
To use it, uncomment the line that incorporates this script at the top of the file. (Just remove the <!-- and --> from the beginning and end of the line.) Also uncomment the creation of the global keyboard variable, the update() function, and the call to the update() function inside the rendering loop. Finally, instead of having the rotation code inside the rendering loop, move it to the appropriate place in the update function. Test it out with your keyboard! (Click on the display area of the window to send your keyboard input to the program.)
If you want finer control over the movement at each joint, you can use four key commands per joint to represent movement in either direction around two possible rotation axes. I recommend picking a cluster of nearby keys for each joint, like WASD or IJKL.
Finish Up
If you have enough time left, you can add a pair of rotating and grasping pincers at the end of the arm (for picking things up). This will involve two more modified cubes and another virtual object. See if you can figure out the necessary program additions based upon the examples so far.
When you are done, make sure that your programming partner(s) have a copy of your work by the end of the lab. Homework 7 will continue the concepts in this lab.