Java3D - Picking

TRX

Mitglied
Hi @All,

ich bin immer noch am programmieren meines Projektes (Satelliten Tracking) und hab Probleme mit dem Picking.

Ich will, dass er mir den Namen des Satelliten zurückgibt wenn ich auf den entsprechenden Satelliten klicke. Mir wurde gesagt, dass wäre mit Picking möglich...

Ich hab es jetzt schon soweit hingekriegt, dass er mir die Klasse des angeklickten Objects anzeigt, was mir aber nicht viel bringt da alle Satelliten über die gleiche Klasse erzeugt werden.

Gibts ne Möglichkeit das Ergebnis genauer zu bekommen, z.B die BranchGroup oder den Namen der Textur oder so etwas?

Gruß
TRX

P.S: Geht des überhaupt mit Picking oder muss ich da was anderes benutzen?
 
Zuletzt bearbeitet von einem Moderator:
Was ich grad auch noch bemerkt habe, ist dass ich weder die Appearance noch die Bounds auslesen kann obwohl ich beide Capability Flags gesetzt habe...

Fehler bei den Bounds:
Exception in thread "AWT-EventQueue-0" javax.media.j3d.CapabilityNotSetException: Node: no capability to read user bounds
at javax.media.j3d.Shape3D.getBounds(Shape3D.java:747)
at satsys.SatelliteSystem$MouseCmd.mouseClicked(SatelliteSystem.java:225)
at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:252)
at java.awt.Component.processMouseEvent(Component.java:6351)
at java.awt.Component.processEvent(Component.java:6113)
at java.awt.Component.dispatchEventImpl(Component.java:4714)
at java.awt.Component.dispatchEvent(Component.java:4544)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:635)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

Zudem kommt egal was ich anklicke, als Klasse javax.media.j3d.Shape3D ist das normal?
 
Zuletzt bearbeitet:
Wenn er sagt, dass die Capability nicht gesetzt ist, liegt das mit an Sicherheit grenzender Wahrscheinlichkeit daran, dass die Capability nicht gesetzt ist.
Und "fast alles", was man bei Java3D auf dem Bildschirm sieht, sind Shape3D-Objekte. Poste ggf. mal mehr Infos, am besten als KSKB...
 
das mit dem KSKB wird nicht ganz so einfach klappen, aber ich versuch mal ein bisschen code beispiele zu posten:
So wird des erste Satellit erzeugt ( ist im Moment einfach ne Kugel)
Java:
Appearance satAppear = new Appearance();
    	satAppear.setTexture(new TextureLoader("textures/" + satdatobj.getName() + ".png",satsys).getTexture());
    	
    	Sphere sat = new Sphere(0.006f, Sphere.GENERATE_NORMALS | Sphere.GENERATE_TEXTURE_COORDS ,100,satAppear);
    	sat.setPickable(true);
    	//sat.setCapability(Primitive.ENABLE_GEOMETRY_PICKING);
		//sat.setCapability(Primitive.ENABLE_PICK_REPORTING);
    	//sat.setCapability(Primitive.ALLOW_BOUNDS_READ);
    	sat.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
    	sat.setCapability(Shape3D.ALLOW_GEOMETRY_WRITE);
    	sat.setCapability(Shape3D.ALLOW_BOUNDS_READ);
    	sat.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
    	sat.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
		sat.setCapability(Shape3D.ENABLE_PICK_REPORTING);
		sat.setCapability(Geometry.ALLOW_INTERSECT);
		sat.setCapability(Appearance.ALLOW_TEXTURE_READ);



Das ist der MouseListener der ein PickCanvas aus der createScene Funktion übergeben bekommt:
Java:
class MouseCmd extends MouseAdapter {
		
		PickCanvas pickCanvas;
		
		
		public MouseCmd(PickCanvas pickCanvas){
			this.pickCanvas = pickCanvas;
		}
		
		public void mouseClicked(MouseEvent e) 
		{ 
		    pickCanvas.setShapeLocation(e); 
		    PickResult result = pickCanvas.pickClosest(); 
		    if (result == null) { 
		       System.out.println("Nichts ausgewählt"); 
		    } else { 
		       Primitive p = (Primitive)result.getNode(PickResult.PRIMITIVE); 
		       Shape3D s = (Shape3D)result.getNode(PickResult.SHAPE3D); 
		       if (p != null) { 
		          System.out.println(p.getClass().getName()); 
		       } else if (s != null) { 
		             System.out.println(s.getClass().getName());
		             System.out.println(s.getAppearance());
		             //System.out.println(s.getBounds());
		       } else{ 
		          System.out.println("null1"); 
		       } 
		    } 
		} 

	}

Wenn ihr noch weitere Infos braucht einfach sagen...

Ich benötige irgendwie den Namen des Satelliten, also habe ich mir gedacht, dass ich mir die Appearance hol, weil da in der Textur der Name steckt...
Oder geht des auch einfacher?
 
Es gibt eine Methode die heißt setUserData().Mit der kann man jeden Knoten im Scenegraphen ein Java Object injezieren.In deinen Fall würde es ja ausreichen wenn dies ein String ist.Also beim erstellen des Satelliten so etwas machen wie setUserData("satellit 1") machen und dann beim Picking getUserdata() auf das Pickingergebnis anwenden.
 
@aze:
deine idee klingt schon mal gut, habs jetzt auch mal implementiert, allerdings liefert es immer null zurück egal was ich anklicke.
(hab werte bei der erde und bei den satelliten gesetzt)

Hast du ne ahnung an was das liegen könnte?

Anfügung:
ich hab mir jetzt ma den Scenegraphpath des results ausgeben lassen:
result.getSceneGraphPath();

Folgende Ausgabe bei klicken auf verschiedene Objekte:
javax.media.j3d.Locale@64e265d0 : javax.media.j3d.Shape3D
LocalToVworld Transform:
0.13222459242574738, -0.010019782759938367, -0.9911691384982124, 0.0
0.7781035739310648, 0.6205183907259516, 0.09752822671708536, 0.0
0.6140614671134714, -0.7841278790633062, 0.08984422008194051, 0.0
0.0, 0.0, 0.0, 1.0

javax.media.j3d.Locale@64e265d0 : javax.media.j3d.Shape3D
LocalToVworld Transform:
0.13878298501550007, -0.010019782759938367, -0.9902721277626828, 0.0
0.7774409128170997, 0.6205183907259516, 0.10267693922682905, 0.0
0.6134532664745556, -0.7841278790633062, 0.09390718357707749, 0.0
0.0, 0.0, 0.0, 1.0

javax.media.j3d.Locale@64e265d0 : javax.media.j3d.Shape3D
LocalToVworld Transform:
0.15186746775235, -0.010019782759938367, -0.9883500777517714, 0.0
0.7760149889026161, 0.6205183907259516, 0.11294982854943941, 0.0
0.6121576669755606, -0.7841278790633062, 0.10201205830057376, 0.0
0.0, 0.0, 0.0, 1.0

javax.media.j3d.Locale@64e265d0 : javax.media.j3d.Shape3D
LocalToVworld Transform:
0.1687115420195186, -0.010019782759938367, -0.9856145390277276, 0.0
0.7739744992168653, 0.6205183907259516, 0.12617607274312226, 0.0
0.6103276907951979, -0.7841278790633062, 0.11244367089473051, 0.0
0.0, 0.0, 0.0, 1.0

Ist da alles in Ordnung
 
Zuletzt bearbeitet:
Probiere mal statt :

Java:
Shape3D s = (Shape3D)result.getNode(PickResult.SHAPE3D);

dies hier

Java:
BranchGroup bg = (BranchGroup)result.getNode(PickResult.BRANCHGROUP);

Dann sollte es funktionieren.

ansonsten könnte es helfen jedem Shape3D Objekt einen String zu injezieren der den Satelliten beschreibt.
 
habs mal so probiert:
System.out.println(result.getNode(PickResult.BRANCH_GROUP).getUserData());
liefert aber eine NullPointerExeption
 
Ich glaub du must beim Konstruktor vom MouseCmd neben dem Canvas auch noch eine Branchgroup angeben auf der das Picking erfolgen soll,in deinen Fall aso wohl die gesamte Scene !
 
hab ich eigentlich gemacht:
Java:
// Picking
        PickCanvas pickCanvas = new PickCanvas(canvas, objRoot); 
        pickCanvas.setMode(PickCanvas.BOUNDS); 

	canvas.addMouseListener(new MouseCmd(pickCanvas));

ich weiß allerdings nicht ob es hinderlich ist, wenn man wie ich die einzelnen Satelliten in einzelne BranchGroups packt und diese dann an die "Root" BranchGroup hängt.
 
Vlt hilt es statt

Java:
pickCanvas.setMode(PickCanvas.BOUNDS);

das hier zu verwenden:

Java:
pickCanvas.setMode(PickCanvas.GEOMETRY);

Ansonsten weiss ich leider auch nicht mehr weiter
 
funktioniert leider auch nicht....

So langsam verzweifel ich an dem Scheiß!

Gibts doch nciht das des so schwierig ist..


Hat noch jemand ne Idee worans liegen könnte?

Anfügung:
Hab jetzt einen Teil des Fehlers entdeckt...
Er gab mir immer null aus, weil ich bei dem einzigen Shape3d Objekt das ich in meiner Programmierung keinen Wert gesetzt hatte.
Diese Objekt ist die Umlaufbahn..
Wenn ich also der Umlaufbahn des Satelliten einen Wert zuweise gibt er mir, egal wohin ich klicke ( ob umlaufbahn oder die leere des raums oder die erde) den wert einer namen einer bahn aus ...
Dabei will ich dass er nur einen Wert ausgibt wenn ich auf die Sphere klicke...
Aber anscheinend überlagern die Sphere3d der Umlaufbahnen alles andere..
Kann man das verhindern?
 
Zuletzt bearbeitet:
Gelöst!

Für alle die so ein Problem auch mal haben sollten:
Mein Problem war dass andere Objekte die eigentlichen Objekte die ich picken wollte überlagert haben und ich sie deshalb nicht picken konnte.
Lösung:
alle unnötigen Objekte vom Picking ausschließen per:
objekt.setPickable(false);


Danke an Alle für die Unterstützung!
 

Neue Themen


Zurück
Oben