Punkt im 3D Raum anhand der Screen Koordinaten

Started by rushtone, December 21, 2012, 05:58:49 PM

Previous topic - Next topic

rushtone

Hi Egon,

vielleicht kannst du mir helfen..
Auch andere dürfen natürlich helfen, wenn sie möchten.. ;)

Du hast mir im englischen Unterforum zu der Methode
reproject2d3d(x,y,z) geraten, leider funzt das nicht so wie ich dachte.

Ich hab meinen Denkfehler dort übrigens noch nicht so recht verstanden, ich war der Meinung, wenn ich
einen Richtungsvektor habe und den mit meiner Distanz multipliziere, dann müsste das, dasselbe sein wie eine translation des Objektes.
Und ich müsste die gleiche koordinate bekommen.. Wo ist mein Denkfehler?
Ich würds gerne verstehen... Sonst lern ich ja nix dabei..

Ich würde gerne die sichtbaren bereiche der Kamera ermitteln, damit ich:

A:
Gegner kurz außerhalb des sichtbaren bereichs erscheinen lassen kann.

B:
Verhindern kann das mein Spielerobjekt außerhalb des sichtbaren bereichs gerät.
Momentan fange ich das durch feste x und y Koordinaten ab, was aber aufgrund der perspektivischen Verzerrung blöd ist, da
die x koordinate natürlich je nach z koordinate anders liegen.

(Meine Objekte bewegen sich alle gleichermaßen auf y und z Achse. (translate(x,y,-y)))

Ich dachte ich kann das einfach ermitteln indem ich über die Bildschirm Koordinaten über die Methode reproject
die jeweiligen maximalen und minimalen Welt Koordinaten ermittle und diese beim Start besetze.

vereinfacht dargstellt:

// Ist klar das das nicht funktioniert, das soll auch nur mein Problem deutlich machen..:
//links oben = letzte sichtbare X koordinate oben
topX = reproject(0, 0, screenHeight);

//rechts unten = letzte sichtbare Y koordinate rechts
bottomY = reproject(screenWidth, screenHeight, 0);


Kannst du mir da helfen?

(bin relativ neu bei dem 3D Kram, ich versuche soviel zu lernen wie möglich und bin auch dabei mich in das thema einzulesen..
Aber jeder hat ja mal klein angefangen, daher hoffe ich, dass ich hier richtig bin und dich nicht nerve.)

Gruß und Danke.


EgonOlsen

Naja, abgesehen davon, dass du die Transformationen der Kamera nicht berücksichtigt hattest...du berechnest eigentlich keinen Richtungsvektor, sondern einen Positionsvektor. Nämlich die Position im r3 (mit z=1), die, auf den Bildschirm projeziert, die Mauskoordinaten ergibt.  Das man es als Richtungsvektor betrachten kann, liegt nur daran, dass die Kamera im Cameraspace immer an (0,0,0) steht. Das deine Rechnung falsch ist, sieht man alleine schon, wenn man einfach mal mit z=1 rechnet. Du bekommst von der Methode eine Position (x,y,1) geliefert. Die interpretierst du als Richtungsvektor und normierst diesen, also (x,y,1)/len. Das multiplizierst du mit dem Abstand der Ebene vom Ursprung in z-Richtung. Bei dir sind das 20, aber im Beispiel mal einfach 1. Es müsste also gelten: ((x,y,1)/len)*1=(x,y,1) => (x,y,1)/len=(x,y,1) => len=1....und das ist ganz offenbar nicht richtig. Deine Method würde klappen, wenn du statt mit der Tiefe der Ebene mit dem Abstand vom Ursprung rechnen würdest. Aber den willst du quasi indirekt gerade ermitteln.

Was die Koordinaten angeht: Das funktioniert doch im Prinzip genauso, wenn dich jetzt richtig verstanden habe. Für x und y setzt du die Bildschirmgrenzen ein, für z die Tiefe im r3. Das musst du für z eigentlich auch nur für 1 und max machen. Die Ergebnisse für andere Werte von Z kannst du dann linear aus diesen interpolieren.

rushtone

Ok ich muss zugeben, ich muss noch ne Menge lernen.
Und so recht verstanden habe ich es immer noch nicht, mag daran liegen das ich matrizen und Vektoren nie in der Schule hatte.
Was ich weiß habe ich mir selbst angeeignet.

Was bei mir nun hängen geblieben ist, ist dass ich:
1. die Position der Kamera nicht einberechnet habe. Ok das macht Sinn.
2. vom Ursprung ausgehe, was koordinate 0,0,0 im WS ist richtig? Ich aber von der Kamera ausgehen müsste, richtig?
Oder bin ich total falsch grade?

Also hiermit kommt in etwa das raus was ich erwarten würde.
Da ich die Kamera auf -40 z sitzen habe und eine tiefe von 20 habe, muss ich bei der tiefe 60 angeben richtig?
40 um auf den Ursprung zu kommen + 20 für die tiefe..


//Kamera etwas raus
camera.setPosition(0, 0, -40);
.
.
.
SimpleVector position = Interact2D.reproject2D3D(camera, fb, x, y,60);
//Kamera Position berücksichtigen
position.add(world.getCamera().getPosition());
position.matMul(camera.getBack().invert3x3());



Kann man die Maximale tiefe auch berechnen?
Das mit dem interpolieren bekomm ich locker hin.

P.s. kannst du mir ein gutes Buch empfehlen damit ich das alles schnell drauf habe?

EgonOlsen

Nein, mit Ursprung meinte ich den Ursprung im Cameraspace. Dein Fehler ist irgendwie, dass du die Länge des Vektors von diesem Ursprung zur Position der Maus im r3 als Länge des Vektors vom Ursprung zu (0,0,z) annimmst. Und das ist falsch außer für einen Klick direkt in die Bildmitte.

Ja, Tiefe 60 scheint mir da ok zu sein. Als maximale Tiefe würde ich die hintere Clipebene erwarten. Aber letztendlich kommt das auf dein Anwendung an. Die maximale Tiefe ist der Wert für Z, an dem du maximal Einheiten erscheinen lassen willst.

Buch...weiß ich jetzt auch nicht.

rushtone

so nachdem ich bis gestern nach um 5 Uhr noch herumgegrübelt habe, dneke ich es auch verstanden zu haben.
Danke schonmal habe hier aufjedenfall etwas gelernt.

Eigentlich war es dumm auf die z Koordinate eingehen zu wollen, da kann man auch das reproject2D3DWS mit z = 1 verwenden und den Punkt einfach auf der Z Achse verschieben.
Aber das war mir an der Stelle irgendwie nicht klar.

Also das klappt nun, vielen dank..

Aber, wie immer gibt es ein aber.. ;)
Kann ich den auch den maximalen Z Wert ermitteln?

Wie bereits erwähnt: meine Objekte bewegen sich auf y und z Achse gleichermaßen.
Beispiel:
y=10, z=-10 -> y=100, z = -100 bzw. in Richtung 1,-1

Wenn ich nun über die reproject Methoden meine maximale y Koordinate auf z = 1 ermittel, könnte ich diesen Punkt auf der z Achse verschieben, wenn ich wüßte wo mein maximaler Z Bereich endet.

Ich könnte nun natürlich hergehen und ein Object an meiner Startposition auf dem selben weg zu verschieben, bis dieses nicht mehr sichtbar ist und mir dann das maximale Z auf diesem wege zu holen. Find ich aber blöd und unsauber.

Wie bekomme ich nun also auf der ebene auf der meine Objekte verschoben werden, den Punkt z an dem sie aus dem Bild verschwinden würden, also außerhalb des Frustum geraten?

Ggf. könnte man den Schnittpunkt den beide Vektoren bilden dazu verwenden?
(Ich werde mir mal Vektoren und Schnittpunkte anschauen derweil, hab noch keinen Schimmer wie das berechnet wird.)

Danke und Gruß.

EgonOlsen

Naja, weiß nicht...zmax ist halt der maximale z-Wert, den du benutzen willst. Im Prinzip ist es auch völlig egal. Du kannst irgendeinen z-Wert als zmax nehmen (nur nicht zmin...). Interpolieren kannst du ja immer, auch über zmax hinaus.

rushtone

#6
hätte hierzu nochmal eine frage..
ich hab mein spiel ein wenig umgestellt.
vorher war die camera auf 0/0/-40 und zeigte auf 0/0/0.
meine objekte haben sich auf x,y und z bewegt.

jetzt habe ich die camera auf 0/-15/-22.5 die cam zeigt auch auf 0/0/0.
meine objekte bewegen sich nun nurnoch auf x und z und y=0.

jetzt bekomm ich meine eckpunkte wieder nicht ordentlich hin.

ich werd wohl irgendwie die camera richtung mit einbeziehen müssen, die sich nun geändert hat.
magst du mir da nochmal helfen?
ich komm leider nicht drauf.


EgonOlsen

Wei sieht denn der Code momentan aus, der das macht?

rushtone

hier der code:

//1:
world.getCamera().setPosition(0, -15, -22.5f);
world.getCamera().lookAt(new SimpleVector(0,0,0));

PLAYFIELD_TOP_LEFT.set(get2D3DWS(0, 0, 23.5));

// Der hier funktioniert wunderbar mit --> world.getCamera().setPosition(0, 0, -22.5f); aber mit world.getCamera().setPosition(0, -15, -22.5f); nicht mehr.
public SimpleVector get2D3DWS(int x, int y, float z) {
SimpleVector position = Interact2D.reproject2D3D(camera, fb, x, y, z);
position.add(world.getCamera().getPosition());
position.matMul(camera.getBack().invert3x3());
return position;
}

Hiermit kommt auch nicht das gewünschte raus.

Interact2D.reproject2D3DWS(camera, fb, 0, 0)


Ich hab auch schon versucht camera.getDirection() mit einzubeziehen, aber wahrscheinlich nicht richtig.

EgonOlsen

Dreh mal das hier um:


position.add(world.getCamera().getPosition());
position.matMul(camera.getBack().invert3x3());


in


position.matMul(camera.getBack().invert3x3());
position.add(world.getCamera().getPosition());

rushtone