OpenGL und Camera



  • Hallo,

    es gibt sehr viele Beispiele wie man in OpenGL eine Kamerasteuerung
    herstellt. Ich brauche da eigentlich dringend eine Hilfe.

    Scenario:

    Kamera beobachtet eine Platte aus 45% über Ecke, diese ist drehbar
    mit der Tastatur left und reight, sowie beweglich rechts links Key.

    Drehe ich aber meine Platte wirken danach die Tasten rechts und links nur
    noch zu einem kleinen Teil,die meiste Erhöhung von zb. X wandert nun in Y
    und umgekehrt.

    Desswegen wirke ich direkt auf die View und Projektions Matrix ein, indem ich
    die Matrixeinträge so manipuliere das bei einer Multiplikation der
    korrekte XY-Anteil in die Darstellung integriert wird, das sieht so aus:

    **LookAt(3, 90, 45, 100);
    **

    void CGLcamera::LookAt(float yaw, float roll, float pitch, float dir)
    {
        m_rot.z -= (yaw/10.0f);     //Seitenruder m_rot.z
        m_rot.x -= (roll/10.0f);    //Nase = m_rot.x 
                                    //Querruder = m_rot.y  
    
    	register float fc = -CVertex::Cos((m_rot.x + 90.0f) * PI180);
    
        m_cam.x =  CVertex::Cos((m_rot.z + 90.0f) * PI180)*fc;//rotate by X+90 with RightLeft 
        m_cam.y =  CVertex::Sin((m_rot.z + 90.0f) * PI180)*fc;//rotate by Y+90 with RightLeft 
        m_cam.z = -CVertex::Sin((m_rot.x + 90.0f) * PI180);   //rotate by Z+90 with UpDown     
    
        if(pitch > 0)//xchg xy
         dir=1,m_cam = CVertex( m_cam.y, -m_cam.x, m_cam.z);
        else if(pitch < 0)//xchg xy
         dir=1,m_cam = CVertex( -m_cam.y, m_cam.x, m_cam.z);
    
    	m_cam   *= dir; //direction normal +1
    
    	m_pos   +=  m_cam;
    }
    

    Im Anschluß Integriere ich die berechnete rotation m_cam
    in die Matrix:

    pCam->CGLmatrix::RotXYZ(m_cam);

    void CGLmatrix::RotXYZ(CVertex rot)
    {
    	float c,s;
    	float x0,y0,z0;
    	float x1,y1,z1;
    	float x2,y2,z2;
    	register float *mod=&m_m0[0][0];
    
    	//x
    	c=Cos(rot.x*PI180);
    	s=Sin(rot.x*PI180);
    
    	x0 = mod[0];
    	y0 = mod[1];
    	z0 = mod[2];
    	x1 = mod[4]*c+mod[8]*s;
    	y1 = mod[5]*c+mod[9]*s;
    	z1 = mod[6]*c+mod[10]*s;
    	x2 = mod[4]*-s+mod[8]*c;
    	y2 = mod[5]*-s+mod[9]*c;
    	z2 = mod[6]*-s+mod[10]*c;
    
    	mod[0] = x0,
    	mod[1] = y0,
    	mod[2] = z0;
    	mod[4] = x1,
    	mod[5] = y1,
    	mod[6] = z1;
    	mod[8] = x2,
    	mod[9] = y2,
    	mod[10] = z2;
    
    	//y
        c=Cos(rot.y*PI180);
    	s=Sin(rot.y*PI180);
    
    	x0 = mod[0]*c+mod[8]*-s;
    	y0 = mod[1]*c+mod[9]*-s;
    	z0 = mod[2]*c+mod[10]*-s;
    	x1 = mod[4];
    	y1 = mod[5];
    	z1 = mod[6];
    	x2 = mod[0]*s+mod[8]*c;
    	y2 = mod[1]*s+mod[9]*c;
    	z2 = mod[2]*s+mod[10]*c;
    
    	mod[0] = x0,
    	mod[1] = y0,
    	mod[2] = z0;
    	mod[4] = x1,
    	mod[5] = y1,
    	mod[6] = z1;
    	mod[8] = x2,
    	mod[9] = y2,
    	mod[10] = z2;
    
    	//z
    	c=Cos(rot.z*PI180);
    	s=Sin(rot.z*PI180);
    
    	x0 = mod[0]*c+mod[4]*s;
    	y0 = mod[1]*c+mod[5]*s;
    	z0 = mod[2]*c+mod[6]*s;
    	x1 = mod[0]*-s+mod[4]*c;
    	y1 = mod[1]*-s+mod[5]*c;
    	z1 = mod[2]*-s+mod[6]*c;
    	x2 = mod[8];
    	y2 = mod[9];
    	z2 = mod[10];
    
    	mod[0] = x0,
    	mod[1] = y0,
    	mod[2] = z0;
    	mod[4] = x1,
    	mod[5] = y1,
    	mod[6] = z1;
    	mod[8] = x2,
    	mod[9] = y2,
    	mod[10] = z2;
    }
    

    Dann translatiere ich die neue Position der Kamera m_pos separat:

    pCam->CGLmatrix::Translate(m_pos);

    //Move matrix by Vector-direction  multiply a point with a matrix
    void CGLmatrix::Translate(const CVertex pos)
    {
    	register float *mod=&m_m0[0][0];
    	mod[12] = mod[0]*pos.x+mod[4]*pos.y+mod[8]*pos.z+mod[12];
    	mod[13] = mod[1]*pos.x+mod[5]*pos.y+mod[9]*pos.z+mod[13];
    	mod[14] = mod[2]*pos.x+mod[6]*pos.y+mod[10]*pos.z+mod[14];
    	mod[15] = mod[3]*pos.x+mod[7]*pos.y+mod[11]*pos.z+mod[15];
    }
    

    Und aktiviere die neue Matrix in OpenGL mit:

    **glLoadMatrixf(&CGLmatrix::m_m0[0][0]);
    **

    Das Problem ist bei meiner Ansteuerung,die einer 3D Egoperspektive entspricht,
    das dort nur noch wirkt : "gehe n vorwärts mit Winkel a°"

    Also: yaw roll pitch force und einen (rl-offset).

    Das eigens hergestellte LookAt funktiniert in einem Egoshooter besser.

    Wie das glLookAt von OpenGL wirkt bleibt für mich ein Mysterium da ich
    in OpenGL Y gegen Z vertauschte. Ich benötige geistig das rechthand Koordinatensystem.

    Frage a)
    Wie kann ich am besten eine Tastaturansteuerung herstellen, die aus
    rechts und links up und down eine yaw roll pitch -Ansteuerung für eine Egoperspektiven generiert?

    *Irgendwie gefällt mir nicht die Tastatur eingaben in in eine Flugzeugsteuerung umzurechnen nur um meine Scene immer gleichnamig
    bewegen zu können.
    *

    Ich möchte gerne direkt meine Tastatur so in die Matrix integrieren das rechts "immer" rechts bleibt,egal wie die Rotation der Scene ist.

    Frage b)
    Hat jemand einen anderen Matrixintegrations -Vorschlag der für die einfache
    Aufgabe besser geeignet ist ?

    **Video zum bisherigen: http://youtu.be/qfuSzISu0ig
    **
    Gruß
    Karsten



  • http://www.codecolony.de/

    oben links auf "OpenGL" klicken und "camera2" auswählen.

    Tutorial "Advanced camera" ansehen.



  • Hallo,

    danke für deine Antwort, das ist eine nette sammlung examples dort
    ich glaube diese seite habe ich so vor 10 Jahren schon mal besucht
    sie scheint unverändert, was mich freut.

    Die Examples lösen mein Problem nicht, inzwischen sehe ich das Problem so:

    Stellt man das globale Koordinatensystem auf eine Betrachtungsrichtung ein
    (es gibt ja keine kamera in dem Sinne) betrachtet man zb ein ein Objekt von
    oben.

    Es ist einfach dieses durch verschieben des globalen Koordinaten systems zu bewegen.

    Dreht man aber das Objekt zB 45° kann man nicht mehr mit der taste rechts links erwarten,das sich das Objekt weiterhin auf diesem Vektor verscheibt sondern das passiert entlang seines gedrehten koordinaten systems also ein ein bischen X und ein bissel Y, es gild also jetzt mit Sin und Cos genau die fehlenden bestandteile zur Bewegung wieder hinzuzu rechnen.

    Ich habe für das Objekt eine zweite transaltionsmatrix integriert, nun fährt das Objekt wie in einem Spiel unter der eingestellten "Kamera" hindurch.

    Man braucht also mehrere translationen.

    Dennoch muss eine translation in einer Achse erneut mit sin/cos korrigiert werden, also bewege ich das globale achsensystem, rotiere aber nur das
    lokale, möglich durch die multiplikation beider matritzen.

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    
    	CGLcamera *pCam(GetCam());
    	CVertex pos3d,pos(pCam->GetPos()),dir(pCam->GetRot());
    
    	//global translation
    	pCam->LoadIdentity();
    	pCam->CGLmatrix::RotXYZ(-dir);
    	pCam->CGLmatrix::Translate(-pos);
    	pCam->SetActiv();
    
    	//local translation
    	m_terrain.LoadIdentity();
    	m_terrain.RotXYZ(-m_terrain.m_rot);
    	m_terrain.Translate(-m_terrain.m_pos);
    
    	pCam->Mult(m_terrain.GetPtr());
    	pCam->SetActiv();
    
    	m_terrain.RenderGrid(&m_font);
    	glEnable(GL_LIGHTING);
    	m_light.Update((CGLfrustum *)pCam);
    	m_terrain.Render(&m_font);
    	glDisable(GL_LIGHTING);
    

    Ich würde nun gerne eine logische Steuerung abbilden, im Moment
    ist aber die globale Ansicht und die lokale Ansicht vermischt,
    wie stellt man das am besten sterungsseitig dar ? Schließlich gibt es
    ja nun quasi zwei mögliche Manipolatoren oder zwei Kameras Lokal und Global

    Grüße und Erfolg
    K.


Anmelden zum Antworten