Autor |
Beitrag |
M. Raab
      
Beiträge: 334
Erhaltene Danke: 1
WIN 7
Delphi XE
|
Verfasst: Sa 14.12.02 14:06
Hallo NG,
folgendes Problem mit OPenGL.
Ich zeichne mit OpenGl ein 3D-Objekt und möchte es mit der Mausdrehen. Die Rotat Funktion geht nun davon aus, dass man eine Achse definiert, also x,y oder z oder eine Kombination dieser Achsen. Wenn ich die Maus nun horizontal nach rechts oder links drehe, kann ich ganz einfach um die y-Ache drehen, wenn ich die Maus nach oben oder unten bewege, drehe ich um die x-Achse. Das alle funktioniert eigentlich so lange gut, bis ich das Objekt so weit gedreht habe, dass die x bzw. y - Ache des Objektes nicht mehr der horizontalen bzw. vertikalen Blickrichtung des Benutzers entsprechen. Also sozusagen die x-Achse "in den Bildschirm" zeigt. Ab dann entspricht die Bewegung der Maus nicht mehr der Drehung um die x-Achse, weil das Objekt ja bereits um 180° gedreht wurde. Jetzt wäre es einfach zu sagen, mn macht eine Fallunterscheidung >180 bzw.<180°. Geht aber nicht, da das Objekt auch in der anderen Richtung gedreht sein kann: es steht also auf dem Kopf und man befindet sich "hinter" dem Objekt. Jetzt sind die Mausbewegungen nicht mehr logisch mit der Drehung verknüpft.
Ich hoffe, ich habe mich verständlich ausgedrückt - zur Verdeutlichung, der entsprechende Programmcode:
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: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65:
| //******************************************************************* procedure T3D.MausMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if ssleft in shift then begin if x<mausx then // Bewegung nach rechts begin wglMakeCurrent(dc,HRC); glrotate(-2,0,1,0); drawscene; wglMakeCurrent(0,0); mausx:=x; end; if x>mausx then // Bewegung nach links begin wglMakeCurrent(dc,HRC); glrotate(2,0,1,0); drawscene; wglMakeCurrent(0,0); mausx:=x; end; if y>mausy then // Bewegung nach unten begin wglMakeCurrent(dc,HRC); glrotate(2,1,0,0); drawscene; wglMakeCurrent(0,0); mausy:=y; end; if y<mausy then // Bewegung nach oben begin wglMakeCurrent(dc,HRC); glrotate(-2,1,0,0); drawscene; wglMakeCurrent(0,0); mausy:=y; end; end;
end; //*******************************************************************
//******************************************************************* procedure T3D.D3AUS(Sender:TObject); begin if D3Form<>nil then begin wglDeleteContext(DC); D3Form:=nil; end; end; //*******************************************************************
//******************************************************************* procedure T3D.MausDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin
mausx:=x; mausy:=y;
end; //******************************************************************* |
Git es keine Lösung, bei der das Objekt der Mausbewegung einfach folgt und zwar unabhängig von der Lage des Benutzers ? Mir schwebt vor, dass zwischen dem Ursprung der Grafik (0,0,0) und der Position der Maus eine hypothetische Achse gebildet wird und die Grafik dieser Achse folgt.
Ums noch deutlicher auszudrücken: nehmt mal an, an der Maus wäre eine Kamera und ich bewege mich nun so durch den Raum. Als Benutzer sehe ich nun das Bild der Kamera und steuere mich mit der Kamera so durch den Raum.
Vielleicht kann jemand helfen.
Gruß
Markus
(15.12. 12:11 Tino) Code-Tags hinzugefügt.
|
|
Jack Falworth
      
Beiträge: 222
Win XP Pro, Slackware 10.0
D5 Enterprise, C++, ABAP
|
Verfasst: Sa 14.12.02 14:54
ich würd das so machen:
wenn die Maus bewegt wird (über MausDown), wird die aktuelle Mausposition mit der neuen Mausposition verglichen. Die Änderungen (Differenz) setzt du in die glRotate procedure (auch unter Mausdown) ein.
Achja: ist es gewollt, dass das Objekt immer um den Winkel -2 rotiert?
Anmerkung: Wenn der Winkel größer 360 ist muss er wieder auf 0 gesetzt werden!
MfG
Jack Falworth
|
|
M. Raab 
      
Beiträge: 334
Erhaltene Danke: 1
WIN 7
Delphi XE
|
Verfasst: Sa 14.12.02 16:11
Hallo Jack,
das mit dem festen Winkel von 2° habe ich absichtlich so gemacht, da sich dadurch eine kontinuierliche Bewegung im Einklang mit der Mausbewegung ergibt - sieht einfach toller aus, wenn sich das Objekt einigermaßen synchron zur Mausbewgung bewegt.
Aber: wie meinst Du das mit dem Einsetzen in Rotate ?
Ich denke, das Problem ist ein Problem mit den Achsen und der Tatsache, dass der Bildschirm nur 2 Dimensionen hat, das Objekt aber 3. Meinst DU, man sollte die Änderung der Mausposition als Winkel eintragen ? Aber: um welche Achse dann ?
Glrotate ((mausxneu-mausxalt)+(mausyneu-mausyalt),?,?,?)
Mit mausxneu sind die alten bzw. neuen Koordinaten der Maus gemeint. Meinst Du das so ?
Gruß
Markus
|
|
Jack Falworth
      
Beiträge: 222
Win XP Pro, Slackware 10.0
D5 Enterprise, C++, ABAP
|
Verfasst: Sa 14.12.02 17:57
hmm achja das hatte ich irgendwie missverstanden
wie gesagt mach das mit dem ändern in x und y Richtung so wie oben gesagt. und das mit der z Achse könntest du z.B. mit dem Mausrad realisieren. Mausrad nach vorne bewegen = Änderung in positiver Z-Achse, nach hinten = Änderung in negativer Z-Achse.
Da, wie du schon gesagt hast Bildschirm: 2D, Objekt: 3D, muss man auf sowas ausweichen oder das andere sehr komplex gestalten.
Mit dem anderen Problem (180°):
Nehmen wir an du hast ne Kugel gezeichnet. Dann kannst du wenn das x veränderst dich einmal komplett um die Kugel drehen. Du musst dann nur wenn du dich einmal um sie rum gedreht hast den winkel wieder auf 0 stellen.
MfG
Jack Falworth
|
|
M. Raab 
      
Beiträge: 334
Erhaltene Danke: 1
WIN 7
Delphi XE
|
Verfasst: So 15.12.02 11:00
Hallo Jack,
ist vielleicht auch eine Lösung. Ich habe in dem Forum schon mal was von einem Kameraeffekt gehört. Kennst Du sowas ?
Noch ein Problem dabei: was mach ich bei LAPTOPS ? So viel ich weiß, haben die nur die beiden Mausfunktionen auf dem Pad. Dann könnte ich noch die Tastatr benutzen: Cursor und Bildtasten....
Ist aber alles unelegant.
Gäbe es noch eine Alternative ?
Gruß
Markus 
|
|
Jack Falworth
      
Beiträge: 222
Win XP Pro, Slackware 10.0
D5 Enterprise, C++, ABAP
|
Verfasst: So 15.12.02 16:01
M. Raab hat folgendes geschrieben: | Hallo Jack,
ist vielleicht auch eine Lösung. Ich habe in dem Forum schon mal was von einem Kameraeffekt gehört. Kennst Du sowas ?
|
Mir bekannt ist der Befehl gluperspective. damit kannst du den Sichtwinkel (FOV= Field of view) und anderes einstellen.
oder ich glaube das trifft eher
gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz);
Beschreibung:
Die ersten drei Parameter bestimmen die Position des Betrachters im Raum, die nächsten drei den Vektor, welcher die Blickrichtung des Betrachters festlegt. Die letzten drei Parameter sind nicht immer sinnvoll, sie legen eine Achse fest, welche senkrecht zur Blickrichtung stehen soll (meist 0,1,0= y- Achse). Später kann, durch Drehung dieses Punktes, die Blickrichtung einfach verändert werden. Aber wie gesagt, meist verändert man diese Parameter nicht.
M. Raab hat folgendes geschrieben: |
Noch ein Problem dabei: was mach ich bei LAPTOPS ? So viel ich weiß, haben die nur die beiden Mausfunktionen auf dem Pad. Dann könnte ich noch die Tastatr benutzen: Cursor und Bildtasten....
Ist aber alles unelegant.
Gäbe es noch eine Alternative ?
Gruß
Markus  |
Eine Möglichkeit ("unelegant") ohne Mausrad:
für das änderen in z-Richtung: linke Maustaste muss gedrückt werden, dann verschieben der Maus in y-Richtung
Zweite Möglichkeit ("eleganter"), aber sinnvoll?:
Du müsstest nen algorithmus schreiben der, wenn du die maus gleichermaßen (mit etwas Toleranz) in x- und y- Richtung bewegst, ein Veränderung in z-Richtung errechnet.
Aber ob das jetzt sinnvoll ist oder nicht sei dahingestellt.
Ich würde trotz unelegant (warum eigentlich?) die erste Möglichkeit vorziehen. Die zweite Möglichkeit ist viel Schreibarbeit und auch ziemlich umständlich.
MfG
Jack Falworth
|
|
Aya
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: So 15.12.02 20:20
Hi,
*grübel* Ich weiß nich so genau ob ich dein Problem richtig verstanen habe... aber, versuch es mal so:
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:
| var RotateX, RotateY: Single; MX, MY: Integer;
procedure DrawScene; begin glRotate(RotateX,1,0,0); glRotate(RotateY,0,1,0); //Kugel Zeichnen! end;
procedure OnMouseMove(...); begin if MX>X then RotateX:=RotateX+3; if MX<X then RotateX:=RotateX-3; if MY>Y then RotateY:=RotateY+3; if MY<Y then RotateY:=RotateY-3; MX:=Y; MY:=Y; end; |
Ist ungetestet, aber so mach ich es immer..
Au'revoir,
Aya~
PS: Rotieren auf der Z-Achse ist relativ unwichtig... X und Y reicht aus.. damit sieht man das objekt von jeder seite
Selbst die großen 3D Programme lassen nur eine rotation auf der X und Y achse zu.
|
|
M. Raab 
      
Beiträge: 334
Erhaltene Danke: 1
WIN 7
Delphi XE
|
Verfasst: Mo 16.12.02 15:20
Hallo Aya, Hallo Jack,
folgender Code - Lösung AYA
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| if MausX>X then RotateX:=RotateX+0.03; if MausX<X then RotateX:=RotateX-0.03; if MausY>Y then RotateY:=RotateY+0.03; if MausY<Y then RotateY:=RotateY-0.03;
wglMakeCurrent(dc,HRC); glrotate(rotatex,1,0,0); glrotate(rotatey,0,1,0); drawscene; wglMakeCurrent(0,0);
MausX:=Y; MausY:=Y; |
Code - Lösung Jack:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| if MausX>X then RotateX:=RotateX+0.03; if MausX<X then RotateX:=RotateX-0.03; if MausY>Y then RotateY:=RotateY+0.03; if MausY<Y then RotateY:=RotateY-0.03;
wglMakeCurrent(dc,HRC); glulookat(rotatex,rotatey,0,0,0,0,0,1,0); drawscene; wglMakeCurrent(0,0); |
Ich denke, ich habe Aya so richtig verstanden. Mit GLULOOKAT hat zwar funktioniert, aber das Bild verschwindet sofort aus der Ebene. Irgendwie stimmt das mit dem Anpassen an die Mausposition nicht. Ich kann also nicht sagen, ob es das Richtige ist. Ich denk aber, die Lösung von AYA scheint mir logischer zu sein. Funktioniert aber irgenwie auch noch nicht. Ich habe deshalb den Code mal geposte - vielleicht mach ich ja was grundlegendes falsch.
Gruß
Markus 
|
|
Aya
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: Mo 16.12.02 15:40
Hi,
so nur kurz auf den ersten blick seh ich nur einen fehler... und zwar in der letzen zeile von meinem Code
Da steht bei dir
MausX:=Y;
Das muß aber:
MausX:=X;
heißen
Ansonsten schau ich morgen mal genauer nach, hab nämlich heute Geburtstag = keine zeit mehr *G*
*winkt*
Aya~
|
|
M. Raab 
      
Beiträge: 334
Erhaltene Danke: 1
WIN 7
Delphi XE
|
Verfasst: Mo 16.12.02 16:21
Hallo Aya,
alles Gute !!!!!!!!!
Ich habe die Fehler behoben: aber: es scheint jetzt so eine Art Aufddiereffekt zu geben. Bewege ich die Maus lange nach links oder rechts, dreht sich das ganze weiter, bleibt stehen und dreht sich dann in die andere Richtung.
Nun ja: feier mal schön weiter !!!!
Gruß
Markus
|
|
Aya
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: Di 17.12.02 03:53
huhu,
Dankee~~~~
also.. bin totmüde.. *g* aber einfach mal so reingerufen würd ich sagen, mach mal:
Quelltext 1: 2: 3: 4:
| if RotateX>360 then RotateX:=RotateX-360; if RotateY>360 then RotateY:=RotateY-360; |
Weiß nich ob's daran lag, aber aufjedenfall ist es schonmal besser wenn der Winkel nich in's unendliche geht *g*
Au'revoir,
Aya~
|
|
Aya
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: Di 17.12.02 04:03
meep meep *g*
Nochmal da
Mal nen beispiel aus einem Programm das ich mal gebastelt hab, das war nen PanoramaAnguck-Programm... also so nen 360° rundumblick ding
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:
| const CPX = 100; CPY = 100;
var RH, RV: Single;
procedure TForm1.OnCreate... begin [...] ShowCursor(False); [...] end;
procedure DrawScene; begin [...] glRotate(RV,1,0,0); glRotate(RH,0,1,0); //ObjektZeichnen [...] end;
procedure OnMouseMove... begin if X>CPX then RH:=RH+Round((X-CPX)/10); if Y<CPY then RV:=RV-Round((CPY-Y)/10); SetCursorPos(CPX,CPY); end; |
Erklärung:
Die Variablen RH und RV sind die Rotation Vertikal und Horizontal..
CPX und CPY ist die CursorPosX/Y.. da würd ich die mitte deines Forms nehmen, 100,100 is nur nen beispiel
Dann in der OnMouseMove Procedure, steht zwei mal /10 da, wenn du den wert veränderst, änderst du die geschwindigkeit mit der sich das Objekt dreht, bzw die MausSensitivität *g*
Der vorteil von deme ganzen ist, du kannst das ding auch weiterdrehen, wenn du mit der Maus schon ganz amRand bist, brauchst nich extra zurück UND... bewegst du die maus schnell, dreht es sich schnell... bewegst du sie langsam, bewegt es sich langsam
Au'revoir,
Aya~
|
|
M. Raab 
      
Beiträge: 334
Erhaltene Danke: 1
WIN 7
Delphi XE
|
Verfasst: Mi 18.12.02 16:46
Hallo Aya,
na, wie war die Nacht ????  oder  oder
Nun ja, ich habe Deinen Vorschlag ausprobiert .. funktioniert, aber noch ist das gleiche Problem, dass nämlich die Drehachse (=x-Achse) mal -wie soll ich mich ausdrücken- in den Bilrdschirm stehen kann ?????!!!
Also, die x-Achse verläuft nicht mehr von links nach rechts am Bildschirm, sondern von vorne in die Tiefe des Bildschirms. Dies ergibt sich einfach aus der Drehung. Dein Vorschlag löst das Problem wenigstens zum Teil --- VIELEN DANK
Vielleicht kannst Du mir noch bei einem weiteren Problem helfen ? Mathematische Art ???? Das ist aber vielleicht nichts fürs Forum !! Eine Punktbestimmung im R3 ?
Gruß
Markus
|
|
Aya
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: Mi 18.12.02 18:14
Hi,
also so ganz verstehen tu ich dein Proglem grad nich, schick mir doch einfach mal dein Programm, vieleicht seh ich's dann
-> Aya@Koshigaya.de
Au'revoir,
Aya~
PS: Punktbestimmung im 3D Raum?? Sag mal genauer was du brauchst 
|
|
|