Results 1 to 6 of 6
  1. #1
    abbeywell is offline Member
    Join Date
    Apr 2011
    Posts
    7
    Rep Power
    0

    Default 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.

    Java 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:

    Java 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
    Jodokus's Avatar
    Jodokus is offline Senior Member
    Join Date
    Jan 2011
    Location
    Amsterdam, the Netherlands
    Posts
    230
    Rep Power
    4

    Default

    I can't reproduce your problem. I get this exception when the puck reaches the bar:

    Java Code:
    Exception occurred during Behavior execution:
    javax.media.j3d.RestrictedAccessException: Cannot get the parent of a live or compiled node
    	at javax.media.j3d.Node.getParent(Node.java:139)
    	at z_javaForumProblem1.SideCollisionDetector.processStimulus(SideCollisionDetector.java:76)
    	at javax.media.j3d.BehaviorScheduler.doWork(BehaviorScheduler.java:172)
    	at javax.media.j3d.J3dThread.run(J3dThread.java:250)
    The puck then passes on through the bar and starts again in the middle of the table.
    Changing the Color of the bar as you asked has no effect (except changing the color of course).

    Just curious: is this your invention or are you following some tutorial?

  3. #3
    abbeywell is offline Member
    Join Date
    Apr 2011
    Posts
    7
    Rep Power
    0

    Default

    Thank you for your reply. It is my invention. Because I'm using an Alpha object, the puck repeats the movement it does on the y-axis, but this will be changed so that there will be a bounce effect showing (change the parameters of the position interpolator in the collision detector class?).
    However this is not my problem at this stage, although if anyone has any ideas on how to implement it, it will be greatly appreciated.

    If you copy and paste my code in two separate classes, the compilation and run should be all ok, and the output should look something like this:

    Collided with top margin1
    Moved whilst colliding with top margin1
    ...
    Stopped colliding with top margin1


    When passing through the margin, both top and bottom margins change colour from yellow to green. I only want the top margin to be affected.

    I have re-tested, therefore I am not sure why you are getting the error you are getting, but I can see it happens in this line:

    Java Code:
    Node theLeaf = ((WakeupOnCollisionEntry) theCriterion)
    	.getTriggeringPath().getObject().getParent();
    Thanks

  4. #4
    Jodokus's Avatar
    Jodokus is offline Senior Member
    Join Date
    Jan 2011
    Location
    Amsterdam, the Netherlands
    Posts
    230
    Rep Power
    4

    Default

    Sorry, I can't get it working, I keep the exception. I've splitted up the offending statement. It is compiled and life. I changed the capabilitybits at the root of the tree: doesn't help. I give up, it's not your problem if it works well on your side.
    I don't know if I can help you. I once made a rudimentary billiardsgame, but I did it with ODE, not with behaviors.
    Yood luck, keep me informed if it works in the end!

  5. #5
    abbeywell is offline Member
    Join Date
    Apr 2011
    Posts
    7
    Rep Power
    0

    Default

    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:

    Java Code:
    collidingTG.getTransform(trans3D);
    			trans3D.get(v);
    			System.out.println(v.getX() + " ; " + v.getY() + " ; " + v.getZ());
    where trans3D is the (commented) argument passed in the SideCollisionDetector constructor and v is a new vector.

    Can anyone help?
    Thanks

  6. #6
    abbeywell is offline Member
    Join Date
    Apr 2011
    Posts
    7
    Rep Power
    0

    Default

    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

Similar Threads

  1. Let's Check My Collision Detection Algorithm
    By Revenna in forum Java 2D
    Replies: 3
    Last Post: 03-23-2011, 02:44 PM
  2. Really Need help with some collision detection
    By Harwad in forum New To Java
    Replies: 1
    Last Post: 01-23-2011, 12:38 AM
  3. Three errors in collision detection methods
    By Fortu in forum New To Java
    Replies: 6
    Last Post: 12-19-2010, 11:32 PM
  4. Collision Detection
    By dotabyss in forum Java Gaming
    Replies: 0
    Last Post: 03-14-2010, 06:13 PM
  5. Collision Detection (Game)
    By mscwd in forum Sun Java Wireless Toolkit
    Replies: 0
    Last Post: 01-28-2008, 08:34 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •