3D-Grafik 3D Kollision

T

Turakar

Gast
Hallo,

ich habe das Problem, das ich keine Idee hab wie ich in Java3D Kollision erkennen soll. Ich zwar ein paar Codes gefunden, wo allerdings nur :rtfm: rauskam. Mein Ziel ist es, 3D-Objekte stoppen zu lassen, wenn sie kollidieren.

Noch ein weiteres Problem, meine Enbindung vom KeyListener klappt nicht, keine events:
Java:
GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
	    Canvas3D canvas3D = new Canvas3D(config);
	    add("Center", canvas3D);
	    
	    canvas3D.setFocusable(true);     // give focus to the canvas 
	    canvas3D.requestFocus();
	    
	    canvas3D.addKeyListener(new KeyListener() 
	    {
	        public void keyPressed(KeyEvent e) 
	        {
	        	System.out.println(e.getKeyChar());
	        }

	        public void keyReleased(KeyEvent e) 
	        {
	        	
	        }

			public void keyTyped(KeyEvent arg0) 
			{
				
			}
			
	      });

Freue mich über schnelle Antworten,

Turakar
 
Zuletzt bearbeitet von einem Moderator:

Marco13

Top Contributor
Auch wenn man in Java3D für sowas eigentlich Behaviors verwendet (ich find' die auch manchmal ziemlich "sperrig") sollte das mit dem KeyListener noch gehen. Vielleicht mal irgendwann ein KSKB erstellen...
 
T

Turakar

Gast

das klappt, dank dir, jetzt. :toll:

Ich hab aber auch noch einen anderen Bug gefunden:
Beim Hinzufügen des JPanels, öffnet sich dieses in einem neuen Fenster, obwohl es von der Klasse Startscreen(Quellcode s. u.) erzeugt und platziert wird. ???:L

Java:
package main;

import gameLogic.World;
import java3D.Universe;

import java.awt.BorderLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class Startscreen extends JFrame
{
	public Startscreen()
	{
		Universe universe = new Universe();
		getContentPane().add(universe, BorderLayout.SOUTH);
		new World(universe);
		this.setVisible(true);
	}
	

	/**
	 * @param args
	 */
	public static void main(String[] args) 
	{
		new Startscreen();
	}

}

Ist dies vllt auch der Grund wieso KeyListener nicht klappt?
 
T

Turakar

Gast
Dass du nichtssagende Codeschnipsel postest und der entscheidende Code in den NICHT geposteten Teilen liegen düfte.

Ich habe mich entschieden, den Code noch mal neu zu schreiben, vieles ist auf umständlichen und CPU-Lastigen Wegen programmiert.
 
Zuletzt bearbeitet von einem Moderator:
T

Turakar

Gast
So, habe jetzt alles nochmal neu geschrieben.
Soweit ich das beurteilen kann, klappt jetzt alles auch, abgesehen von der Kollision. Ich merke zwar, wann Elemente kollidieren, kriege aber nur den Wert null für das andere Element. Ich denke meine Sprite3D Klasse und die Klasset TestSprite reichen, ansonsten bitte hier posten.

Klasse Sprite3D (meine Hauptklasse für alle Grafikobjekte)
Java:
package bin.grafik;

import java.util.Enumeration;

import javax.media.j3d.Appearance;
import javax.media.j3d.Behavior;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Bounds;
import javax.media.j3d.Material;
import javax.media.j3d.Node;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
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;

public abstract class Sprite3D 
{
	TransformGroup tg;
	
	Transform3D toMove;
	Transform3D curr;
	
	Color3f color;
	public Vector3d pos;

	private BoundingSphere bounds;
	
	
	public Sprite3D(Color3f color, Vector3d pos, BoundingSphere bounds)
	{
		this.bounds = bounds;
		this.color = color;
		this.pos = pos;
		curr = new Transform3D();
		curr.set(this.pos);
		tg = new TransformGroup(curr);
		addChilds();
		tg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
		tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		
		toMove = new Transform3D();
	}

	abstract void addChilds();
	
	public void afterInit()
	{
		CollisionDetector myColDet = new CollisionDetector(this.tg, bounds);
	    tg.addChild(myColDet);
	}
	
	public Appearance getAp()
	{
		Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
		Color3f specular = new Color3f(0.9f, 0.9f, 0.9f);
		
		Material m = new Material(color, black, color, specular, 25.0f);
		m.setLightingEnable(true);
		
		Appearance ap = new Appearance();
		ap.setMaterial(m);
		
		return ap;
	}

	public TransformGroup getTG()
	{
		return tg;
	}
	
	public void setPos(Vector3d move)
	{
		tg.getTransform(curr);
	    toMove.setTranslation(move);
	    curr.mul(toMove);
	    tg.setTransform(curr);
	    pos = move;
	}

}

class CollisionDetector extends Behavior 
{
	/** The separate criteria used to wake up this behavior. */
	protected WakeupCriterion[] theCriteria;

	/** The OR of the separate criteria. */
	protected WakeupOr oredCriteria;

	/** The shape that is watched for collision. */
	protected TransformGroup collidingShape;

	/**
	 * @param theShape
	 *            Shape3D that is to be watched for collisions.
	 * @param theBounds
	 *            Bounds that define the active region for this behavior
	 */
	 public CollisionDetector(TransformGroup theShape, Bounds theBounds) 
	 {
		 collidingShape = theShape;
		 setSchedulingBounds(theBounds);
	 }

	 /**
	   * 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(collidingShape);
		 theCriteria[1] = new WakeupOnCollisionExit(collidingShape);
		 theCriteria[2] = new WakeupOnCollisionMovement(collidingShape);
		 oredCriteria = new WakeupOr(theCriteria);
		 wakeupOn(oredCriteria);
	 }

	 /**
	  * Where the work is done in this class. A message is printed out using the
	  * userData of the object collided with. The wake up condition is then set
	  * to the OR'ed criterion again.
	  */
	 public void processStimulus(Enumeration criteria) 
	 {
		 WakeupCriterion theCriterion = (WakeupCriterion) criteria.nextElement();
		 if (theCriterion instanceof WakeupOnCollisionEntry) 
		 {
			 Node theLeaf = ((WakeupOnCollisionEntry) theCriterion).getTriggeringPath().getObject();
			 System.out.println("Collided with " + theLeaf.getUserData());
		 } 
		 else if (theCriterion instanceof WakeupOnCollisionExit) 
		 {
			 Node theLeaf = ((WakeupOnCollisionExit) theCriterion).getTriggeringPath().getObject();
			 System.out.println("Stopped colliding with  " + theLeaf.getUserData());
		 } 
		 else 
		 {
		     Node theLeaf = ((WakeupOnCollisionMovement) theCriterion).getTriggeringPath().getObject();
		     System.out.println("Moved whilst colliding with " + theLeaf.getUserData());
		 }
		 wakeupOn(oredCriteria);
	 }
}

Meine TestSprite Klasse(Erbt von Sprite3D)
Java:
package bin.grafik;

import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Node;
import javax.media.j3d.Shape3D;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Color3f;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.geometry.Sphere;

public class TestSprite extends Sprite3D
{

	private Sphere sphere;
	
	public TestSprite(BoundingSphere bounds) 
	{
		super(new Color3f(0.1f, 0.5f, 0.7f), new Vector3d(0.0F, 0.0F, 0.0F), bounds);
	}

	@Override
	void addChilds() 
	{
		sphere = new Sphere(2.0F, this.getAp());
		tg.addChild(sphere);
	}

}
 

Marco13

Top Contributor
Es gibt nicht viele die sich "aktiv" mit Java3D beschäftigen. Ich tue das auch nicht, aber habe vor einigen Jahren mal ein bißchen was damit gemacht. Deswegen versuche ich üblicherweise hier zu helfen, wenn ich kann, auch wenn die Antworten oft nur Links auf "java2s.com" enthalten :D Aber nur durch Lesen einer bestimmten Klasse kann ich nicht erkennen ob oder was daran falsch ist.
 
T

Turakar

Gast
schade, hast du dich aber vllt schonmal mit Kollision auseinandergesetzt oder kennst ein gutes Tutorial?
 

Marco13

Top Contributor
Versuch' mal, bei den "SceneGraphPath"-Objekten, die man sich da als "getTriggeringPath" abholt, nach oben zu laufen, und jeden Knoten auszugeben
Java:
private static void printPath(SceneGraphPath path)
{
    for (int i=0; i<path.nodeCount(); i++)
    {
        System.out.println("At "+i+" node "+path.getNode(i));
    }
}
Vielleicht steht da was interessantes drin.
 
T

Turakar

Gast
Die Ausgabe der Konsole lautet:

Starting
Collided with null
At 0 node null
At 1 node null
At 2 node null
At 3 node null
At 4 node null
Collided with null
At 0 node null
At 1 node null
At 2 node null
At 3 node null
At 4 node null
Collided with null
At 0 node null
At 1 node null
At 2 node null
At 3 node null
At 4 node null
Shutting down

Ich denke das der TriggeringPath nicht klappt, oder?
 

Marco13

Top Contributor
Hm - der Path ist ja DA, er enthält ja Knoten. Aber... im Moment hab' ich so das Bauchgefühl, dass diese Knoten NICHT 'null' sind, auch wenn die Ausgabe das suggeriert. Lass' es mal im Debugger laufen, und setz' da nen Breakpoint, oder probier
Java:
private static void printPath(SceneGraphPath path)
{
    for (int i=0; i<path.nodeCount(); i++)
    {
        Node node = path.getNode(i);
        System.out.println("At "+i+" node "+node+" is null? "+(node==null));
    }
}
Wenn's nicht klappt: Ein KSKB hilft meistens.
 
T

Turakar

Gast
Ich bin leider erst am Sonntagabend wieder da, würde mich aber freuen wenn du dann wieder reinguckst!:toll:
 
Ähnliche Java Themen

Ähnliche Java Themen

Neue Themen


Oben