CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Apr 2011
    Location
    London
    Posts
    14

    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); 
    	}
    }
    //}

  2. #2
    Join Date
    Apr 2011
    Location
    London
    Posts
    14

    Re: Java3D collision detection

    bump

  3. #3
    Join Date
    May 2006
    Location
    UK
    Posts
    4,473

    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.
    Posting code? Use code tags like this: [code]...Your code here...[/code]
    Click here for examples of Java Code

  4. #4
    Join Date
    Apr 2011
    Location
    London
    Posts
    14

    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

  5. #5
    Join Date
    May 2006
    Location
    UK
    Posts
    4,473

    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.
    Posting code? Use code tags like this: [code]...Your code here...[/code]
    Click here for examples of Java Code

  6. #6
    Join Date
    Apr 2011
    Location
    London
    Posts
    14

    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

  7. #7
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    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.

  8. #8
    Join Date
    Apr 2011
    Location
    London
    Posts
    14

    Re: Java3D collision detection

    thanks for replying, I'm still not sure why x and y aren't 0 and z negative

  9. #9
    Join Date
    May 2006
    Location
    UK
    Posts
    4,473

    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.
    Posting code? Use code tags like this: [code]...Your code here...[/code]
    Click here for examples of Java Code

  10. #10
    Join Date
    Apr 2011
    Location
    London
    Posts
    14

    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

  11. #11
    Join Date
    Feb 2008
    Posts
    966

    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
  •  





Click Here to Expand Forum to Full Width

Featured