summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Morgan <jesse@jesterpm.net>2011-02-16 08:12:56 +0000
committerJesse Morgan <jesse@jesterpm.net>2011-02-16 08:12:56 +0000
commit350a482b32512191596daad55104beec98af9981 (patch)
tree34967e2dd86b18a78a3ea0f8316a502a1e8637d3
parent5e9f617bdfea01d0bd5e66daf7a5e55f8f94dbf0 (diff)
Added alden's code, moved his objects into the object class and made them extend physical object. Fixed a node selection problem in TesseractUI.
-rw-r--r--src/alden/CollidableObject.java62
-rw-r--r--src/alden/CollisionDetector.java204
-rw-r--r--src/alden/CollisionInfo.java13
-rw-r--r--src/tesseract/TesseractUI.java20
-rw-r--r--src/tesseract/objects/Box.java36
-rw-r--r--src/tesseract/objects/Circle.java55
-rw-r--r--src/tesseract/objects/Particle.java2
-rw-r--r--src/tesseract/objects/Polygon.java43
-rw-r--r--src/tesseract/objects/Sphere.java (renamed from src/alden/Sphere.java)14
9 files changed, 383 insertions, 66 deletions
diff --git a/src/alden/CollidableObject.java b/src/alden/CollidableObject.java
index f3e1ed9..eb3ff6a 100644
--- a/src/alden/CollidableObject.java
+++ b/src/alden/CollidableObject.java
@@ -45,7 +45,7 @@ public abstract class CollidableObject {
angularVelocity = new Vector3f();
torqueAccumulator = new Vector3f();
inverseInertiaTensor = new Matrix3f();
- coefficientOfRestitution = 0.65f;
+ coefficientOfRestitution = 0.75f;
penetrationCorrection = 1.05f;
dynamicFriction = 0.02f;
TG = new TransformGroup();
@@ -58,7 +58,7 @@ public abstract class CollidableObject {
protected void setShape(Node node) {
this.node = node;
TG.addChild(node);
- //TG.addChild(CollisionDetector.createShape(CollisionDetector.triangularize(node)));
+// TG.addChild(CollisionDetector.createShape(CollisionDetector.triangularize(node)));
}
public Group getGroup() {
@@ -79,6 +79,7 @@ public abstract class CollidableObject {
velocity.scaleAdd(duration, forceAccumulator, velocity);
// The force vector is cleared.
forceAccumulator.set(0, 0, 0);
+
angularVelocity.scaleAdd(duration, torqueAccumulator, angularVelocity);
torqueAccumulator.set(0, 0, 0);
UnQuat4f tmp = new UnQuat4f(angularVelocity.x, angularVelocity.y, angularVelocity.z, 0);
@@ -89,10 +90,16 @@ public abstract class CollidableObject {
}
protected void updateTransformGroup() {
+ Vector3f com = new Vector3f(-centerOfMass.x, -centerOfMass.y, -centerOfMass.z);
Transform3D tmp = new Transform3D();
- tmp.setRotation(orientation);
- tmp.setTranslation(position);
- TG.setTransform(tmp);
+ tmp.setTranslation(com);
+ Transform3D tmp2 = new Transform3D();
+ tmp2.setRotation(orientation);
+ com.negate();
+ com.add(position);
+ tmp2.setTranslation(com);
+ tmp2.mul(tmp);
+ TG.setTransform(tmp2);
clearCaches();
}
@@ -122,12 +129,15 @@ public abstract class CollidableObject {
if (inverseInertiaTensorCache == null) {
inverseInertiaTensorCache = new Matrix3f();
inverseInertiaTensorCache.set(orientation);
- inverseInertiaTensorCache.invert();
- inverseInertiaTensorCache.mul(inverseInertiaTensor);
+ Matrix3f tmp = new Matrix3f(inverseInertiaTensor);
+ Matrix3f tmp2 = new Matrix3f(inverseInertiaTensorCache);
+ tmp2.invert();
+ tmp.mul(tmp2);
+ inverseInertiaTensorCache.mul(tmp);
}
return inverseInertiaTensorCache;
}
-
+
protected void clearCaches() {
vertexCache = null;
triangleCache = null;
@@ -144,7 +154,6 @@ public abstract class CollidableObject {
float max = Float.NEGATIVE_INFINITY;
int count = 0;
for (CollisionInfo collision : collisions) {
-// float speed = collision.contactNormal.dot(previousVelocity) - collision.contactNormal.dot(other.previousVelocity);
Vector3f thisRelativeContactPosition = new Vector3f();
thisRelativeContactPosition.scaleAdd(-1, position, collision.contactPoint);
thisRelativeContactPosition.scaleAdd(-1, centerOfMass, thisRelativeContactPosition);
@@ -203,34 +212,47 @@ public abstract class CollidableObject {
if (totalInverseMass == 0)
return;
+ Vector3f thisMovementUnit = new Vector3f();
+ thisMovementUnit.cross(thisRelativeContactPosition, ci.contactNormal);
+ getInverseInertiaTensor().transform(thisMovementUnit);
Vector3f thisAngularVelocityUnit = new Vector3f();
- thisAngularVelocityUnit.cross(thisRelativeContactPosition, ci.contactNormal);
- getInverseInertiaTensor().transform(thisAngularVelocityUnit);
- thisAngularVelocityUnit.cross(thisAngularVelocityUnit, thisRelativeContactPosition);
+ thisAngularVelocityUnit.cross(thisMovementUnit, thisRelativeContactPosition);
totalInverseMass += thisAngularVelocityUnit.dot(ci.contactNormal);
+ Vector3f otherMovementUnit = new Vector3f();
+ otherMovementUnit.cross(otherRelativeContactPosition, ci.contactNormal);
+ other.getInverseInertiaTensor().transform(otherMovementUnit);
Vector3f otherAngularVelocityUnit = new Vector3f();
- otherAngularVelocityUnit.cross(otherRelativeContactPosition, ci.contactNormal);
- other.getInverseInertiaTensor().transform(otherAngularVelocityUnit);
- otherAngularVelocityUnit.cross(otherAngularVelocityUnit, otherRelativeContactPosition);
+ otherAngularVelocityUnit.cross(otherMovementUnit, otherRelativeContactPosition);
totalInverseMass += otherAngularVelocityUnit.dot(ci.contactNormal);
-
+
Vector3f impulse = new Vector3f(ci.contactNormal);
impulse.scale(deltaClosingSpeed / totalInverseMass);
+
velocity.scaleAdd(inverseMass, impulse, velocity);
Vector3f tmp = new Vector3f();
tmp.cross(thisRelativeContactPosition, impulse);
- tmp.scale(thisAngularVelocityUnit.dot(ci.contactNormal));
getInverseInertiaTensor().transform(tmp);
angularVelocity.add(tmp);
- position.scaleAdd(-ci.penetration * penetrationCorrection * inverseMass / (inverseMass + other.inverseMass), ci.contactNormal, position);
+ position.scaleAdd(-ci.penetration * penetrationCorrection * inverseMass / totalInverseMass, ci.contactNormal, position);
+ thisMovementUnit.scale(-ci.penetration * penetrationCorrection / totalInverseMass);
+ UnQuat4f tmp2 = new UnQuat4f(thisMovementUnit.x, thisMovementUnit.y, thisMovementUnit.z, 0);
+ tmp2.scale(0.5f);
+ tmp2.mul(orientation);
+ orientation.add(tmp2);
+ orientation.normalize();
impulse.negate();
other.velocity.scaleAdd(other.inverseMass, impulse, other.velocity);
tmp.cross(otherRelativeContactPosition, impulse);
- tmp.scale(otherAngularVelocityUnit.dot(ci.contactNormal));
other.getInverseInertiaTensor().transform(tmp);
other.angularVelocity.add(tmp);
- other.position.scaleAdd(ci.penetration * penetrationCorrection * other.inverseMass / (inverseMass + other.inverseMass), ci.contactNormal, other.position);
+ other.position.scaleAdd(ci.penetration * penetrationCorrection * other.inverseMass / totalInverseMass, ci.contactNormal, other.position);
+ otherMovementUnit.scale(ci.penetration * penetrationCorrection / totalInverseMass);
+ tmp2.set(otherMovementUnit.x, otherMovementUnit.y, otherMovementUnit.z, 0);
+ tmp2.scale(0.5f);
+ tmp2.mul(other.orientation);
+ other.orientation.add(tmp2);
+ other.orientation.normalize();
}
}
diff --git a/src/alden/CollisionDetector.java b/src/alden/CollisionDetector.java
index bb7817c..84682b8 100644
--- a/src/alden/CollisionDetector.java
+++ b/src/alden/CollisionDetector.java
@@ -1,4 +1,5 @@
package alden;
+
import java.util.ArrayList;
import javax.media.j3d.Appearance;
@@ -15,11 +16,15 @@ import javax.media.j3d.Transform3D;
import javax.media.j3d.TriangleArray;
import javax.media.j3d.TriangleFanArray;
import javax.media.j3d.TriangleStripArray;
+import javax.vecmath.Matrix3f;
import javax.vecmath.Point3f;
import javax.vecmath.Tuple3f;
import javax.vecmath.Vector3f;
import tesseract.objects.HalfSpace;
+import tesseract.objects.Particle;
+import tesseract.objects.Polygon;
+import tesseract.objects.Sphere;
import com.sun.j3d.utils.geometry.Primitive;
@@ -228,21 +233,6 @@ public class CollisionDetector {
}
return region;
}
-
- public boolean isAdjacent(Triangle other) {
- if (a.equals(other.a)) {
- if (b.equals(other.b) || b.equals(other.c) || c.equals(other.b) || c.equals(other.c))
- return true;
- } else if (a.equals(other.b)) {
- if (b.equals(other.a) || b.equals(other.c) || c.equals(other.a) || c.equals(other.c))
- return true;
- } else if (a.equals(other.c)) {
- if (b.equals(other.a) || b.equals(other.b) || c.equals(other.a) || c.equals(other.b))
- return true;
- } else if ((b.equals(other.b) || b.equals(other.c)) && (c.equals(other.b) || c.equals(other.c)))
- return true;
- return false;
- }
}
public static ArrayList<CollisionInfo> calculateCollisions(CollidableObject a, CollidableObject b) {
@@ -251,28 +241,72 @@ public class CollisionDetector {
if (a instanceof HalfSpace) {
if (b instanceof HalfSpace)
return EMPTY_COLLISION_LIST;
+ if (b instanceof Particle)
+ return calculateCollisions((HalfSpace)a, (Particle)b);
if (b instanceof Sphere)
return calculateCollisions((HalfSpace)a, (Sphere)b);
return calculateCollisions((HalfSpace)a, b.getVertices());
}
- if (!a.getBounds().intersect(b.getBounds()))
- return EMPTY_COLLISION_LIST;
+ if (b instanceof HalfSpace) {
+ if (a instanceof Particle)
+ return flipContactNormals(calculateCollisions((HalfSpace)b, (Particle)a));
+ if (a instanceof Sphere)
+ return flipContactNormals(calculateCollisions((HalfSpace)b, (Sphere)a));
+ return flipContactNormals(calculateCollisions((HalfSpace)b, a.getVertices()));
+ }
+ if (a instanceof Particle) {
+ if (b instanceof Particle)
+ return EMPTY_COLLISION_LIST;
+ if (b instanceof Sphere)
+ return calculateCollisions((Particle)a, (Sphere)b);
+ if (b instanceof Polygon)
+ return calculateCollisions((Particle)a, (Polygon)b);
+ }
+ if (b instanceof Particle) {
+ if (a instanceof Sphere)
+ return flipContactNormals(calculateCollisions((Particle)b, (Sphere)a));
+ if (a instanceof Polygon)
+ return flipContactNormals(calculateCollisions((Particle)b, (Polygon)a));
+ }
if (a instanceof Sphere && b instanceof Sphere)
return calculateCollisions((Sphere)a, (Sphere)b);
+
+ if (!a.getBounds().intersect(b.getBounds()))
+ return EMPTY_COLLISION_LIST;
+
+ if (a instanceof Particle)
+ return calculateCollisions((Particle)a, b);
+ if (b instanceof Particle)
+ return flipContactNormals(calculateCollisions((Particle)b, a));
+ if (a instanceof Polygon)
+ return calculateCollisions((Polygon)a, b);
+ if (b instanceof Polygon)
+ return calculateCollisions((Polygon)b, a);
return CollisionDetector.calculateCollisions(a.getCollisionTriangles(), b.getCollisionTriangles());
}
+ private static ArrayList<CollisionInfo> calculateCollisions(HalfSpace a, Particle b) {
+ float penetration = a.intercept - a.normal.dot(b.position);
+ if (penetration < 0)
+ return EMPTY_COLLISION_LIST;
+ Vector3f contactPoint = new Vector3f();
+ contactPoint.scaleAdd(penetration, a.normal, b.position);
+ assert(Math.abs(a.normal.dot(contactPoint) - a.intercept) < 0.01);
+ ArrayList<CollisionInfo> collisions = new ArrayList<CollisionInfo>();
+ collisions.add(new CollisionInfo(contactPoint, new Vector3f(a.normal), penetration));
+ return collisions;
+ }
+
private static ArrayList<CollisionInfo> calculateCollisions(HalfSpace a, Sphere b) {
float penetration = b.radius - (a.normal.dot(b.position) - a.intercept);
- if (penetration >= 0) {
- Vector3f contactPoint = new Vector3f();
- contactPoint.scaleAdd(-(b.radius - penetration), a.normal, b.position);
- assert(Math.abs(a.normal.dot(contactPoint) - a.intercept) < 0.01);
- ArrayList<CollisionInfo> collisions = new ArrayList<CollisionInfo>();
- collisions.add(new CollisionInfo(contactPoint, a.normal, penetration));
- return collisions;
- }
- return EMPTY_COLLISION_LIST;
+ if (penetration < 0)
+ return EMPTY_COLLISION_LIST;
+ Vector3f contactPoint = new Vector3f();
+ contactPoint.scaleAdd(-(b.radius - penetration), a.normal, b.position);
+ assert(Math.abs(a.normal.dot(contactPoint) - a.intercept) < 0.01);
+ ArrayList<CollisionInfo> collisions = new ArrayList<CollisionInfo>();
+ collisions.add(new CollisionInfo(contactPoint, new Vector3f(a.normal), penetration));
+ return collisions;
}
private static ArrayList<CollisionInfo> calculateCollisions(HalfSpace a, ArrayList<Vector3f> setB) {
@@ -283,24 +317,124 @@ public class CollisionDetector {
Vector3f contactPoint = new Vector3f();
contactPoint.scaleAdd(penetration, a.normal, vertex);
assert(Math.abs(a.normal.dot(contactPoint) - a.intercept) < 0.01);
- collisions.add(new CollisionInfo(contactPoint, a.normal, penetration));
+ collisions.add(new CollisionInfo(contactPoint, new Vector3f(a.normal), penetration));
}
}
return collisions;
}
+ private static ArrayList<CollisionInfo> calculateCollisions(Particle a, Sphere b) {
+ Vector3f delta = new Vector3f();
+ delta.scaleAdd(-1, a.position, b.position);
+ float penetration = b.radius - delta.length();
+ if (penetration < 0)
+ return EMPTY_COLLISION_LIST;
+
+ ArrayList<CollisionInfo> collisions = new ArrayList<CollisionInfo>();
+ delta.normalize();
+ Vector3f contactPoint = new Vector3f();
+ contactPoint.scaleAdd(-(b.radius - 0.5f * penetration), delta, b.position);
+ collisions.add(new CollisionInfo(contactPoint, delta, penetration));
+ return collisions;
+ }
+
+ private static ArrayList<CollisionInfo> calculateCollisions(Particle a, Polygon b) {
+ float penetration = b.intercept - b.normal.dot(a.position);
+ float previousPenetration = b.intercept - b.normal.dot(a.previousPosition);
+ if (Math.signum(penetration) == Math.signum(previousPenetration))
+ return EMPTY_COLLISION_LIST;
+
+ for (Triangle triangle : b.getCollisionTriangles()) {
+ Matrix3f tmp = new Matrix3f(a.previousPosition.x - a.position.x, triangle.b.x - triangle.a.x, triangle.c.x - triangle.a.x,
+ a.previousPosition.y - a.position.y, triangle.b.y - triangle.a.y, triangle.c.y - triangle.a.y,
+ a.previousPosition.z - a.position.z, triangle.b.z - triangle.a.z, triangle.c.z - triangle.a.z);
+ tmp.invert();
+ Vector3f intercept = new Vector3f();
+ intercept.scaleAdd(-1, triangle.a, a.previousPosition);
+ tmp.transform(intercept);
+
+ assert(intercept.x >= 0 && intercept.x <= 1);
+
+ if (intercept.y >= 0 && intercept.y <= 1 && intercept.z >= 0 && intercept.z <= 1 && (intercept.y + intercept.z) <= 1) {
+ Vector3f contactPoint = new Vector3f();
+ contactPoint.scaleAdd(-1, a.previousPosition, a.position);
+ contactPoint.scale(intercept.x);
+ contactPoint.add(a.previousPosition);
+ assert(Math.abs(b.normal.dot(contactPoint) - b.intercept) < 0.01);
+ Vector3f contactNormal = new Vector3f(b.normal);
+ if (penetration - previousPenetration > 0)
+ contactNormal.negate();
+ else
+ penetration = -penetration;
+ ArrayList<CollisionInfo> collisions = new ArrayList<CollisionInfo>();
+ collisions.add(new CollisionInfo(contactPoint, contactNormal, penetration));
+ return collisions;
+ }
+ }
+ return EMPTY_COLLISION_LIST;
+ }
+
+ private static ArrayList<CollisionInfo> calculateCollisions(Particle a, CollidableObject b) {
+ ArrayList<CollisionInfo> collisions = new ArrayList<CollisionInfo>();
+ for (Triangle triangle : b.getCollisionTriangles()) {
+ float penetration = triangle.intercept - triangle.normal.dot(a.position);
+ if (penetration < 0 || (!collisions.isEmpty() && penetration <= collisions.get(0).penetration))
+ continue;
+ float previousPenetration = triangle.intercept - triangle.normal.dot(a.previousPosition);
+ if (Math.signum(penetration) == Math.signum(previousPenetration))
+ continue;
+
+ Matrix3f tmp = new Matrix3f(a.previousPosition.x - a.position.x, triangle.b.x - triangle.a.x, triangle.c.x - triangle.a.x,
+ a.previousPosition.y - a.position.y, triangle.b.y - triangle.a.y, triangle.c.y - triangle.a.y,
+ a.previousPosition.z - a.position.z, triangle.b.z - triangle.a.z, triangle.c.z - triangle.a.z);
+ tmp.invert();
+ Vector3f intercept = new Vector3f();
+ intercept.scaleAdd(-1, triangle.a, a.previousPosition);
+ tmp.transform(intercept);
+
+ assert(intercept.x >= 0 && intercept.x <= 1);
+
+ if (intercept.y >= 0 && intercept.y <= 1 && intercept.z >= 0 && intercept.z <= 1 && (intercept.y + intercept.z) <= 1) {
+ Vector3f contactPoint = new Vector3f();
+ contactPoint.scaleAdd(-1, a.previousPosition, a.position);
+ contactPoint.scale(intercept.x);
+ contactPoint.add(a.previousPosition);
+ assert(Math.abs(triangle.normal.dot(contactPoint) - triangle.intercept) < 0.01);
+ Vector3f contactNormal = new Vector3f(triangle.normal);
+ if (penetration - previousPenetration > 0)
+ contactNormal.negate();
+ else
+ penetration = -penetration;
+ collisions.clear();
+ collisions.add(new CollisionInfo(contactPoint, contactNormal, penetration));
+ }
+ }
+ return collisions;
+ }
+
private static ArrayList<CollisionInfo> calculateCollisions(Sphere a, Sphere b) {
Vector3f delta = new Vector3f();
delta.scaleAdd(-1, a.position, b.position);
- float penetration = delta.length() - a.radius - b.radius;
- if (penetration > 0)
+ float penetration = a.radius + b.radius - delta.length();
+ if (penetration < 0)
return EMPTY_COLLISION_LIST;
ArrayList<CollisionInfo> collisions = new ArrayList<CollisionInfo>();
delta.normalize();
Vector3f contactPoint = new Vector3f();
- contactPoint.scaleAdd(a.radius + 0.5f * penetration, delta, a.position);
- collisions.add(new CollisionInfo(contactPoint, delta, -penetration));
+ contactPoint.scaleAdd(a.radius - 0.5f * penetration, delta, a.position);
+ collisions.add(new CollisionInfo(contactPoint, delta, penetration));
+ return collisions;
+ }
+
+ private static ArrayList<CollisionInfo> calculateCollisions(Polygon a, CollidableObject b) {
+ ArrayList<CollisionInfo> collisions = calculateCollisions(a.getCollisionTriangles(), b.getCollisionTriangles());
+ int size = collisions.size();
+ collisions.ensureCapacity(2 * size);
+ for (int i = 0; i < size; i++) {
+ collisions.add(collisions.get(i).clone());
+ collisions.get(collisions.size() - 1).contactNormal.negate();
+ }
return collisions;
}
@@ -315,6 +449,12 @@ public class CollisionDetector {
return collisions;
}
+ private static ArrayList<CollisionInfo> flipContactNormals(ArrayList<CollisionInfo> collisions) {
+ for (CollisionInfo collision : collisions)
+ collision.contactNormal.negate();
+ return collisions;
+ }
+
public static ArrayList<Vector3f> extractVertices(Node node) {
ArrayList<Vector3f> vertices = new ArrayList<Vector3f>();
extractVertices(node, vertices);
@@ -343,7 +483,7 @@ public class CollisionDetector {
for (int i = 0; i < group.numChildren(); i++)
extractVertices(group.getChild(i), vertices);
} else
- throw new IllegalArgumentException("Illegal node type for vertex extraction ");
+ throw new IllegalArgumentException("Illegal node type for vertex extraction");
}
private static void extractVertices(Geometry geometry, Transform3D transform, ArrayList<Vector3f> vertices) {
diff --git a/src/alden/CollisionInfo.java b/src/alden/CollisionInfo.java
index 9cefcd0..dad74a5 100644
--- a/src/alden/CollisionInfo.java
+++ b/src/alden/CollisionInfo.java
@@ -2,7 +2,7 @@ package alden;
import javax.vecmath.*;
@SuppressWarnings("restriction")
-public class CollisionInfo {
+public class CollisionInfo implements Cloneable {
public Vector3f contactPoint;
public Vector3f contactNormal;
public float penetration;
@@ -12,4 +12,15 @@ public class CollisionInfo {
this.contactNormal = contactNormal;
this.penetration = penetration;
}
+
+ public CollisionInfo clone() {
+ try {
+ CollisionInfo copy = (CollisionInfo)super.clone();
+ copy.contactPoint = new Vector3f(contactPoint);
+ copy.contactNormal = new Vector3f(contactNormal);
+ return copy;
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+ }
} \ No newline at end of file
diff --git a/src/tesseract/TesseractUI.java b/src/tesseract/TesseractUI.java
index 1e8ff9c..ca882e2 100644
--- a/src/tesseract/TesseractUI.java
+++ b/src/tesseract/TesseractUI.java
@@ -12,6 +12,7 @@ import java.awt.event.MouseWheelListener;
import javax.media.j3d.BoundingBox;
import javax.media.j3d.Canvas3D;
+import javax.media.j3d.Node;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.JCheckBoxMenuItem;
@@ -39,6 +40,7 @@ import tesseract.menuitems.IcosahedronMenuItem;
import tesseract.menuitems.ParticleEmitterMenuItem;
import tesseract.menuitems.ParticleMenuItem;
import tesseract.menuitems.PlanarPolygonMenuItem;
+import tesseract.objects.Box;
import tesseract.objects.ChainLink2;
import tesseract.objects.PhysicalObject;
@@ -149,6 +151,7 @@ public class TesseractUI extends JFrame {
ChainLink2 o = new ChainLink2(new Vector3f(), 1);
o.setRotation();
myWorld.addObject(o);
+ myWorld.addObject(new Box(0.20f, 0.09f, 0.10f, new Vector3f(0, 0.25f, 0)));
}
/**
@@ -342,11 +345,18 @@ public class TesseractUI extends JFrame {
pc.setShapeLocation(e);
PickResult r = pc.pickClosest();
- if (r != null && r.getObject().getUserData() instanceof PhysicalObject) {
- myCurrentObject =
- (PhysicalObject) r.getObject().getUserData();
-
- myCurrentObject.selected(true);
+ if (r != null) {
+ for (int i = r.getSceneGraphPath().nodeCount() - 1;
+ i > 0; i--) {
+ Node n = r.getSceneGraphPath().getNode(i);
+ if (n.getUserData() instanceof PhysicalObject) {
+ myCurrentObject =
+ (PhysicalObject) n.getUserData();
+ myCurrentObject.selected(true);
+
+ break;
+ }
+ }
}
}
diff --git a/src/tesseract/objects/Box.java b/src/tesseract/objects/Box.java
new file mode 100644
index 0000000..fb3dc42
--- /dev/null
+++ b/src/tesseract/objects/Box.java
@@ -0,0 +1,36 @@
+package tesseract.objects;
+import javax.media.j3d.Appearance;
+import javax.media.j3d.Geometry;
+import javax.media.j3d.Material;
+import javax.media.j3d.Node;
+import javax.vecmath.Vector3f;
+
+import com.sun.j3d.utils.geometry.Primitive;
+
+public class Box extends PhysicalObject {
+ public Box(float width, float height, float depth, Vector3f position) {
+ this(1, width, height, depth, position);
+ }
+
+ public Box(float mass, float width, float height, float depth, Vector3f position) {
+ super(position, mass);
+ setShape(createShape(width, height, depth));
+
+ previousPosition.set(position);
+ if (inverseMass != 0) {
+ inverseInertiaTensor.m00 = 1f / 12 / inverseMass * (height * height + depth * depth);
+ inverseInertiaTensor.m11 = 1f / 12 / inverseMass * (width * width + depth * depth);
+ inverseInertiaTensor.m22 = 1f / 12 / inverseMass * (width * width + height * height);
+ inverseInertiaTensor.invert();
+ }
+ updateTransformGroup();
+ }
+
+ protected Node createShape(float width, float height, float depth) {
+ Appearance appearance = new Appearance();
+ Material material = new Material();
+ material.setDiffuseColor(0.7f, 1, 0.7f);
+ appearance.setMaterial(material);
+ return new com.sun.j3d.utils.geometry.Box(width / 2, height / 2, depth / 2, appearance);
+ }
+}
diff --git a/src/tesseract/objects/Circle.java b/src/tesseract/objects/Circle.java
new file mode 100644
index 0000000..3019a2b
--- /dev/null
+++ b/src/tesseract/objects/Circle.java
@@ -0,0 +1,55 @@
+package tesseract.objects;
+import com.sun.j3d.utils.image.*;
+import javax.media.j3d.*;
+import javax.vecmath.*;
+
+public class Circle extends Polygon {
+ public Circle(float radius, Vector3f position, Vector3f normal) {
+ this(1, radius, position, normal);
+ }
+
+ public Circle(float mass, float radius, Vector3f position, Vector3f normal) {
+ super(mass, position, normal);
+ setShape(createShape(radius, 22));
+ if (inverseMass != 0) {
+ inverseInertiaTensor.m00 = 1f / 4 / inverseMass * radius * radius;
+ inverseInertiaTensor.m11 = 2 * inverseInertiaTensor.m00;
+ inverseInertiaTensor.m22 = inverseInertiaTensor.m00;
+ inverseInertiaTensor.invert();
+ }
+ updateTransformGroup();
+ }
+
+ protected Node createShape(float radius, int divisions) {
+ TriangleFanArray geometry = new TriangleFanArray(divisions, TriangleFanArray.COORDINATES | TriangleFanArray.TEXTURE_COORDINATE_2, new int[] {divisions});
+ for (int i = 0; i < divisions; i++) {
+ float baseX = (float)Math.cos(2 * Math.PI * i / divisions);
+ float baseZ = -(float)Math.sin(2 * Math.PI * i / divisions);
+ geometry.setCoordinate(i, new Point3f(radius * baseX, 0, radius * baseZ));
+ geometry.setTextureCoordinate(0, i, new TexCoord2f((baseX + 1) / 2, (-baseZ + 1) / 2));
+ }
+
+ TextureLoader tl = new TextureLoader("wood.jpg", null);
+ ImageComponent2D image = tl.getImage();
+ int width = image.getWidth();
+ int height = image.getHeight();
+ Texture2D texture = new Texture2D(Texture.MULTI_LEVEL_MIPMAP, Texture.RGB, width, height);
+
+ int imageLevel = 0;
+ texture.setImage(imageLevel, image);
+ while (width > 1 || height > 1) {
+ imageLevel++;
+ if (width > 1) width /= 2;
+ if (height > 1) height /= 2;
+ texture.setImage(imageLevel, tl.getScaledImage(width, height));
+ }
+ texture.setMagFilter(Texture2D.NICEST);
+ texture.setMinFilter(Texture2D.NICEST);
+
+ Appearance appearance = new Appearance();
+ appearance.setTexture(texture);
+ PolygonAttributes polyAttr = new PolygonAttributes(PolygonAttributes.POLYGON_FILL, PolygonAttributes.CULL_NONE, 0);
+ appearance.setPolygonAttributes(polyAttr);
+ return new Shape3D(geometry, appearance);
+ }
+}
diff --git a/src/tesseract/objects/Particle.java b/src/tesseract/objects/Particle.java
index 6dcc864..b3b6274 100644
--- a/src/tesseract/objects/Particle.java
+++ b/src/tesseract/objects/Particle.java
@@ -75,7 +75,7 @@ public class Particle extends PhysicalObject {
cAttr = new ColoringAttributes(color, ColoringAttributes.FASTEST);
Appearance appearance = new Appearance();
appearance.setColoringAttributes(cAttr);
- Sphere sphere = new Sphere(RADIUS, Sphere.ENABLE_GEOMETRY_PICKING | Sphere.GEOMETRY_NOT_SHARED,
+ Sphere sphere = new Sphere(RADIUS, Sphere.ENABLE_GEOMETRY_PICKING,
DIVISIONS, appearance);
TransformGroup tg = new TransformGroup();
tg.addChild(sphere);
diff --git a/src/tesseract/objects/Polygon.java b/src/tesseract/objects/Polygon.java
new file mode 100644
index 0000000..c8fcf53
--- /dev/null
+++ b/src/tesseract/objects/Polygon.java
@@ -0,0 +1,43 @@
+package tesseract.objects;
+import javax.media.j3d.Transform3D;
+import javax.vecmath.*;
+
+import alden.CollidableObject;
+
+public abstract class Polygon extends PhysicalObject {
+ public Vector3f normal;
+ // Right-hand side of the plane equation: Ax + By + Cz = D
+ public float intercept;
+
+ public Polygon(Vector3f position, Vector3f normal) {
+ this(1, position, normal);
+ }
+
+ public Polygon(float mass, Vector3f position, Vector3f normal) {
+ super(position, mass);
+
+ this.normal = new Vector3f(normal);
+ this.normal.normalize();
+ intercept = this.normal.dot(position);
+ Vector3f newX = new Vector3f(1, 0, 0);
+ if (Math.abs(newX.dot(this.normal)) == 1)
+ newX = new Vector3f(0, -1, 0);
+ newX.scaleAdd(-newX.dot(this.normal), this.normal, newX);
+ newX.normalize();
+ Vector3f newZ = new Vector3f();
+ newZ.cross(newX, this.normal);
+ new Matrix4f(new Matrix3f(newX.x, this.normal.x, newZ.x, newX.y, this.normal.y, newZ.y, newX.z, this.normal.z, newZ.z), position, 1).get(orientation);
+ }
+
+ protected void updateTransformGroup() {
+ super.updateTransformGroup();
+ Transform3D tmp = new Transform3D();
+ TG.getTransform(tmp);
+ Matrix3f rot = new Matrix3f();
+ tmp.get(rot);
+ normal.x = rot.m01;
+ normal.y = rot.m11;
+ normal.z = rot.m21;
+ intercept = normal.dot(position);
+ }
+}
diff --git a/src/alden/Sphere.java b/src/tesseract/objects/Sphere.java
index ddbaff4..4ec4aaa 100644
--- a/src/alden/Sphere.java
+++ b/src/tesseract/objects/Sphere.java
@@ -1,21 +1,21 @@
-package alden;
-
+package tesseract.objects;
import javax.media.j3d.*;
import javax.vecmath.*;
-@SuppressWarnings("restriction")
-public class Sphere extends CollidableObject {
- protected float radius;
+import alden.CollidableObject;
+
+public class Sphere extends PhysicalObject {
+ public float radius;
public Sphere(float radius, Vector3f position) {
this(1, radius, position);
}
public Sphere(float mass, float radius, Vector3f position) {
- super(mass);
+ super(position, mass);
setShape(createShape(radius, 22));
this.radius = radius;
- this.position.set(position);
+
if (inverseMass != 0) {
inverseInertiaTensor.m00 = 2f / 5 / inverseMass * radius * radius;
inverseInertiaTensor.m11 = inverseInertiaTensor.m00;