summaryrefslogtreecommitdiff
path: root/src/tesseract/objects/ChainLink2.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/tesseract/objects/ChainLink2.java')
-rw-r--r--src/tesseract/objects/ChainLink2.java214
1 files changed, 214 insertions, 0 deletions
diff --git a/src/tesseract/objects/ChainLink2.java b/src/tesseract/objects/ChainLink2.java
new file mode 100644
index 0000000..e98280b
--- /dev/null
+++ b/src/tesseract/objects/ChainLink2.java
@@ -0,0 +1,214 @@
+package tesseract.objects;
+
+import javax.media.j3d.Appearance;
+import javax.media.j3d.IndexedQuadArray;
+import javax.media.j3d.Material;
+import javax.media.j3d.PointArray;
+import javax.media.j3d.Shape3D;
+import javax.media.j3d.Transform3D;
+import javax.vecmath.Point3f;
+import javax.vecmath.Vector3f;
+
+import com.sun.j3d.utils.geometry.GeometryInfo;
+import com.sun.j3d.utils.geometry.NormalGenerator;
+
+/**
+ * Chain link object.
+ *
+ * @author Jesse Morgan
+ */
+public class ChainLink2 extends PhysicalObject {
+ /**
+ * Default link length.
+ */
+ public static final float DEFAULT_LENGTH = 0.15f;
+
+ /**
+ * Default ratio of length to width.
+ */
+ public static final float DEFAULT_WIDTH_RATIO = 0.75f;
+
+ /**
+ * Default ratio of length to link diameter.
+ */
+ public static final float DEFAULT_DIAMETER_RATIO = 0.25f;
+
+ /**
+ * Number of slices to render.
+ */
+ protected static final int SLICE_COUNT = 40;
+
+ /**
+ * Number of points in the circumference of the circle.
+ */
+ protected static final int SLICE_DIVISIONS = 16;
+
+ /**
+ * Construct a chain link.
+ *
+ * @param thePosition Position.
+ * @param mass Mass.
+ */
+ public ChainLink2(final Vector3f thePosition, final float mass) {
+ this(thePosition, mass, DEFAULT_LENGTH * DEFAULT_DIAMETER_RATIO,
+ DEFAULT_LENGTH, DEFAULT_LENGTH * DEFAULT_WIDTH_RATIO);
+ }
+
+ /**
+ * Construct a chain link.
+ *
+ * @param thePosition Position.
+ * @param mass Mass.
+ * @param length Link length.
+ * Width and diameter are created from the default ratios.
+ */
+ public ChainLink2(final Vector3f thePosition, final float mass,
+ final float length) {
+ this(thePosition, mass, length * DEFAULT_DIAMETER_RATIO,
+ length, length * DEFAULT_WIDTH_RATIO);
+ }
+
+ /**
+ * Construct a Chain Link.
+ *
+ * @param thePosition Position.
+ * @param mass Mass.
+ * @param diameter Diameter of link.
+ * @param length Length of link.
+ * @param width Width of link.
+ */
+ public ChainLink2(final Vector3f thePosition, final float mass,
+ final float diameter, final float length, final float width) {
+ super(thePosition, mass);
+
+ setShape(createShape(SLICE_COUNT, SLICE_DIVISIONS,
+ diameter, length, width));
+ }
+
+ /**
+ * Create the shape.
+ *
+ * @param sliceCount Number of slices.
+ * @param sliceDivisions Number of divisions.
+ * @param diameter Diameter.
+ * @param length Length.
+ * @param width Width.
+ *
+ * @return Chainlink shape.
+ */
+ public Shape3D createShape(final int sliceCount, final int sliceDivisions,
+ final float diameter, final float length, final float width) {
+
+ Point3f[][] coords = new Point3f[sliceCount][sliceDivisions];
+
+ // Design the first circle
+ double theta = 2 * Math.PI / sliceDivisions;
+ float radius = diameter / 2.0f;
+
+ // Translate the coords to the correct place.
+ Transform3D t3d = new Transform3D();
+
+ for (int i = 0; i < sliceDivisions; i++) {
+ coords[0][i] = new Point3f(
+ 0f,
+ (float) (radius * Math.cos(i * theta)),
+ (float) (radius * Math.sin(i * theta)));
+
+ // Move to the right place.
+ //t3d.transform(coords[0][i]);
+ }
+
+ // Create the arc
+ radius = (width - radius) / 2.0f;
+
+ t3d.setIdentity();
+ t3d.setTranslation(new Vector3f(0, -radius, 0));
+
+ Transform3D tmp = new Transform3D();
+ tmp.rotZ(Math.PI / (sliceCount / 2.0 - 1));
+ t3d.mul(tmp);
+ tmp.setIdentity();
+ //new Vector3f(-(length / 2.0f - radius), -width / 2.0f, 0));
+ tmp.setTranslation(new Vector3f(0, radius, 0));
+ t3d.mul(tmp);
+
+ for (int j = 1; j < sliceCount / 2; j++) {
+ for (int i = 0; i < sliceDivisions; i++) {
+ coords[j][i] = new Point3f(coords[j - 1][i]);
+ t3d.transform(coords[j][i]);
+ }
+ }
+
+ // Next build second half...
+ t3d.setIdentity();
+ t3d.setTranslation(new Vector3f(
+ -(length / 2.0f - radius / 2.0f),
+ (width - diameter / 2.0f) / 2.0f,
+ 0));
+
+ Transform3D rot = new Transform3D();
+ rot.rotY(Math.PI);
+ tmp.setIdentity();
+ tmp.rotX(Math.PI);
+ rot.mul(tmp);
+ for (int j = 0; j < sliceCount / 2; j++) {
+ for (int i = 0; i < sliceDivisions; i++) {
+ t3d.transform(coords[j][i]);
+
+ coords[j + sliceCount / 2][i] = new Point3f(coords[j][i]);
+ rot.transform(coords[j + sliceCount / 2][i]);
+ }
+ }
+
+
+ // Build Geoemetry
+ IndexedQuadArray geometry = new IndexedQuadArray(
+ sliceCount * sliceDivisions,
+ PointArray.COORDINATES,
+ 4 * sliceDivisions * sliceCount);
+
+ // TODO: Remove /2
+ for (int i = 0; i < sliceCount; i++) {
+ geometry.setCoordinates(i * sliceDivisions, coords[i]);
+ }
+
+ int index = 0;
+ for (int j = 0; j < (sliceCount - 1); j++) {
+ for (int i = 0; i < sliceDivisions; i++) {
+ geometry.setCoordinateIndex(index++, j * sliceDivisions + i);
+ geometry.setCoordinateIndex(index++,
+ (j + 1) * sliceDivisions + i);
+ geometry.setCoordinateIndex(index++,
+ (j + 1) * sliceDivisions + (i + 1) % sliceDivisions);
+ geometry.setCoordinateIndex(index++,
+ j * sliceDivisions + (i + 1) % sliceDivisions);
+ }
+ }
+
+ for (int i = 0; i < sliceDivisions; i++) {
+ geometry.setCoordinateIndex(index++,
+ (sliceCount - 1) * sliceDivisions + i);
+ geometry.setCoordinateIndex(index++,
+ i);
+ geometry.setCoordinateIndex(index++,
+ (i + 1) % sliceDivisions);
+ geometry.setCoordinateIndex(index++,
+ (sliceCount - 1) * sliceDivisions
+ + (i + 1) % sliceDivisions);
+ }
+
+ GeometryInfo gInfo = new GeometryInfo(geometry);
+ gInfo.convertToIndexedTriangles();
+ new NormalGenerator().generateNormals(gInfo);
+
+ Shape3D shape = new Shape3D(gInfo.getGeometryArray());
+ Appearance app = new Appearance();
+ Material mat = new Material();
+ mat.setDiffuseColor(1, 0, 0);
+ app.setMaterial(mat);
+ shape.setAppearance(app);
+
+ return shape;
+ }
+
+}