//
/**
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 GeoModel1(this));
}
}
// This class extends the Model class. The createModel method in this class
// is where you construct your animation.
class GeoModel1 extends Model {
// Get the size of the applet in the constructor, and stores it in the
// member variables.
GeoModel1(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;
}
//