/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package automenta.spacenet.space.geom; import automenta.spacenet.space.*; import automenta.spacenet.var.scalar.DoubleVar; import automenta.spacenet.var.scalar.DoubleVar.IfDoubleChanges; import automenta.spacenet.var.vector.Quat; import automenta.spacenet.var.vector.Quat.IfQuatChanges; import automenta.spacenet.var.vector.V3; import automenta.spacenet.var.vector.V3.IfV3Changes; import com.ardor3d.bounding.BoundingSphere; import com.ardor3d.bounding.OrientedBoundingBox; import com.ardor3d.math.Vector3; import com.ardor3d.renderer.state.CullState; import com.ardor3d.scenegraph.Mesh; import com.ardor3d.scenegraph.Spatial; import com.ardor3d.scenegraph.shape.Sphere; import java.util.LinkedList; import java.util.List; /** * TODO rename to BoxSpace? * @author seh */ public class Box extends Space implements HasPosition3, HasScale3, WrapsMesh { Mesh shapeSpatial; private final V3 position; private final V3 scale; private final Quat ori; private IfV3Changes positionChange; private IfV3Changes scaleChange; private IfQuatChanges oriChange; private BoxShape currentShape; private DoubleVar aspectXY = new DoubleVar(0.0); private IfDoubleChanges aspectXYChange; private final Vector3 vA = new Vector3(); //for temporary calculations public Box scale(double d) { return scale(d, d, d); } public void move(Vector3 c) { move(c.getX(), c.getY(), c.getZ()); } public static enum BoxShape { Empty, Cubic, Spheroid } public Box(BoxShape b) { this(new V3(), new V3(1, 1, 1), new Quat(), b); } public Box(V3 position, V3 scale, Quat orientation, BoxShape shape) { super(); this.position = position; this.scale = scale; this.ori = orientation; setShape(shape); } @Override protected void afterAttached(Spatial newParent) { positionChange = position.add(new V3.IfV3Changes() { @Override public void onV3Changed(V3 v) { positionChanged(); } }); scaleChange = scale.add(new V3.IfV3Changes() { @Override public void onV3Changed(V3 v) { sizeChanged(); } }); oriChange = ori.add(new IfQuatChanges() { @Override public void onQuatChanged(Quat q) { oriChanged(); } }); aspectXYChange = getAspectXY().add(new DoubleVar.IfDoubleChanges() { @Override public void onDoubleChange(DoubleVar d) { aspectChanged(); } }); positionChanged(); sizeChanged(); oriChanged(); } @Override protected void beforeDetached(Spatial parent) { position.remove(positionChange); scale.remove(scaleChange); ori.remove(oriChange); aspectXY.remove(aspectXYChange); } protected void positionChanged() { setTranslation(position); } protected void sizeChanged() { setScale(scale); } protected void oriChanged() { setRotation(ori); } protected void aspectChanged() { sizeChanged(); } public void setShape(BoxShape shape) { if (this.currentShape == shape) { return; } if (shapeSpatial != null) { detachChild(shapeSpatial); } switch (shape) { case Empty: // //com.ardor3d.scenegraph.shape.Quad x = new com.ardor3d.scenegraph.shape.Quad("", 1.0, 1.0); // com.ardor3d.scenegraph.shape.Box x = new com.ardor3d.scenegraph.shape.Box(); // CullState cs = new CullState(); // cs.setCullFace(CullState.Face.FrontAndBack); // x.setRenderState(cs); // x.setModelBound(new OrientedBoundingBox()); // shapeSpatial = x; break; case Cubic: com.ardor3d.scenegraph.shape.Box b = new com.ardor3d.scenegraph.shape.Box(); b.setModelBound(new OrientedBoundingBox()); shapeSpatial = b; break; case Spheroid: Sphere s = new Sphere("", 12, 12, 0.5); s.setModelBound(new BoundingSphere()); shapeSpatial = s; break; } this.currentShape = shape; CullState cs = new CullState(); cs.setCullFace(CullState.Face.None); setRenderState(cs); if (shapeSpatial != null) { attachChild(shapeSpatial); } } public Box move(double px, double py, double pz) { position.set(px, py, pz); return this; } public Box scale(double sx, double sy, double sz) { scale.set(sx, sy, sz); return this; } public Box span(double ulX, double ulY, double brX, double brY) { double w = Math.abs(brX - ulX); double h = Math.abs(brY - ulY); double cx = 0.5 * (ulX + brX); double cy = 0.5 * (ulY + brY); move(cx, cy, 0); scale(w, h, getSize().getZ()); return this; } public Box moveDZ(double dz) { return move(getPosition().getX(), getPosition().getY(), getPosition().getZ() + dz); } public Box rotate(double heading, double attitude, double bank) { ori.set(heading, attitude, bank); return this; } @Override public V3 getPosition() { return position; } @Override public V3 getScale() { return scale; } @Override @Deprecated public V3 getSize() { return scale; } public Quat getOrientation() { return ori; } @Override public void removeAll() { List<Spatial> c = new LinkedList(getChildren()); c.remove(shapeSpatial); for (Spatial s : c) { remove(s); } } public Box spanZ(double zStart, double zStop) { scale(getSize().getX(), getSize().getY(), Math.abs(zStop - zStart)); move(getPosition().getX(), getPosition().getY(), 0.5 * (zStop + zStart)); return this; } /** makes the box face a vector */ public Box face(double x, double y, double z) { Vector3 up = new Vector3(0, 1, 0); getOrientation().lookAt(new Vector3(x, y, z), up); return this; } public Box aspectXY(double newAspectXY) { getAspectXY().set(newAspectXY); return this; } public DoubleVar getAspectXY() { return aspectXY; } @Override public void updateWorldTransform(boolean recurse) { super.updateWorldTransform(recurse); //TODO alX and alY applyAspectXY(((Vector3) getWorldScale()), ((Vector3) getWorldTranslation()), getWorldRotation(), getAspectXY().d(), 0, 0, vA); } public Mesh getWrappedMesh() { return shapeSpatial; } }