|
-
April 11th, 2011, 12:02 PM
#1
Java3D collision detection
Hi,
I am currently developing an air hockey game in java3d and have come across an issue with collision detection between the puck and sides (or goals).
I am trying to change the colour of the sides when the puck bounces off them (not implemented yet), however, not only the side that the puck is colliding against changes colour, but anything else of the same colour (ie. the bottom side). Try changing the colour of one of the sides (ie. Box tableMarginTop = new Box(3.5f, 0.1f, 0.2f, blueApp) and notice the difference. How do I avoid this problem?
Thanks in advance.
Code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.media.j3d.Alpha;
import javax.media.j3d.Appearance;
import javax.media.j3d.Background;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.ColoringAttributes;
import javax.media.j3d.PositionInterpolator;
import javax.media.j3d.RotationInterpolator;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.JApplet;
import javax.vecmath.AxisAngle4d;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.behaviors.mouse.MouseTranslate;
import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
import com.sun.j3d.utils.geometry.Box;
import com.sun.j3d.utils.geometry.Cylinder;
import com.sun.j3d.utils.universe.SimpleUniverse;
public class TestAlpha extends JApplet {
Alpha alpha = null;
PositionInterpolator posInt = null;
private Background background = null;
Canvas3D canvas3D =
new Canvas3D(SimpleUniverse.getPreferredConfiguration());
SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
// Create a bounds for the background and behaviours
BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
// Create the root of the branch graph
BranchGroup scene = createSceneGraph();
TransformGroup tg = simpleU.getViewingPlatform().getViewPlatformTransform();
public TestAlpha(){
launchApplication();
}
private void launchApplication() {
background = new Background();
background.setCapability(Background.ALLOW_IMAGE_WRITE);
background.setCapability(Background.ALLOW_COLOR_WRITE);
background.setApplicationBounds(bounds);
scene.addChild(background);
this.setLayout(new BorderLayout());
this.add(canvas3D, BorderLayout.CENTER);
positionCamera(simpleU);
scene.compile();
simpleU.addBranchGraph(scene);
}
private void positionCamera(SimpleUniverse su) {
// Translation + rotation
Transform3D translation = new Transform3D();
translation.setTranslation(new Vector3f(0, -1, 14));
Transform3D rotationX = new Transform3D();
rotationX.rotX(45f * Math.PI/180f);
Transform3D trans = new Transform3D();
trans.mul(rotationX, translation);
tg.setTransform(trans);
}
private BranchGroup createSceneGraph() {
BranchGroup parent = new BranchGroup();
parent.addChild(createTable());
return parent;
}
private BranchGroup createTable(){
// If you were writing a pool game you could use a PickSegment (PickRaySegment) to represent the pool cue
// and you could pick with BoundingSphere to detecting collisions between the balls.
// blue
Appearance blueApp = new Appearance();
blueApp.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_WRITE);
Color3f blueColor = new Color3f(0.3f, 0.3f, 1.0f);
ColoringAttributes blueCA = new ColoringAttributes();
blueCA.setColor(blueColor);
blueApp.setColoringAttributes(blueCA);
// medium blue
Appearance medBlueApp = new Appearance();
Color3f medBlueColor = new Color3f(0.1f, 0.8f, 1.0f);
ColoringAttributes medBlueCA = new ColoringAttributes();
medBlueCA.setColor(medBlueColor);
medBlueApp.setColoringAttributes(medBlueCA);
// orange
Appearance orangeApp = new Appearance();
orangeApp.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_WRITE);
Color3f orangeColor = new Color3f(0.988f, 0.800f, 0.080f);
ColoringAttributes orangeCA = new ColoringAttributes();
orangeCA.setColor(orangeColor);
orangeApp.setColoringAttributes(orangeCA);
BranchGroup parent = new BranchGroup();
//Shape3D hockeyTableSlate = new Box(3.3f, 5.0f, 0.001f);
Box hockeyTableSlate = new Box(3.3f, 5.0f, 0.001f, medBlueApp);
//hockeyTableSlate.setUserData(new String("table bottom"));
// the top table margin
Box tableMarginTop = new Box(3.5f, 0.1f, 0.2f, orangeApp);
tableMarginTop.setUserData(new String("top margin1"));
Transform3D tableMarginToptr = new Transform3D();
tableMarginToptr.setTranslation(new Vector3f(0f, 5.1f, 0.1f));
TransformGroup tableMarginTopTG = new TransformGroup(tableMarginToptr);
tableMarginTopTG.addChild(tableMarginTop);
tableMarginTopTG.setUserData(new String("top margin2"));
// the bottom table margin
Box tableMarginBottom = new Box(3.5f, 0.1f, 0.2f, orangeApp);
tableMarginBottom.setUserData(new String("bottom margin"));
//SideCollisionDetector pcd2 = new SideCollisionDetector(tableMarginBottom);
//pcd2.setSchedulingBounds(bounds);
Transform3D tableMarginBottomtr = new Transform3D();
tableMarginBottomtr.setTranslation(new Vector3f(0f, -5.1f, 0.1f));
TransformGroup tableMarginBottomTG = new TransformGroup(
tableMarginBottomtr);
tableMarginBottomTG.addChild(tableMarginBottom);
//parent.addChild(tableMarginBottomTG);
TransformGroup mainTG = new TransformGroup();
mainTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
mainTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
mainTG.addChild(hockeyTableSlate);
mainTG.addChild(tableMarginTopTG);
mainTG.addChild(tableMarginBottomTG);
//parent.addChild(mainTG);
// Create the rotate behavior node
MouseRotate behavior = new MouseRotate();
behavior.setTransformGroup(mainTG);
parent.addChild(behavior);
behavior.setSchedulingBounds(bounds);
// Create the zoom behavior node
MouseZoom behavior2 = new MouseZoom();
behavior2.setTransformGroup(mainTG);
parent.addChild(behavior2);
behavior2.setSchedulingBounds(bounds);
// Create the translate behavior node
MouseTranslate behavior3 = new MouseTranslate();
behavior3.setTransformGroup(mainTG);
parent.addChild(behavior3);
behavior3.setSchedulingBounds(bounds);
//light blue
Appearance ltBlueApp = new Appearance();
ltBlueApp.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_WRITE);
Color3f ltBlueColor = new Color3f(0.5f, 1.0f, 1.0f);
ColoringAttributes ltBlueCA = new ColoringAttributes();
ltBlueCA.setColor(ltBlueColor);
ltBlueApp.setColoringAttributes(ltBlueCA);
// puck
TransformGroup transPuckTG = new TransformGroup();
transPuckTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Transform3D puckTranslation3D = new Transform3D();
puckTranslation3D.setTranslation(new Vector3f(0f, 0.0f, .2f)); //0.05
puckTranslation3D.setRotation(new AxisAngle4d(1.0, 0.0, 0.0, Math.PI / 2.0));
transPuckTG.setTransform(puckTranslation3D);
Cylinder puck = new Cylinder(0.22f, 0.075f, ltBlueApp);
puck.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_WRITE);
transPuckTG.addChild(puck);
//scd.setSchedulingBounds(bounds);
// animation
TransformGroup animationTG = new TransformGroup();
animationTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Transform3D axe = new Transform3D();
axe.setRotation(new AxisAngle4d(0.0, 0.0, 1.0, Math.PI/2));
alpha = new Alpha(-1, 5000);
alpha.setStartTime(System.currentTimeMillis());
posInt = new PositionInterpolator(alpha, animationTG, axe, 0f, 6.1f);
posInt.setSchedulingBounds(bounds);
SideCollisionDetector scd = new SideCollisionDetector(transPuckTG,/* axe, alpha, posInt, */bounds);
// try adding the alpha
animationTG.addChild(posInt);
animationTG.addChild(transPuckTG);
animationTG.addChild(scd);
mainTG.addChild(animationTG);
parent.addChild(mainTG);
parent.compile();
return parent;
}
public static void main(String[] args) {
Frame frame = new MainFrame(new TestAlpha(), 790, 600);
frame.setResizable(false);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent winEvent) {
System.exit(0);
}
});
}
} //TestAlpha.java
And the collision detector class:
Code:
import java.util.Enumeration;
import javax.media.j3d.Appearance;
import javax.media.j3d.Behavior;
import javax.media.j3d.Bounds;
import javax.media.j3d.ColoringAttributes;
import javax.media.j3d.Node;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.WakeupCriterion;
import javax.media.j3d.WakeupOnCollisionEntry;
import javax.media.j3d.WakeupOnCollisionExit;
import javax.media.j3d.WakeupOnCollisionMovement;
import javax.media.j3d.WakeupOr;
import javax.vecmath.Color3f;
import javax.vecmath.Vector3d;
import com.sun.j3d.utils.geometry.Primitive;
public class SideCollisionDetector extends Behavior{
private static final Color3f highlightColor = new Color3f(0.0f, 1.0f, 0.0f);
private Appearance sideAppearance;
private static final ColoringAttributes highlight = new ColoringAttributes(
highlightColor, ColoringAttributes.SHADE_GOURAUD); //smooth shading model
/** The separate criteria used to wake up this behaviour. */
private WakeupCriterion[] theCriteria;
/** The OR of the separate criteria. */
private WakeupOr oredCriteria;
/** The transformgroup that is watched for collision. */
private TransformGroup collidingTG;
Vector3d v = new Vector3d();
/**
* @param transG
* TransformGroup that is to be watched for collisions.
* @param theBounds
* Bounds that define the active region for this behaviour.
*/
public SideCollisionDetector(TransformGroup transTG, /*Transform3D trans3D, Alpha a, PositionInterpolator positionInt, */Bounds theBounds) {
collidingTG = transTG;
//collidingTrans3D = trans3D;
//collidingAlpha = a;
//collidingPos = positionInt;
setSchedulingBounds(theBounds);
//inCollision = false;
}
/**
* This creates an entry, exit and movement collision criteria. These are then OR'ed together,
* and the wake up condition set to the result.
*/
public void initialize() {
theCriteria = new WakeupCriterion[3];
theCriteria[0] = new WakeupOnCollisionEntry(collidingTG, WakeupOnCollisionEntry.USE_GEOMETRY);
theCriteria[1] = new WakeupOnCollisionExit(collidingTG, WakeupOnCollisionEntry.USE_GEOMETRY);
theCriteria[2] = new WakeupOnCollisionMovement(collidingTG, WakeupOnCollisionEntry.USE_GEOMETRY);
oredCriteria = new WakeupOr(theCriteria);
wakeupOn(oredCriteria);
}
public void processStimulus(Enumeration criteria) {
WakeupCriterion theCriterion = (WakeupCriterion) criteria.nextElement();
if (theCriterion instanceof WakeupOnCollisionEntry) {
Node theLeaf = ((WakeupOnCollisionEntry) theCriterion)
.getTriggeringPath().getObject().getParent();
System.out.println("Collided with " + theLeaf.getUserData());
sideAppearance = ((Primitive) theLeaf).getAppearance();
sideAppearance.getColoringAttributes();
sideAppearance.setColoringAttributes(highlight);
} else if (theCriterion instanceof WakeupOnCollisionExit) {
Node theLeaf = ((WakeupOnCollisionExit) theCriterion)
.getTriggeringPath().getObject().getParent();
System.out.println("Stopped colliding with "
+ theLeaf.getUserData());
// orange
Appearance orangeApp = new Appearance();
orangeApp.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_WRITE);
Color3f orangeColor = new Color3f(0.988f, 0.800f, 0.080f);
ColoringAttributes orangeCA = new ColoringAttributes(orangeColor, ColoringAttributes.SHADE_GOURAUD);
orangeCA.setColor(orangeColor);
sideAppearance.setColoringAttributes(orangeCA);
} else {
Node theLeaf = ((WakeupOnCollisionMovement) theCriterion)
.getTriggeringPath().getObject().getParent();
System.out.println("Moved whilst colliding with "
+ theLeaf.getUserData());
sideAppearance = ((Primitive) theLeaf).getAppearance();
sideAppearance.getColoringAttributes();
sideAppearance.setColoringAttributes(highlight);
}
wakeupOn(oredCriteria);
}
}
//}
-
April 20th, 2011, 09:41 AM
#2
Re: Java3D collision detection
-
April 20th, 2011, 11:23 AM
#3
Re: Java3D collision detection
It looks like you're changing the colour of the Appearance object so everything that uses that appearance object will change colour. You need to use a different instance of the Appearance class for each Box you want to control independently of the others.
-
April 20th, 2011, 12:50 PM
#4
Re: Java3D collision detection
Thank you for your reply, that makes sense now.
Another problem I am having is getting the position of the puck when it comes into contact with any of the sides. Instead of showing that the puck is moving on the - z axis, the value of z stays the same where as the values of x and y change, which is weird.
The output is:
Collided with top margin1
3.008308430189949E-16 ; 4.912940502166748 ; 0.0
Moved whilst colliding with top margin1
3.032961347059877E-16 ; 4.953201770782471 ; 0.0
But it should look something like:
Collided with top margin1
0.0 ; 0.0 ; -4.95243
Moved whilst colliding with top margin1
0.0 ; 0.0 ; -5.01231
The code I have used which gives the wrong values is:
Code:
collidingTG.getTransform(trans3D);
trans3D.get(v);
System.out.println(v.getX() + " ; " + v.getY() + " ; " + v.getZ());
where trans3D is a new Transform3D object and v is a new vector, both created in the collision detection class.
Code:
private Transform3D trans3D = new Transform3D();
Vector3d v = new Vector3d();
How do I get Sys out to print the correct values?
Thanks
-
April 21st, 2011, 03:13 AM
#5
Re: Java3D collision detection
How do I get Sys out to print the correct values?
It's only printing out the values you have calculated so the answer has to be you have to calculate the correct values.
Can you show the code which performs the calculation once a collision has taken place.
-
April 21st, 2011, 04:28 AM
#6
Re: Java3D collision detection
Im not calculating anything, the puck moves across the v-axis because of the alpha and position interpolator objects, in the main TestAlpha class.
the puck is then added to the transPuckTG transform group and passed into the SideCollisionDetector's arguments.
Code:
SideCollisionDetector scd = new SideCollisionDetector(transPuckTG, axe,/* alpha, posInt, */bounds);
In the collision detection class, the code I have posted in the previous post takes the transPuckTG object, assigns a vector to its transform and gets the x, y, and z values.
The values are wrong because the puck is only moving along the z-axis, so the other two should remain 0. The code to extract the values is correct, I have a feeling im passing the wrong transform group in the SideColisionDetector object, but whichever way I do it, it still wont display the right values
-
April 21st, 2011, 05:27 AM
#7
Re: Java3D collision detection
3.008308430189949E-16 is as close to zero as makes no difference. Try rounding.
The most exciting phrase to hear in science -the one that heralds new discoveries- is not "Eureka!" but "That's funny...".
I. Asimov
Please use [CODE]...your code here...[/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.
-
April 23rd, 2011, 01:31 PM
#8
Re: Java3D collision detection
thanks for replying, I'm still not sure why x and y aren't 0 and z negative
-
April 23rd, 2011, 03:03 PM
#9
Re: Java3D collision detection
I haven't got the time to work out what the code is doing but just from looking at the numbers you have shown it looks like your Y and Z values are transposed. I would check the transform you are using.
As dlorde has already said the X value is basically 0 - the value shown could be due to the inaccuracies that can occur in floating point math. So if Y and Z are transposed and you round all the values to say 6 decimal places you will have your 0 values for X and Y and a Z value that moves albeit in the wrong direction (possibly another transform issue).
Sorry I can't be of more help.
-
April 27th, 2011, 08:48 AM
#10
Re: Java3D collision detection
Can anyone tell me how will I be able to differentiate between objects with regards to collision detection?
Currently, because the puck is a cylinder, and the sides/goals are boxes, the way they see if they collide is through their transform groups. However this doesn't seem to work very well because the puck reads the same type of collision with any object it collides with. For example when it bounces off a side, the side changes colour, however the same happens when the puck collides with the paddles, and I don't want the paddles to change colour (the same happens with playing a sound when in collision). The same applies for the goals, which are also boxes, except a different colour, and also for objects which aren't necessarily boxes.
If I change all the objects in my plan to Shape3D, including the puck, which will obviously take some time, will the collision detection become easier? Will I be able to manipulate which items I want to highlight, or play a sound, or for example when the puck hits the goal increment the corresponding score counter?
Thanks,
AW
Last edited by abbeywell; April 27th, 2011 at 08:51 AM.
Reason: added extra info
-
April 27th, 2011, 10:45 AM
#11
Re: Java3D collision detection
It sounds like you need to separate your logic out. If you had 3 methods, one for contacting a puck, one for the goal and one for the walls, you could then differentiate and code what specific things need to happen (playing a sound, coloring a wall) based on the event. But the collision detection should be similar in all cases.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|