/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package automenta.spacenet.space.geom;
import automenta.spacenet.space.Space;
import automenta.spacenet.space.WrapsMesh;
import automenta.spacenet.var.scalar.DoubleVar;
import automenta.spacenet.var.scalar.DoubleVar.IfDoubleChanges;
import automenta.spacenet.var.vector.V3;
import automenta.spacenet.var.vector.V3.IfV3Changes;
import com.ardor3d.bounding.OrientedBoundingBox;
import com.ardor3d.math.Vector3;
import com.ardor3d.scenegraph.Line;
import com.ardor3d.scenegraph.Mesh;
import com.ardor3d.scenegraph.Spatial;
import com.ardor3d.scenegraph.shape.Extrusion;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
*
* @author seh
*/
public class Line3D extends Space implements WrapsMesh {
private final V3 a;
private final V3 b;
private final int radialSamples;
private final DoubleVar radius;
private Extrusion extrusion;
final static Vector3 up = new Vector3(0, 1, 0);
private List<Vector3> points;
private List<Vector3> localPoints = new LinkedList();
private IfV3Changes pointChanges;
private IfDoubleChanges radChanges;
private Line shape;
private V3 center = new V3();
private boolean extrusionNeedsUpdate;
public Line3D(V3 a, V3 b, int radialSamples, double radius) {
super();
this.a = a;
this.b = b;
this.radialSamples = radialSamples;
this.radius = new DoubleVar(radius);
this.points = Arrays.asList(new Vector3[]{a, b});
}
@Override
protected void afterAttached(Spatial parent) {
super.afterAttached(parent);
pointChanges = new IfV3Changes() {
@Override public void onV3Changed(V3 v) {
needsToUpdateExtrusion();
}
};
radChanges = getRadius().add(new IfDoubleChanges() {
@Override public void onDoubleChange(DoubleVar d) {
updateShape();
needsToUpdateExtrusion();
}
});
a.add(pointChanges);
b.add(pointChanges);
updateExtrusion();
}
protected void needsToUpdateExtrusion() {
extrusionNeedsUpdate = true;
}
@Override
protected void beforeDetached(Spatial previousParent) {
a.remove(pointChanges);
b.remove(pointChanges);
pointChanges = null;
super.beforeDetached(previousParent);
}
private void updateShape() {
shape = new Line();
shape.appendCircle(getRadius().d(), 0, 0, radialSamples, false);
}
@Override
public void updateControllers(double time) {
super.updateControllers(time);
if (extrusionNeedsUpdate) {
extrusionNeedsUpdate = false;
updateExtrusion();
}
}
protected void updateExtrusion() {
if (shape == null) {
updateShape();
}
center.set(a);
center.addLocal(b);
center.multiplyLocal(0.5);
setTranslation(center);
localPoints.clear();
for (Vector3 v : points) {
Vector3 v2 = new Vector3(v);
v2.subtractLocal(center);
localPoints.add(v2);
}
if (extrusion == null) {
extrusion = new Extrusion("", shape, localPoints, up);
extrusion.setModelBound(new OrientedBoundingBox());
attachChild(extrusion);
} else {
extrusion.updateGeometry(shape, localPoints, up);
extrusion.updateModelBound();
}
}
public DoubleVar getRadius() {
return radius;
}
public double getLength() {
return a.distance(b);
}
@Override
public Mesh getWrappedMesh() {
return extrusion;
}
}