Lab 4: Distance Control
/*
* Lab exercise 4.0
* CSc 474, Computer Graphics
* Copyright 2002 Chris Buckalew
*
* This lab gives you the code to do the simple 1-D Bezier that we
* used as an example in class, using 10 steps to go from one end to
* the other.
*
* 1) Create an array and evaluate and store many points along the curve,
* along with the t values and the total distance
traveled. Start out
* with 20 steps so you can compare the results with
what we did in class.
* Make sure that D(1.0) = 25 for this curve.
*
* 2) Create another array to store the t values for 10 equal steps
along
* the curve. Compute these steps by just searching
out the bracketing
* values for the desired distance and picking the
nearest. To display
* the motion, use the frame number as an index into
this array, pull
* out the t value stored there, and plug that value
into the curve.
* Before you go on, make sure the motion looks like
equal steps.
*
* 3) Increase the quality of the motion by increasing the size of the
* distance table. See what size seems to give
good results without
* being too big.
*
* 4) Finally, increase the number of steps in the animation from 10
to 100
* in the same length of time. You'll likely
also have to increase the
* distance table size as well to give smooth results.
*
*
*------------------------------------------------------------*/
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import java.io.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.*;
import java.awt.Font;
import com.sun.j3d.utils.behaviors.mouse.*;
public class DistanceControlLab extends Applet
implements ActionListener {
private Timer animControl;
private int frame, startFrame, endFrame, increment;
static Transform3D tempTrans;
private TransformGroup cubeTrans;
public DistanceControlLab() {
setLayout(new BorderLayout());
GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
Canvas3D c = new Canvas3D(config);
add("Center", c);
// Create a simple scene and attach it to
the virtual universe
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
tempTrans = new Transform3D();
frame = 0;
startFrame = 0;
endFrame = 10;
increment = 1;
animControl = new Timer(150, this);
animControl.start();
// This will move the ViewPlatform back a
bit so the
// objects in
the scene can be viewed.
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
private BranchGroup createSceneGraph() {
// Create the root of the branch graph
BranchGroup objRoot = new BranchGroup();
// Create light source
// first bound its influence
BoundingSphere bounds = new BoundingSphere(new
Point3d(0.0,0.0,0.0),100.0);
// now make the light itself
DirectionalLight light = new DirectionalLight(new
Color3f(1.0f, 1.0f, 1.0f),
new Vector3f( 0f,0f,-1f));
light.setInfluencingBounds(bounds);
objRoot.addChild(light);
// make the transform that moves the whole
model
TransformGroup modelTrans = new TransformGroup();
Transform3D trans = new Transform3D();
// initially move it away from camera
trans.setTranslation(new Vector3d(0d, 0d,
-10.0d));
// and shrink everything so it fits in field
of view
trans.setScale(new Vector3d(0.3d, 0.3d, 0.3d));
modelTrans.setTransform(trans);
// necessary so mouse movements can read and
change transform
modelTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
modelTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
// Create the rotate behavior node
MouseRotate modelRot = new MouseRotate();
modelRot.setTransformGroup(modelTrans);
modelTrans.addChild(modelRot);
modelRot.setSchedulingBounds(bounds);
// Create the zoom behavior node
MouseZoom modelZoom = new MouseZoom();
modelZoom.setTransformGroup(modelTrans);
modelTrans.addChild(modelZoom);
modelZoom.setSchedulingBounds(bounds);
// Create the translate behavior node
MouseTranslate modelTranslate = new MouseTranslate();
modelTranslate.setTransformGroup(modelTrans);
modelTrans.addChild(modelTranslate);
modelTranslate.setSchedulingBounds(bounds);
modelTrans.addChild(generateLinearCube());
objRoot.addChild(modelTrans);
return objRoot;
}
public void actionPerformed(ActionEvent e)
{
// This function is called for each frame
of animation
if ((Timer)e.getSource() == animControl) {
double t = (double) (frame
- startFrame) / (endFrame - startFrame);
//this implements linear
interpolation on the translation
double x, y, z;
x = (1-t)*(1-t)*-10.0 +
2.0*t*(1.0-t)*20 + t*t*10.0;
y = 0.0;
z = 0.0;
tempTrans.setTranslation(new
Vector3d(x, y, z));
cubeTrans.setTransform(tempTrans);
if (frame == endFrame) increment
= -1;
else if (frame == startFrame)
increment = 1;
frame = frame + increment;
}
}
private TransformGroup generateLinearCube()
{
// Generate the cube that moves linearly
cubeTrans = new TransformGroup();
cubeTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Transform3D trans = new Transform3D();
trans.setTranslation(new Vector3d(0.0d, 0.0d,
0.0d));
cubeTrans.setTransform(trans);
// Make the cube's color
Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
Appearance cubeApp = new Appearance();
cubeApp.setMaterial(new Material(black, black,
new Color3f(1.0f,1.0f,1.0f), black, 0f));
com.sun.j3d.utils.geometry.Box cube =
new com.sun.j3d.utils.geometry.Box(0.5f,
0.5f, 0.5f, cubeApp);
cubeTrans.addChild(cube);
return cubeTrans;
}
// The following allows DistanceControlLab to be run as an application
// as well as an applet
public static void main(String[] args) {
new MainFrame(new DistanceControlLab(), 500,500);
}
}