Autor Beitrag
knittel
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: Di 19.02.13 14:09 
Hallo allerseits,

Ich bin mal wieder am verzweifeln, hab sogar schon in einem anderen Forum um Hilfe gesucht, aber bisher doch noch keine bekommen. :/
Ich will das wenn ich an einen Ort klicke, ein Objekt an diesem Punkt erscheint, so wie in einem Leveleditor.

Das funktioniert prima, solange ich die Kamera nicht drehe, bzw. nur geringfügig drehe. Die Objekte erscheinen wie geplant auf der xz-Ebene. Sobald ich aber anbfange mich um 90° nach links oder nach recht zu drehen, passiert folgendes: Wenn ich an einen Punkt klicke erscheint der Busch nicht dort, aber in der gleichen xz-Richtung nur mit größerer Entfernung weiter hin. Den folgenden Code verwende ich für die Positionierung des Objektes.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
procedure TestClick(X, Y: Integer);
var ParX, ParY: double; Projection, Rotation, pVX, pVY, pVZ, FinalPosition: TMeleePosition; Perspective: TMeleeMatrix; ViewVector: TMeleePosition; i: integer;
begin
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  gluPerspective(45.01920/10800.0110000);
  glMatrixMode(GL_MODELVIEW); // Modellmatrix laden, da diese als default aktiviert sein soll.
Projection := MyCamera.ExportPerspectiveToXYZ(); // Läd den X,X-Wert der Projektions Matrix in Projection.X und den Y,Y-Wert der Projektions Matrix in Projection.Y
Perspective := MyCamera.ExportToMatrix(); // Lädt die Modelview Matrix der Camera in Perspective.
Rotation := MyCamera.Rotation; // unwichtig, hab ich zu Test-Zwecken eingebaut und entferne ich am Ende wieder.
pVX := meGetXVector(Perspective); // 0. Spalte (X-Achse) der Modelview Matrix in X-Achsen Vektor einlesen.
pVY := meGetYVector(Perspective); // 1. Spalte (Y-Achse) der Modelview Matrix in X-Achsen Vektor einlesen.
pVZ := meGetZVector(Perspective); // 2. Spalte (Z-Achse) der Modelview Matrix in X-Achsen Vektor einlesen.
ParX := (X / 960 - 1); // Hier rechne ich aus, wie viel % des X-Vektors an den Z Vektor angehängt werden müssen damit dem angeklickten Punkt entspricht.
ParY := -(Y / 540 - 1); // X, Y sind hierbei die auf dem Bildschirm angeklickten Koordinanten, von oben, links. Daher auch das Minus vor dem Y.
ViewVector := meCalculate(PVZ, me_Add, meCalculate(
meCalculate(PVX, me_Multiply, ParX / Projection.X),
me_Add,
meCalculate(PVY, me_Multiply, ParY / Projection.Y)));
// Hier passiert letztendlich nur das die Vektoren PVZ, PVY, PVX nach folgender Formel zum Angeklickten Richtungsvektor addiert werden.
// 1 * PVZ + (ParX / Projection.X) * PVX + (ParY / Projection.Y) * PVY
// erst der komplette Z-Vektor, dann je nachdem wie weit man nach rechts geklickt hat der ParX Wert multipliziert mit dem X-Wert aus der Projektionsmatrix und das selbe mit dem y-Vektor.
 
 
ViewVector := meNormalize(ViewVector); // Brauch man eigentlich nicht aber beim Testen hab ich es einfach mal eingebaut.
// Ab hier dann einfach Schnittpunkte Gerade mit Ebene (z = 0).
FinalPosition.Y := 0// Schnittpunkt mit der X-Z Ebene ermitteln, wobei (-MyCamera.Position.Y / ViewVector.Y) dem Vielfachen des Vektors entspricht um Y = 0 zu erfüllen.
FinalPosition.X := MyCamera.Position.X + (-MyCamera.Position.Y / ViewVector.Y) * ViewVector.X ; 
FinalPosition.Z := MyCamera.Position.Z - (-MyCamera.Position.y / ViewVector.y) * ViewVector.Z;
i := random(length(MyPosArray)); // Zu Testzwecken habe ich bereits Objekte und positioniere nur ein zufälliges von ihnen, am Zielpunkt.
MyPosArray[i].X := FinalPosition.X; // Nicht wundern, dass hier Y fehlt, das bleibt standardmäßig auf Null.
MyPosArray[i].Y := FinalPosition.Z; // Diese Zeile ist auch so geplant mit Y := Z. MyPosArray speichert nur die Koordinate auf der Karte (2 Dimensional).
end;


Wie bereits gesagt, sobald ich die Kamera um mehr als 90° nach nach links oder rechts drehe, werden die Objekte weiter weg als mein eigentlicher Mausklick gesetzt. Solange ich nur weiter nach oben oder nach unten schaue funktioniert die Funktion auch noch.
Wenn ihr mir irgendwie helfen könntet wäre ich sehr dankbar. :)

_________________
"Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."
Gammatester
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 328
Erhaltene Danke: 101



BeitragVerfasst: Di 19.02.13 14:28 
Welchen Wert hat denn in den fraglichen Fällen die Komponente ViewVector.Y bevor Du dadurch dividierst, bzw. wie werden an der Stellen Überlauf oder Division durch 0 behandelt? Kann es sein, daß an der Stelle mit fehlerhaften/rundungsverseuchten Werten falsch gestreckt wird?
knittel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: Di 19.02.13 17:38 
ViewVector.Y = 0 würde ja genau dann zutreffen, wenn ich direkt auf den Horizont klicke, was sobald ich die Kamera auch nur ein kleines bisschen drehe, sehr unwahrscheinlich wird, dass bei der ganzen Berechnung als ViewVector.Y = 0 herauskommt. Und zumal würde ansonsten alles stimmen, dann sollte bei einem normalen Klick auf den Boden, dieser Fehler auf jeden Fall nicht auftreten. Aber dort entsteht ja bereits diese Streckung.

Ich habe mal das Programm angehängt, damit ihr seht wie genau die Verzerrung aussieht, wenn man die Kamera nach links oder rechts dreht. Vielleicht hilft euch das ja weiter.

EDIT: Ich habe sicherheitshalber eine Überprüfung eingebaut, ob ViewVector.Y = 0 ist und dann ein showmessage eingefügt. Die Nachricht wurde bei den Problemfällen nicht angezeigt.
Einloggen, um Attachments anzusehen!
_________________
"Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."
Bergmann89
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: Di 19.02.13 18:05 
Hey,

du musst das nicht selber berechnen. Für sowas gibt es gluUnProject ;)

MfG Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
knittel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: Di 19.02.13 19:24 
glReadPixels gibt als Z Value bei mir immer 0.997 zurück. Irgendeine Idee warum?
Ich rufe die Funktion bei einem OnMouseDownEvent auf.
AmEnde eines Framedurchlaufs verwende ich: SwapBuffers(GraphicDevice);
falls das was hilft?

Weiterhin will ich später auch noch den Framebuffer für Post-Effects benutzen, weswegen dann das ReadPixels wahrscheinlich dann auch nichts mehr bringt.

Mein Code funktioniert ja auch, nur dann halt nicht wenn ich die Kamera zu weit nach links oder rechts drehe.

_________________
"Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."
Bergmann89
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: Di 19.02.13 20:04 
Hey,

kann sein das der ReadBuffer nicht richtig initialisiert ist, den kann man mit glReadBuffer setzen. Die Post-Effekte sind auch kein Problem, du musst den Buffer nur vorher auslesen. Mit glSwapBuffers hat das nix zu tun, du kannst das wenn du willst auch komplett Off-Screen machen.

MfG Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
knittel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: Mi 20.02.13 11:03 
Rein theoretisch wenn ich doch sowieso nur den Richtungsvektor ermitteln will, kann ich doch eigentlich einen beliebigen Wert für den Tiefenwert einsetzen, oder nicht?

EDIT: OK. Funktioniert jetzt bei mir! Musste vorher nur noch die KameraMatrix auf den Ursprung transformieren, damit die ermittelten Raumkoordinaten von glUnproject auch tatsächlich dem Richtungsvektor entsprechen. Funktioniert auf jeden Fall jetzt perfekt! :) War leider irgendwie ein bissl blöd mit dem gluUnproject, weil das immer doubles haben will und ich alles in floats halte. ;)

_________________
"Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."
Mr_Emre_D
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 114
Erhaltene Danke: 14



BeitragVerfasst: Mi 20.02.13 12:02 
Ich bin gedanklich nicht sehr auf dein Code eingegangen, aber dank deiner geuploadeten Anwendung und dieser Stelle
Zitat:
ausblenden Delphi-Quelltext
1:
// Ab hier dann einfach Schnittpunkte Gerade mit Ebene (z = 0).					

kann ich sagen, dass die Ebene nicht richtig ist. So wie ich das gesehen habe, handelt es sich bei dir um die IdentityKorrekt-Bewegete-Jedoch-nicht-Rotierte-XZ-Ebene.. das darf aber nicht sein.
Da gehört die Rotation rein. Also die Matrix gehört da noch angepasst. Wo genau das geschehen muss in deinem Code.. kA

Edit: Du verwendest "ViewVector".. Ich würde kucken, ob da die Berechnung nu wirklich korrekt ist!
knittel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: Mi 20.02.13 19:01 
Upps... Mein Kommentar an der Stelle war da auch nicht richtig. Wäre eigentlich Schnittpunkt mit y = 0 Ebene, weil ja diese dann der XZ Ebene entspricht.
Die Schnittpunktbildung von der y = 0 Ebene und einer Gerade ist ja jetzt wirklich net schwer und den teil des codes hab ich schon gut genug überprüft.

Ich glaube wie du sagts, das am ViewVector was net gestimmt hat. Den hab ich mir jetzt aber von der gluUnprojectFunktion ausrechnen lassen, der ja standardnäßig bei OpenGL dabei ist, daher funktioniert es jetzt auch. Aber danke, dass du noch versucht hast meinen Code zu retten! :zustimm:

_________________
"Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."
Bergmann89
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: Mi 20.02.13 23:44 
Hey,

nochma als kleine Ergänzung: Selbst wenn du den Richtungsvektor der Kamera für deine Berechnungen nutzen würdest, dann hättest du trotzdem an manchen Punkten falsche Ergebnisse. Das liegt daran, das du den Öffnungswinkel der Kamera noch mit den geklickten Punkt verrechnen musst. Der Vektor der dann daraus resultiert ist nicht parallel zu der Blickrichtung der Kamera. Zumindest ist das bei nicht-orthogonalen-Projektionsmatricen so.

MfG Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
knittel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: So 24.02.13 00:49 
Das war mir schon klar. Deswegen hatte ich in meinem Original Quelltext als Richtungsvektor von dem Kamera aus.

1 * Z-Achsenvektor + r * X-Achsenvektor + s * Y-Achsenvektor

mit

r = (X-Wert des geklickten Punktes auf -1 (linker Rand) bis +1 (rechter Rand) gestreckt) * Projektionsmatrix[0] bzw [0,0]
s = (Y-Wert des geklickten Punktes auf -1 (unterer Rand) bis +1 (oberer Rand) gestreckt) * Projektionsmatrix[5] bzw [1,1]

Die Multiplikation mit dem Wert aus der Projektionsmatrix haben ich nach diesem Artikel entsprechend ausgewählt: wiki.delphigl.com/index.php/gluPerspective

_________________
"Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."