PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Mousekoordinaten -> Mapkoordinaten


Gast
2004-06-07, 03:10:28
Hallo,

ich hätte da mal ein ganz allgemeines Programmierproblem: ich habe eine um 45° gedrehte 2D-Isomap wie z.b.
http://mitglied.lycos.de/peinig3r/rautenmap.png sowas hier (hab das mal um die Hälfte verkleinert, damit's hier reinpasst)

Meine Frage ist nun: wie kann ich, wenn man irgendwo in die Map klickt, anhand der Mousekoordinaten am einfachsten bestimmen, in welches Feld geklickt wurde? Sprich, ich will die Pixelkoordinaten in Koordinaten für mein Map-Array umwandeln, weiß allerdings nicht, wie genau ich das anstellen soll, da ja alles um 45° gedreht ist.

Da gibt es doch sicher irgend eine Formel für oder so, kann mir jemand weiterhelfen?

Matti
2004-06-07, 15:14:54
wenn man OpenGL verwendet, gehts mit gluUnproject. Wenn nicht, mußte dir eben eine Berechnung selber überlegen. Bin jetzt zu faul für dich nachzudenken ;)

Gnafoo
2004-06-07, 18:26:00
Also ich hätte das folgendermaßen gemacht:
(Ich mach das einfach mal ausführlich, weil ich nicht weiß, wie gut du dich bereits auskennst)

Du definierst dein Spielfeld mit drei Vektoren: ein Vektor definiert den Ursprung des Feldes, die anderen zwei definieren die Richtung der X- und Y- Achse.

Der Ursprung müsste die Linke Ecke des Feldes sein. Die anderen zwei Vektoren erhältst du, indem du von der oberen Ecke bzw. der unteren Ecke den Ursprung subtrahierst und den Vektor normalisierst.

Beispiel:
Linke Ecke O(0; 0,5)
Obere Ecke U(0,5; 0)
Untere Ecke L(0,5; 1)

Xv = U-O = (0,5; -0,5)
Yv = L-O = (0,5; 0,5)

Normalisiert: (durch die Länge l=sqrt(x²+y²) geteilt)

Xv' = (0,7071...; -0,7071...)
Yv' = (0,7071...; 0,7071...)

Ich nehme einfach mal an, der User klickt jetzt auf den Punkt P(0,7; 0,6).
Daraus kann man einen neuen Vektor v konstruieren (roter Strich in der Mitte):
v = P-O = (0,7; 0,1)

Die Frage ist jetzt, wie weit sich der Vektor v in Richtung der X- bzw. Y-Achse ausdehnt (Xv und Yv). Dafür kann man wunderbar das Punktprodukt benutzen.

Das Punktprodukt zweier Vektoren A und B ist definiert als:
A.B = |A|*|B|*cos(phi)

Wenn A ein Einheitsvektor ist (|A|=1), dann gibt das Ergebnis an, wie weit sich B in Richtung von A ausdehnt. (Siehe auch z.b.: http://htc.physik.hu-berlin.de/~mitdank/dist/scriptenm/skalarprodukt.htm)

Wir machen also:
Xp = Xv'.v
Yp = Yv'.v

und haben damit die X und Y Koordinaten unseres Punktes auf dem Feld. Wenn wir diese auf Werte zwischen 0 und 1 bringen wollen, müssen wir sie durch die entsprechende Kantenlänge teilen.

Bei den Werten von vorhin wäre das:
Xp = 0,7071...*0,7-0,7071...*0,1 ~= 0,339
Yp = 0,7071...*0,7+0,7071...*0,1 ~= 0,566

und durch die Kantenlänge:
Xp' = Xp/|Xv| = 0,339/sqrt(0.5²+(-0,5)²) ~=0,564
Yp' = Yp/|Yv| = 0,566/sqrt(0.5²+0,5²) ~= 0,8

Also bei 15 Feldern:
Xf = Xp'*15 ~= 8,46
Yf = Yp'*15 ~= 12

Hm ist einiges mehr geworden, als ich gedacht habe, aber egal. Ich hoffe mal ich habe keinen Fehler gemacht :) Ich hab das ganze Zeug auch nur aus Tutorials etc. erlernt :D

Gast
2004-06-09, 09:56:23
Wow, danke für die ausführliche Beschreibung :)
einigermaßen seh ich sogar durch ;) ich werd mal versuchen das ganze umzusetzen

Wenn ich nich weiterkomm meld ich mich wieder

Gnafoo
2004-06-11, 10:40:54
Und hat es jetzt eigentlich funktioniert ? :)

Vedek Bareil
2004-06-12, 00:04:22
@Der Tod: wenn ich das richtig sehe, sind die Vektoren, von denen du sprichst, Vektoren auf der 2D-Bildschirmfläche, nicht im virtuellen 3D-Raum.
Jetzt sind mir aber noch drei Dinge unklar:

1) wie bestimmt man die Bildschirmkoordinaten des Mauszeigers? Gibt's vermutlich ne Funktion in der Win32 API für, GetMousePosition oder so, die ich nur grad nicht weiß ;)

2) wie bestimmt man die Bildschirmkoordinaten des Ursprungs des Feldes? Man gibt dessen Koordinaten ja erstmal nur im 3D-Raum an, die Umrechnung in 2D-Bildschirmkoordinaten macht OpenGL intern (über die T&L-Einheit bzw. den Vertex Shader).

3) warum um alles in der Welt verwendest du für das Produkt zweier Skalare das Zeichen "*", für das Skalarprodukt zweier Vektoren dagegen *.*? Üblicherweise verwendet man für beiden Arten der Multiplikation das gleiche Rechenzeichen, um ihre enge Verwandtschaft zu symbolisieren ;)

Gnafoo
2004-06-12, 00:40:55
Bist du eigentlich der Gast ? :)

Original geschrieben von Vedek Bareil
@Der Tod: wenn ich das richtig sehe, sind die Vektoren, von denen du sprichst, Vektoren auf der 2D-Bildschirmfläche, nicht im virtuellen 3D-Raum.

Jup. Ich glaube das müsste funktionieren :D

Original geschrieben von Vedek Bareil
1) wie bestimmt man die Bildschirmkoordinaten des Mauszeigers? Gibt's vermutlich ne Funktion in der Win32 API für, GetMousePosition oder so, die ich nur grad nicht weiß ;)

Hm naja da kann ich dir leider auch nicht genau weiterhelfen, da ich primär unter Linux mit SDL programmiere. Kannst du nicht einfach die entsprechende WindowMessage abfangen und die Koordinaten aus wParam und lParam auslesen? (naja das ist schon etwas her bei mir :D)
Edit: vielleicht hilft dir das hier (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/resources/cursors/cursorreference/cursorfunctions/getcursorpos.asp)

Original geschrieben von Vedek Bareil
2) wie bestimmt man die Bildschirmkoordinaten des Ursprungs des Feldes? Man gibt dessen Koordinaten ja erstmal nur im 3D-Raum an, die Umrechnung in 2D-Bildschirmkoordinaten macht OpenGL intern (über die T&L-Einheit bzw. den Vertex Shader).

Ich wusste nicht, dass das ganze OpenGL ist. Mit der Funktion gluProject kann man 3D-Koordinaten in 2D umrechnen. Allerdings geht die ganze Geschichte wahrscheinlich auch einfacher, wenn das ganze OpenGL ist. :D

Original geschrieben von Vedek Bareil
3) warum um alles in der Welt verwendest du für das Produkt zweier Skalare das Zeichen "*", für das Skalarprodukt zweier Vektoren dagegen *.*? Üblicherweise verwendet man für beiden Arten der Multiplikation das gleiche Rechenzeichen, um ihre enge Verwandtschaft zu symbolisieren ;)
Wie gesagt :) ich hab das ganze Zeug nur aus Tutorials gelernt und nie in der Schule / Studium / was-weiß-ich (Mathematik Klasse 12 halt :D) .. Aber danke für den Hinweis.

Vedek Bareil
2004-06-12, 01:48:29
Neee, bin nicht der Gast. Aber ich hatte mal ein ähnliches Problem, hab dann aber keine Lösung dafür gefunden und es dann nicht weiterverfolgt, weil's mir nicht so wichtig erschien. Daher mein neuerliches Interesse ;)