OpenGL Mauskamerasteuerung

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...

OpenGL Mauskamerasteuerung

Beitragvon Hartkern » 16. Jun 2016, 11:31 OpenGL Mauskamerasteuerung

Hallo,

ich hänge fest an meiner "Kamera" Steuerung. Ich versuche diese mit der Maus aus einer Ich Perspektive zu steuern. Jedoch scheitere ich an setzen der Mauscursorpositionen, irgendwann ist die Maus aus dem fenster und nix klappt mehr.
Die Tastenvariante funktioniert dagegen :evil: :cry:

Code: Alles auswählen
procedure tOpenGlKamera.MouseMove(x, y: integer);
var NewCursorPos: TSmallPoint;
begin
 NewCursorPos.x:=x;
 NewCursorPos.y:=y;
 
  if CursorPos.y-NewCursorPos.y>0  then  //hochschauen
     begin
         RotY:=RotY+fRot_speed;
         If RotY>45 then RotY:=45; //Kopf-Nick-Begrenzung
     end;
 
  if  CursorPos.y-NewCursorPos.y<0 then   //Runterschauen
      begin
          RotY:=RotY-fRot_speed;
          If RotY<-45 then RotY:=-45; //Kopf-Nick-Begrenzung
       end;
 
  if  CursorPos.x-NewCursorPos.x>0 then //Rechtsschauen
     begin
          RotZ:=RotZ+fRot_speed;
          If RotZ>360 then RotZ:=360;
     end;
 
  if CursorPos.x-NewCursorPos.x<0 then //Linkschauen
     begin
          RotZ:=RotZ-fRot_speed;
          If RotZ>-360 then RotZ:=-360;
     end;
 
  SetCursorPos(fOpenGLControl.Width div 2,fOpenGLControl.Height div 2); //hier ist die unknackbare Nuss
  CursorPos.X:=fOpenGLControl.Width div 2; //oder hier ist die unknackbare Nuss
  CursorPos.Y:=fOpenGLControl.Height div 2;//könnte auch hier sein
end;   


bei Bedarf zur Verbesserung kann ich meine gesamte Klasse TOpenGlKamera nachreichen.
Hartkern
 
Beiträge: 68
Registriert: 5. Dez 2015, 20:03
Wohnort: Leipzig
OS, Lazarus, FPC: Win10 IDE 1.6 | 
CPU-Target: 64Bit
Nach oben

Beitragvon Mathias » 16. Jun 2016, 19:20 Re: OpenGL Mauskamerasteuerung

Auf deinem Code sieht man zu wenig, aber ich habe da eine fertige Lösung, welche du angucken kannst.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3993
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon wp_xyz » 16. Jun 2016, 19:43 Re: OpenGL Mauskamerasteuerung

Leider hat diese Lösung wie viele andere in dieser Richtung das Problem, dass die Bedienung bzgl. Drehung irgendwann nicht mehr intuitiv ist. Unter "intuitiv" meine ich: Wenn ich die Maus nach rechts ziehe, dreht sich das Modell um die y-Achse nach rechts. So ist es zu Beginn des Programm, ok. Aber nun starte ich neu und ziehe als erstes die Maus vertikal so lange, bis die grüne Rückseite des Würfels durch Drehung um die x-Achse vorne ist. Ziehe ich jetzt die Maus horizontal, dreht sich der Würfel um die y-Achse (ok), aber entgegengesetzt zur Maus! Noch verrückter ist es, wenn ich nach dem Programmstart den Würfel nur um 90° um die x-Achse drehst (also pink- oder cyan-Fläche vorne). Dann bewirkt eine anschließende horizontale Bewegung der Maus nicht mehr eine Drehung um die y-Achse, sondern um die in den Bildschirm reichende z-Achse. Dieses Verhalten finde ich bei vielen einfachen 3D-Programmen extrem frustrierend.
wp_xyz
 
Beiträge: 2533
Registriert: 8. Apr 2011, 08:01

Beitragvon Mathias » 16. Jun 2016, 22:08 Re: OpenGL Mauskamerasteuerung

Meinst du so sei es besser ?
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3993
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon wp_xyz » 16. Jun 2016, 23:11 Re: OpenGL Mauskamerasteuerung

Hey, sehr gut! Dann kriegst du die nächste Stufe auch noch hin, die Drehung um die z-Achse, bei dir mit der mittleren Maustaste realisiert. Momentan bewirkt ein Ziehen der Maus nach rechts eine Drehung im, nach links entgegen dem Uhrzeigersinn. Ich habe aber die Vorstellung, ich würde mit der Maus einen Teil des Modells anfassen und herumdrehen. Das heißt, das Modell sollte der Bewegung der Maus folgen. Im Modell des Würfels: Fasse ich ihn an der oberen rechten Ecke an und bewege die Maus nach rechts, dreht er sich im Uhrzeigersinn - ok. Jetzt fasse ich die Maus an der unteren linken Ecke an und bewege die Maus nach rechts. Weil Rechtsziehen eine Drehung im Uhrzeigersinn bewirkt, dreht sich der Würfel anders herum als ich mir vorstelle. Das zweite Problem ist die Drehung bei vertikalem Ziehen, das passiert, je nachdem, wie "senkrecht" die Bewegung erfolgt, mehr oder weniger gar nichts. Im Idealfall sollte die Drehung durch den Vektor der Mausbewegung, nicht nur durch die horizontale Distanz bestimmt werden.
wp_xyz
 
Beiträge: 2533
Registriert: 8. Apr 2011, 08:01

Beitragvon wp_xyz » 17. Jun 2016, 12:57 Re: OpenGL Mauskamerasteuerung

Ich antworte mal selber: mit diesem Code wird der Drehwinkel berechnet und in deiner Drehroutine eingesetzt:

Code: Alles auswählen
procedure TForm1.OpenGLControl1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: integer);
const
  MoveStep = 1.0 / 100;
  RotStep = 100;
var
  phi1, phi2, dphi: Double;
  ctr: TPoint;
begin
  if Shift = [ssLeft] then begin
    Translate(MyMatrix, (X - MousePos.x) * MoveStep, -(Y - MousePos.y) * MoveStep, 0.0);
  end;
  if Shift = [ssRight] then begin
    RotateB(MyMatrix, -(X - MousePos.x) / RotStep);
    RotateA(MyMatrix, (Y - MousePos.y) / RotStep);
  end;
  if Shift = [ssMiddle] then begin
    ctr := Point(Width div 2, Height div 2);
    phi1 := arctan2(MousePos.Y - ctr.Y, MousePos.X - ctr.X);
    phi2 := arctan2(Y - ctr.Y, X - ctr.X);
    dphi := phi2 - phi1;
    if (phi2 > pi/2) and (phi1 < -pi/2) then
      dphi := 2*pi - dphi
    else
    if (phi1 > pi/2) and (phi2 < -pi/2) then
      dphi := 2*pi + dphi;
    RotateC(MyMatrix, -RadToDeg(dphi) / RotStep);
  end;
 
  MousePos.x := X;
  MousePos.y := Y;
end;
 
wp_xyz
 
Beiträge: 2533
Registriert: 8. Apr 2011, 08:01

Beitragvon Mathias » 17. Jun 2016, 17:59 Re: OpenGL Mauskamerasteuerung

Hey, sehr gut! Dann kriegst du die nächste Stufe auch noch hin, die Drehung um die z-Achse, bei dir mit der mittleren Maustaste realisiert.

Ich weiss optimal ist diese nicht.

Aber das du schon eine Lösung hast, werde ich diese bei mir einbauen, danke.
Vielleicht sollte noch erwähnt werden, das die Unit Math eingebunden werden muss.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3993
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon corpsman » 17. Jun 2016, 18:37 Re: OpenGL Mauskamerasteuerung

in meinem MAW Sample ist auch ne MAussteuerung drin, wenn dir die Gefällt, dort wird das ganze mittels Matrizen gemacht, eigentlich auch recht intuitiv *g*
--
Just try it
corpsman
 
Beiträge: 1041
Registriert: 28. Feb 2009, 08:54
Wohnort: Stuttgart
OS, Lazarus, FPC: Kubuntu 14.04, Lazarus SVN Trunk, FPC 3.0 | 
CPU-Target: 32Bit
Nach oben

Beitragvon Mathias » 17. Jun 2016, 19:21 Re: OpenGL Mauskamerasteuerung

n meinem MAW Sample

Was meinst du mit MAW ?

dort wird das ganze mittels Matrizen gemacht

Meine Variante geht auch mit Matrixen, oder meinst du was anderes ?
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3993
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon corpsman » 17. Jun 2016, 19:40 Re: OpenGL Mauskamerasteuerung

hättest du auf MAW geklickt, wärst di hier http://corpsman.de/index.php?doc=opengl/maw rausgekommen ;)

Meine Variante nimmt den OpenGL Stack und manipuliert die Matrix damit, somit sind keine trigonometrischen Routinen notwendig *g*
--
Just try it
corpsman
 
Beiträge: 1041
Registriert: 28. Feb 2009, 08:54
Wohnort: Stuttgart
OS, Lazarus, FPC: Kubuntu 14.04, Lazarus SVN Trunk, FPC 3.0 | 
CPU-Target: 32Bit
Nach oben

Beitragvon wp_xyz » 17. Jun 2016, 20:02 Re: OpenGL Mauskamerasteuerung

Corpsman hat geschrieben:hättest du auf MAW geklickt

Diese eingebetteten Links sind zwar chic, aber nur sehr schwer zu erkennen (zumindest mit Firefox unter Win10). Dazu hatte ich vor kurzem im englischen Forum dasselbe Problem

Corpsman hat geschrieben:wärst di hier http://corpsman.de/index.php?doc=opengl/maw rausgekommen

Da erhält man aber nur eine exe mit Steuerdateien, aber keinen Quellcode. Oder bin ich mal wieder völlig blind?
wp_xyz
 
Beiträge: 2533
Registriert: 8. Apr 2011, 08:01

Beitragvon Mathias » 17. Jun 2016, 20:11 Re: OpenGL Mauskamerasteuerung

Diese eingebetteten Links sind zwar chic, aber nur sehr schwer zu erkennen

Genau dies habe ich auch gemerkt, wen ich jetzt genau gucke sehe ich ihn.

Meine Variante nimmt den OpenGL Stack und manipuliert die Matrix damit, somit sind keine trigonometrischen Routinen notwendig *g*

Ich werde mir dies mal angucken. Da ich letzte Zeit mit OpenGL 3.3 arbeitete, musste ich die Matrixen sowieso selbst berechnen.
Wen man mit dem alten OpenGL arbeitet, ist das mit dem Stack sicher sinnvoll.
Ich wollte es erst auch damit versuchen, aber es funktionierte nicht. :wink:

PS: Bei dem MAV Link hat es nur eine EXE, Code sieht man keinen.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3993
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon corpsman » 17. Jun 2016, 20:43 Re: OpenGL Mauskamerasteuerung

*g*

dann hier mal ein Code snippet :

Code: Alles auswählen
Procedure TMarionette.Rotate(ID: Glint; dx, dy, dz: GLfloat);
Begin
  glPushMatrix();
  glLoadIdentity();
  Case ID Of
    1: Begin // Drehung der Gesamtfigur , am Bauch
        glTranslatef(Bauch.rotateMatrix[3, 0], Bauch.rotateMatrix[3, 1], Bauch.rotateMatrix[3, 2]);
        glRotatef(dx, 1.0, 0.0, 0.0);
        glRotatef(dy, 0.0, 1.0, 0.0);
        glRotatef(dz, 0.0, 0.0, 1.0);
        glTranslatef(-Bauch.rotateMatrix[3, 0], -Bauch.rotateMatrix[3, 1], -Bauch.rotateMatrix[3, 2]);
        glMultMatrixf(@Bauch.rotateMatrix[0, 0]);
        glGetFloatv(GL_MODELVIEW_MATRIX, @Bauch.rotateMatrix[0, 0]);
      End;
..
 


Ich hoffe das hilft weiter ;)
--
Just try it
corpsman
 
Beiträge: 1041
Registriert: 28. Feb 2009, 08:54
Wohnort: Stuttgart
OS, Lazarus, FPC: Kubuntu 14.04, Lazarus SVN Trunk, FPC 3.0 | 
CPU-Target: 32Bit
Nach oben

Beitragvon wp_xyz » 18. Jun 2016, 10:18 Re: OpenGL Mauskamerasteuerung

Ich hab die MAW-exe gerade gestartet, aber ich muss sagen: das ist genau die Sorte von 3D-Programm, die ich oben erwähnt habe: Man bewegt die Maus nach links, und die Figur bewegt sich nach rechts.
wp_xyz
 
Beiträge: 2533
Registriert: 8. Apr 2011, 08:01

Beitragvon Hartkern » 18. Jun 2016, 10:36 Re: OpenGL Mauskamerasteuerung

Entschuldigung für meine späte Antwort...ich war die letzten Tage damit beschäftigz OpenGl 3.3 zum laufen zu bringen!!! Mein erstes Dreieck..

so.. hier mal meine komplette Kameraklasse...

Code: Alles auswählen
unit uOpemGLKamera;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  ExtCtrls,OpenGLContext, dglOpenGL, math, Windows,video,keyboard;
 
  type
 
    { tKamera }
 
    { tOpenGlKamera }
 
    tOpenGlKamera = class
      private
       fOpenGLControl : TOpenGLControl;
       Matrix : Array[0..15] of glFloat;
       fKey_vor : char;
       fKey_zurueck : char;
       fKey_strafe_links : char;
       fKey_strafe_rechts : char;
       fKey_hoch : char;
       fKey_runter : char;
       fKey_drehen_links : char;
       fKey_drehen_rechts : char;
       fKey_drehen_hoch : char;
       fKey_drehen_runter : char;
       fmovespeed : glFloat;
       fRot_Speed : glFloat;
       pi         : glFloat;
       PosX_Aktuell : glFloat;
       PosY_Aktuell : glFloat;
       PosZ_Aktuell : glFloat;
       RotY, RotZ   : glFloat;
       CursorPos : TSmallPoint;
      public
        constructor create(OGL: TOpenGLControl);
        destructor free;
        procedure Update;       // kommt dorthin wo gerendert wird
        procedure KeyPress(Key : char); // kommt ins OnKeyPress Event des Forms, oder OpenglContext ?
        procedure MouseMove(x,y : integer); //kommt ins On MouseMove Event von OpenGLContext
        procedure SetKey_Bewegung(vor,zurueck,strafe_rechts,strafe_links,hoch,runter : char);   //Wird im Create vorbelegt
        procedure SetKey_Drehung(links, rechts, oben, unten : char); //Wird im Create vorbelegt
        procedure SetMoveSpeed(value : glFloat);   //Wird im Create vorbelegt
        procedure SetRotSpeed(value : glFloat)//Wird im Create vorbelegt
        procedure SetKameraPos(PosX, PosY, PosZ : GLFloat)//Wird im Create vorbelegt
    end;
 
implementation
 
{ tOpenGlKamera }
 
constructor tOpenGlKamera.create(OGL: TOpenGLControl);
begin
       fOpenGLControl:=OGL;
       fKey_vor :='w';
       fKey_zurueck :='s';
       fKey_strafe_links :='a';
       fKey_strafe_rechts :='d';
       fKey_hoch :='q';
       fKey_runter :='e';
       fKey_drehen_links :='f';
       fKey_drehen_rechts :='h';
       fKey_drehen_hoch :='t';
       fKey_drehen_runter :='g';
       fmovespeed:=0.1;
       fRot_Speed :=1.0;
       PosX_Aktuell :=0;
       PosY_Aktuell :=0;
       PosZ_Aktuell :=-15;
       pi := arccos(-1);
       CursorPos.X:=fOpenGLControl.Width;
       CursorPos.Y:=fOpenGLControl.Height;
end;
 
destructor tOpenGlKamera.free;
begin
 
end;
 
procedure tOpenGlKamera.SetKameraPos(PosX, PosY, PosZ : GLFloat);
begin
  PosX_Aktuell :=PosX;
  PosY_Aktuell :=PosY;
  PosZ_Aktuell :=PosZ;
 
end;
 
procedure tOpenGlKamera.Update;
begin
    matrix[0]:=cos(RotZ*pi/180);
    matrix[1]:=sin(RotY*PI/180)*-sin(RotZ*PI/180);
    matrix[2]:=cos(RotY*PI/180)*-sin(RotZ*PI/180);
    matrix[3]:=0;
    matrix[4]:=0;
    matrix[5]:=cos(RotY*PI/180);
    matrix[6]:=-sin(RotY*PI/180);
    matrix[7]:=0;
    matrix[8]:=sin(RotZ*PI/180);
    matrix[9]:=sin(RotY*PI/180)*cos(RotZ*PI/180);
    matrix[10]:=cos(RotY*PI/180)*cos(RotZ*PI/180);
    matrix[11]:=0;
    matrix[12]:=PosX_Aktuell*cos(RotZ*PI/180)+PosZ_Aktuell*sin(RotZ*PI/180);
    matrix[13]:=-PosX_Aktuell*sin(RotY*PI/180)*sin(RotZ*PI/180)+PosZ_Aktuell*sin(RotY*PI/180)*cos(RotZ*PI/180)+PosY_Aktuell*cos(RotY*PI/180);
    matrix[14]:=-PosX_Aktuell*cos(RotY*PI/180)*sin(RotZ*PI/180)+PosZ_Aktuell*cos(RotY*PI/180)*cos(RotZ*PI/180)-PosY_Aktuell*sin(RotY*PI/180);
    matrix[15]:=1;
glLoadMatrixf(matrix);
end;
 
procedure tOpenGlKamera.KeyPress(Key: char);
begin
 
  if Key = fKey_vor then   //Vorwärtsbewegung
  begin
    PosX_Aktuell+=fmovespeed*sin(-RotZ*PI/180);
    PosZ_Aktuell+=fmovespeed*cos(-RotZ*PI/180);
  end;
 
  if Key = fKey_zurueck then //Rückwärtsbewegung
  begin
    PosX_Aktuell-=fmovespeed*sin(-RotZ*PI/180);
    PosZ_Aktuell-=fmovespeed*cos(-RotZ*PI/180);
  end;
 
  if Key = fKey_strafe_links  then //Strafe Links
  begin
     PosX_Aktuell+=fmovespeed*sin((-RotZ+90)*PI/180);
     PosZ_Aktuell+=fmovespeed*cos((-RotZ+90)*PI/180);
  end;
 
  if Key = fKey_strafe_rechts then //Strafe Rechts
  begin
     PosX_Aktuell-=fmovespeed*sin((-RotZ+90)*PI/180);
     PosZ_Aktuell-=fmovespeed*cos((-RotZ+90)*PI/180);
  end;
 
  if Key = fKey_hoch then //Hochschweben
  begin
    PosY_Aktuell-=fmovespeed;
  end;
 
  if Key = fKey_runter then //Runterschweben
  begin
    PosY_Aktuell+=fmovespeed;
  end;
 
  if Key = fKey_drehen_hoch then //Hochschauen
  begin
    RotY:=RotY+fRot_speed;
    If RotY>45 then RotY:=45;
  end;
 
   if Key = fKey_drehen_runter then //Runterschauen
  begin
    RotY:=RotY-fRot_speed;
    If RotY<-45 then RotY:=-45;
  end;
 
   if Key = fKey_drehen_links then //Linkschauen
  begin
    RotZ:=RotZ-fRot_speed;
    If RotZ<-360 then RotZ:=-360;
  end;
 
  if Key = fKey_drehen_rechts then //Rechtsschauen
  begin
    RotZ:=RotZ+fRot_speed;
    If RotZ>360 then RotZ:=360;
  end;
 
end;
 
 
procedure tOpenGlKamera.MouseMove(x, y: integer);
var NewCursorPos: TSmallPoint;
begin
 NewCursorPos.x:=x;
 NewCursorPos.y:=y;
 
  if CursorPos.y-NewCursorPos.y>0  then  //hochschauen
     begin
         RotY:=RotY+fRot_speed;
         If RotY>45 then RotY:=45; //Kopf-Nick-Begrenzung
     end;
 
  if  CursorPos.y-NewCursorPos.y<0 then   //Runterschauen
      begin
          RotY:=RotY-fRot_speed;
          If RotY<-45 then RotY:=-45; //Kopf-Nick-Begrenzung
       end;
 
  if  CursorPos.x-NewCursorPos.x>0 then //Rechtsschauen
     begin
          RotZ:=RotZ+fRot_speed;
          If RotZ>360 then RotZ:=360;
     end;
 
  if CursorPos.x-NewCursorPos.x<0 then //Linkschauen
     begin
          RotZ:=RotZ-fRot_speed;
          If RotZ<-360 then RotZ:=-360;
     end;
 
  SetCursorPos(fOpenGLControl.Width div 2,fOpenGLControl.Height div 2);
  CursorPos.X:=fOpenGLControl.Width div 2;
  CursorPos.Y:=fOpenGLControl.Height div 2;
end;
 
procedure tOpenGlKamera.SetKey_Bewegung(vor, zurueck, strafe_rechts, strafe_links, hoch,
  runter: char);
begin
   fKey_vor :=vor;
   fKey_zurueck :=zurueck;
   fKey_strafe_links :=strafe_links;
   fKey_strafe_rechts :=strafe_rechts;
   fKey_hoch :=hoch;
   fKey_runter :=runter;
end;
 
procedure tOpenGlKamera.SetKey_Drehung(links, rechts, oben, unten: char);
begin
   fKey_drehen_links :=links;
   fKey_drehen_rechts :=rechts;
   fKey_drehen_hoch :=oben;
   fKey_drehen_runter :=unten;
end;
 
procedure tOpenGlKamera.SetMoveSpeed(value: glFloat);
begin
  fmovespeed:=value;
end;
 
procedure tOpenGlKamera.SetRotSpeed(value: glFloat);
begin
  fRot_Speed:=value;
end;
 
 
 
end
Hartkern
 
Beiträge: 68
Registriert: 5. Dez 2015, 20:03
Wohnort: Leipzig
OS, Lazarus, FPC: Win10 IDE 1.6 | 
CPU-Target: 64Bit
Nach oben

» Weitere Beiträge siehe nächste Seite »
Nächste

Zurück zu Multimedia



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast

porpoises-institution
accuracy-worried