Previous Topic Tutorial Home Page Next Topic
GeoApplet1: A Spinning Cube

This applet constructs a spinning cube to fit in the view window. It illustrates how to import a geometry, manipulate it, and view it with a camera.

import com.ms.dxmedia.*; direct animation libraries
import java.awt.*;
for getting the applet dimension
import java.net.*;
for URLs

This class extends the DXMApplet class. The model you set in this class, by calling the setModel() method, is the model that will be displayed.
public class GeoApplet1 extends DXMApplet {

Set the model in the init() method.
public void init() {

Always call the super classes init first to ensure codeBase is set.
super.init() ;

Now set the model.
setModel (new GeoModel(this));
}
}

This class extends the Model class. The createModel method in this class is where you construct your animation.
class GeoModel extends Model {

Get the size of the applet in the constructor, and stores it in the member variables.
GeoModel(DXMApplet dxma) {

Get the size of the applet.
Dimension dim = dxma.getSize();

The base unit of measure for DirectAnimation is the meter. Convert the size into meters by multiplying it with the pixelBvr.
_halfWidthNum = mul(toBvr(dim.width*0.5),pixelBvr);
_halfHeightNum = mul(toBvr(dim.height*0.5),pixelBvr);
}

This function scales the geometry uniformly to fit in the unit box and centers it at the origin. The bounding box of the resulting geometry will be -0.5 to 0.5 in its largest dimension.
GeometryBvr mapToCenteredUnitBox(GeometryBvr geo) {

Find the extent and the center of the geometry.
Bbox3Bvr bbx3 = geo.boundingBox();
Point3Bvr minPt3 = bbx3.getMin();
Point3Bvr maxPt3 = bbx3.getMax();

Vector3Bvr extVec3 = sub(maxPt3, minPt3);
Point3Bvr centerPt3 = add(minPt3, extVec3.div(toBvr(2)));

NumberBvr maxExtNum = max(extVec3.getX(),
max(extVec3.getY(),
extVec3.getZ()));

Move the object to the origin, and resize it. Translate takes effect before scale is how compose works.
Transform3Bvr normalizingXf3 =
compose(scale3(div(toBvr(1), maxExtNum)),
translate(sub(origin3, centerPt3)));

return geo.transform(normalizingXf3);
}

Create the animation in the createModel method.
public void createModel(BvrsToRun blist) {

Build up a URL to import relative to.
URL mediaBase = getImportBase();
URL geoBase = buildURL(mediaBase, "geometry/");

Import a cube, scale it to the unit cube and center it at the origin. The resulting cube has a bounding box of -0.5 to 0.5 in all 3 dimensions.
GeometryBvr geo = importGeometry(buildURL(geoBase, "cube.x"));
geo = mapToCenteredUnitBox(geo);

Spin the cube around the origin. Find the smaller of the halfWidth and halfHeight of the view window, and use it to scale the cube so that the rendered image for the cube will be about half the size of the viewport. The part of the cube that's exactly on the viewing plane (Z = 0) will be exactly half the size of the viewport, the part that's behind the plane will be smaller, and the part that's in front will be bigger.
NumberBvr minHalfExtNum = min(_halfWidthNum, _halfHeightNum);
geo = geo.transform(compose(scale3(minHalfExtNum),
compose(rotate(yVector3, localTime),
rotate(zVector3, mul(localTime, toBvr(1.3))))));

Make the color time-varying.
geo = geo.diffuseColor(colorHsl(mul(localTime, toBvr(0.3)),
toBvr(0.8), toBvr(0.6)));

The near plane should be bigger than the max Z (in this case, sqrt(2)*minHalfExtNum after the cube is scaled to fit half viewport) of the bounding box of the spinning cube, so the cube doesn't get clipped out. The projection point determines the amount of perspective you'll see. The farther away it is from the viewing plane, the less perspective will result. Here, it's set to 5 times the near plane.
NumberBvr maxZNum = mul(sqrt(toBvr(2)), minHalfExtNum);
NumberBvr projPointNum = mul(toBvr(5), maxZNum);
CameraBvr cam = perspectiveCamera(projPointNum, maxZNum);

Overlay the cube on top of the color image background, and get the image displayed.
setImage(overlay(union(geo, directionalLight).render(cam),
solidColorImage(blue)));
}

max: returns max(x, y)
public static NumberBvr max(NumberBvr x, NumberBvr y) {
return (NumberBvr) cond(gt(y, x), y, x);
}

min: returns min(x, y)
public static NumberBvr min(NumberBvr x, NumberBvr y) {
return (NumberBvr) cond(lt(y, x), y, x);
}

private NumberBvr _halfWidthNum, _halfHeightNum;
}

© 1998 Microsoft Corporation. All rights reserved. Terms of Use.

Previous Topic Tutorial Home Page Next Topic