# j3d Koordinaten bestimmen



## bob_sheknowdas (19. Apr 2012)

Hallo,
da das forum hier ganz hilfreich zu sein scheint setll ich euch mal weiter meine probleme vor^^

Ich möchte gerne die exacten Koordinaten einer Sphere bestimmen. Die Sphere spawnt zwar im Nullpunkt des Koordinatensystems, bewegt sich danach aber unvorhersehbar, und ich wüsste gerne zu jedem Zeitpunkt, wo sie sich gerade befindet.
Bislang nutze ich folgendes (sehr umständliches Verfahren)


```
public Float getX(){		
		Transform3D tempTransform1 = new Transform3D();
		Vector3f tempVector1 = new Vector3f();
		sphere.getLocalToVworld(tempTransform1);
		tempTransform1.get(tempVector1);
		return tempVector1.x;
	}
```

Das hat sich allerdings als nicht sehr zuverlässig in Sachen Genauigkeit herausgestellt. Irgendwie orientiert sich der so ermittelte Punkt zwar an meiner Sphere (wenn die sich nach links bewegt, bewegt sich der Punkt auch nach links), aber er gibt eben nicht die exakte Position der Spehre an...

Kennt ihr vllt ein besseres Verfahren?


----------



## Marco13 (19. Apr 2012)

Eigentlich ist das so richtig... Auch wenn er nur die x-Koordinate liefert. Wie äußern sich die "Fehler" denn?


----------



## bob_sheknowdas (20. Apr 2012)

Marco13 hat gesagt.:


> Eigentlich ist das so richtig... Auch wenn er nur die x-Koordinate liefert. Wie äußern sich die "Fehler" denn?



Ich habe eine vergleichbare Funktion auch für Y und Z erstellt.


Der Sachverhalt ist folgender:
Ich will einen kleinen Shooter programmieren. Die Sphere repräsentiert derzeit noch den vorderen Teil der Spielfigur, aus dem die Geschosse abgefeuert werden sollen. ( Dafür brauch ich logischer Weise jeder Zeit die Koordinaten der Sphere um die Kugel ein Stückchen davor spawnen zu lassen).

Wenn sich die Sphere nur ein Stückchen in z Richtung bewgt klappt das auch. Bewegt sie sich aber zu weit, oder bewegt sich gar in x oder y Richtung verscheibt sich der Spawnpoint immer weiter von der Sphere weg in unvorhersehbarer Richtung...



Edit: 
Ok, also nur die z Koordinate wird falsch bestimmt. Je länger das game läuft, desto weiter entfernt sich der Bulletspawnpoint in z richtung von der geplanten Position. y und x koordinate scheinen aber zu stimmen...


----------



## bob_sheknowdas (20. Apr 2012)

Edit2:
Nur die Koordinate in Bewegungsrichtung wird falsch bestimmt. Wenn sich die Sphere nur in y-Richtung bewegt, entfernt sich der tatsächliche Spawnpoint auch nur in y-Richtung vom geplanten Spwanpoint.


----------



## Marco13 (20. Apr 2012)

Hmja, etwas präziseres/nachvollziehbareres wäre nicht schlecht... Wie wird denn die Kugel animiert? Gibt's ein KSKB?


----------



## Spacerat (20. Apr 2012)

Liegt es vllt. an [c]sphere.getLocalToWorld()[/c]? Wenn die View nicht im Ursprung liegt, sind lokale und Weltkoordinaten der Kugel mit Sicherheit verschieden. Das Bullet-Objekt müsste logischerweise auch an "localToWorld"-Koordinaten gespawnt werden, seine Koordinaten also mit dem Differenzvektor der Kugel ("Ursprung -> Kugel" - "Ursprung -> Welt") aufaddiert werden.


----------



## bob_sheknowdas (23. Apr 2012)

Spacerat hat gesagt.:


> Liegt es vllt. an [c]sphere.getLocalToWorld()[/c]? Wenn die View nicht im Ursprung liegt, sind lokale und Weltkoordinaten der Kugel mit Sicherheit verschieden. Das Bullet-Objekt müsste logischerweise auch an "localToWorld"-Koordinaten gespawnt werden, seine Koordinaten also mit dem Differenzvektor der Kugel ("Ursprung -> Kugel" - "Ursprung -> Welt") aufaddiert werden.



Könntest du das vllt genauer dastellen? Eventuell an 5 Zeilen Code?


----------



## Spacerat (23. Apr 2012)

In 5 Zeilen Code? Leider nein, weil Java3D 
Aber 'ne Zeichnung kann ich bieten (siehe Anhang).

Zum besseren Verständnis:
Jedes Objekt in 3D-Welten hat eigene Koordinaten, welche sich auf einen Punkt (Ursprung bzw. Identität) beziehen (LocalToWorld), Auch die Viewplatform oder auch Kamera-Objekt genannt hat solche Koordinaten. Selten liegt aber mal ein Objekt im Ursprung einer 3D-Welt, am allerwenigsten ein Kamera-Objekt. Daraus ergibt sich ein ständiger Differenz-Vector zwischen LocalToWorld- und LocalToView-Koordinaten. Wenn man nun ein neues Objekt erscheinen lassen will, muss man schon wissen, mit welchem Ursprung man arbeitet - mit den Koordinaten der View oder jenen des Ursprungs - sprich Kamera- oder Welt-Relativiert.


----------



## bob_sheknowdas (24. Apr 2012)

Hmm, irgendwie glaube ich nicht, dass das das Problem ist.

Leider bin ich nicht in der Lage ein *K*SKB zu erstellen, deswegen habe ich euch mal mein gesammte Projekt hochgeladen, soweit wie es bislang ist.

Ich schätze ihr versteht das problem am besten, wenn ihrs selbst mal ausprobiert.

Ausführbare Klasse ist "Start". Steuerung mit Pfeiltasten, schießen mit Leertaste (macht den ersten Schuss so früh wie möglich, sonst seht ihr die Kugel gar nicht mehr, weil sich der Spwanpoint zu weit von euch entfernt hat^^)

Achja, und wenn ihr in irgendwas reinfliegt (wahlweise auch eure eigenen Geschosse) bricht das Spiel komplett ab


----------



## Spacerat (24. Apr 2012)

Hilfeeeee... Java 3D OMG...
Naja, ich hab's angefangen und führe es zu Ende. 
Denn im Prinzip ist es ja wie ich sage. Mir war das nur mit den TransformGroups entgangen, hab' Java3D schon lange nicht mehr gehabt.
Also zunächst einmal, bewegst du die Welt (Kamera) und nicht das Flugzeug, aber das halt Ego-Perspektive. Den besagten Differenzvektor berechnest du alledings schon (mv), fatalerweise benutzt du ihn auch, wie ich es gesagt habe.
Aber in diesem Fall brauchst du zur Position des Flugzeugs eigentlich nur den Wert hinzuzählen in welche Richtung du feuern willst (+/- z) und das mit der View-Transform multiplizieren.
Eigentlich... denn du machst noch einen fatalen Fehler. Beim adden von Objekten in die Welt (create3DObjectXXX) erhalten diese fixierte Positionen != Ursprung. Das bedeutet der Fixpunkt (PVot) dieser Objekte liegt ausserhalb statt in deren Mittelpunkt. Solche Objekte dann auch noch bewegen wollen... viel Spass.
Aber ich werd's mir noch mal anschauen...
BTW.: Was hälst du eigentlich von gut durch dokumentiertem Quelltext? Gar nichts? Dann sind wir ja schon 2.


----------



## Spacerat (24. Apr 2012)

Sooo, bitte hier ist mal meine Version. Viel Spass damit.


----------



## bob_sheknowdas (25. Apr 2012)

Haha  

also 2 Dinge:
1. kann ich dein jar-File nicht öffnen (an mir liegts nicht, andere jar-Files funktionieren problemlos)
2. ist es ja sehr nett, wenn du alles fertig programmiert hast. Aber das bring mir nix, wenn ich den Code nicht einsehen kann.^^
Es wäre also sehr nett, wenn du entweder den Code posten könntest, oder wie ich ein zib-File hochlädst


----------



## Spacerat (25. Apr 2012)

Hmmmm... 
Was soll der Schwachfug... :lol: Nimm' dies und stör' mich nicht beim in der Gegend rum ballern. XD


----------



## bob_sheknowdas (25. Apr 2012)

Sehr nice, vielen Dank. :toll:

Aber ich verstehe den Code noch nicht so ganz. Was bewirkt z.B. das 'count' in der Bullet-Klasse? Oder trans.mul(copy) in selbiger? Und wo im Code werden jetzt die Spawnpoints der Bullets definiert (und vor allem wie)?




PS: So ganz koscher ist das übrigens immer noch nicht (wenn man in der Drehung schießt passieren ganz misteriöse Dinge). Aber ich denke das Problem kann ich selbst beheben, wenn ich erstmal deinen Code verstanden haben^^


----------



## Spacerat (25. Apr 2012)

Erstmal zum "count"...
Sicher ist dir dies
	
	
	
	





```
for(Enumeration<Bullet> e = bullets.getAllChildren(); e.hasMoreElements();) {
        	Bullet b = e.nextElement();
        	if(b.move()) {
        		bullets.removeChild(b);
        	}
        }
```
 bei "updateMovement" aufgefallen. Dort wird über eine Reihe (Enumeration) Bullets iteriert (richtig..., einzelne Bullets bewegen sich jetzt unabhängig) und deren "move()"-Methode aufgerufen. Liefert diese Methode true zurück, wird das Bullet aus der Gruppe entfernt und im folgenden nicht mehr beachtet. In besagter "move()"-Methode wird count heraufgezählt. Solange wie die Vorgabe nicht erreicht wurde, wird die Bullet bewegt, ansonsten entfernt. Count ist also so 'ne Art Reichweite. Werden die Bullets nach einer Zeit nicht entfernt, füllst du nicht nur den Weltraum damit, sondern auch deinen Speicher, deswegen hab' ich's so gemacht.
Der Spawnpoint eines Bullets ist immer der selbe - oh Wunder - nämlich 1.0 Einheiten vor dem Flugzeug durch "new Vector3f(0,0,-1)". Dieser Vector wird an eine TranslationMatrix übergeben, deren Wert sich zur Bullet-Lebenszeit nicht mehr ändert (könnte man als Konstante für alle Bullets definieren). Dem Konstruktor von Bullet wird die augenblickliche View-Matrix (Abstand View zum Flugzeug) übergeben. Damit wird eine Lokale Bullet-Matrix initialisiert (this.trans.mul(trans)) und anschliessend wird diese lokale Matrix noch mit der konstanten TranslationsMatrix multipliziert (this.trans.mul(copy)). "<Bullet>.trans" enthält nun den "Spawnpoint" des Bullets. Mit jedem durchlauf von "<bullet>.move()" wird diesem Point erneut der Bewegungsvektor (welcher immernoch 0,0,-1 ist) aufmultipliziert (trans.mul(copy)).
Mit <Transform3D>.mul() kann man also 2 Transformationsmatritzen miteinander multiplizieren. Für Laien ausgedrückt: Damit bewegt man Objekte um einen definierten Vektor.


bob_sheknowdas hat gesagt.:


> So ganz koscher ist das übrigens immer noch nicht (wenn man in der Drehung schießt passieren ganz misteriöse Dinge). Aber ich denke das Problem kann ich selbst beheben, wenn ich erstmal deinen Code verstanden haben^^


Tja... ich weis... liegt aber nicht an meinem Code, sondern eher daran, dass ich "Anfängerpfusch" (Sorry dafür, wirst' aber mit steigender Erfahrung noch selbst drauf kommen.) nur selten ganz durchschaue. Wenn du deinen alten Code noch hast, kannst ja mal vergleichen, was alles anders ist.


----------



## Spacerat (25. Apr 2012)

Damit's ein wenig besser wird, führen wir die "move()" mal vor "fire()" aus, etwa so:
	
	
	
	





```
private void updateMovement() {
        if (pressedKeys.contains(upKey)&& !pressedKeys.contains(downKey)){
            rotate(-speed, 0);
        }
        if (pressedKeys.contains(downKey)&& !pressedKeys.contains(upKey)){
            rotate(speed, 0);
        }
        if (pressedKeys.contains(leftKey)&& !pressedKeys.contains(rightKey)){
            rotate(0, speed);
        }
        if (pressedKeys.contains(rightKey) && !pressedKeys.contains(leftKey)) {
            rotate(0, -speed);
        }
        move();
        if(pressedKeys.contains(space)){
        	fire();
        }
        for(Enumeration<Bullet> e = bullets.getAllChildren(); e.hasMoreElements();) {
        	Bullet b = e.nextElement();
        	if(b.move()) {
        		bullets.removeChild(b);
        	}
        }
    }
```


----------



## bob_sheknowdas (25. Apr 2012)

ja, da bin ich auch schon drauf gekommen^^

vielen dank natürlich trotzdem. Ich denke, damit kann ich das Thema abhaken.


----------

