Toon posts:

[C++/OpenGL] View matrix veranderen

Pagina: 1
Acties:

Verwijderd

Topicstarter
'k Ben reeds enige tijd aan't zoeken hoe ik een probleem met m'n view matrix kan oplossen.

[edit]Heb alles aangepast op 7/11/04, 19.50u
M'n viewport wordt eerst ingesteld als volgt:
C++:
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
void CGraphicsOGL::Set_ViewportSize(const int iX, const int iY)
{
    iViewportX = iX;
    iViewportY = iY;

    glViewport(0, 0, iViewportX, iViewportY);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // gluPerspective(view angle, aspect ratio of the width to the height, closest distance to the camera
    // before it clips, farthest distance before it stops drawing)
    gluPerspective(70.0f,(GLfloat)iViewportX/(GLfloat)iViewportY, 5.0f, 10000.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void CGraphicsOGL::Set_ViewMatrix(const int iMatrixType)
{
    switch (iMatrixType)
    {
        case VIEWMATRIX_ORTHOGONAL:
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            // last parameters are near and far planes
            //0.1 used to be 0.0, but then text comes after bitmaps in menu's
            glOrtho(0, iViewportX, iViewportY, 0, 0.1f, -0.1f);
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();
            glDisable(GL_DEPTH_TEST);
            break;
        case VIEWMATRIX_PERSPECTIVE:
            glMatrixMode(GL_PROJECTION);    
            glLoadIdentity();
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();
            glEnable(GL_DEPTH_TEST);
            break;
        default:
            break;
    }
}


De render loop is als volgt:
C++:
1
2
3
4
5
6
7
bridgePtr->BeginScene(false);
    rendererPtr->Set_Camera(camera.GetPosition(), camera.GetLookAt(), camera.GetUpPosition());
    sceneObjectManagerPtr->RenderAll();
    rendererPtr->Start_GuiViewMatrix();
    guiObjectManagerPtr->RenderAll();
    rendererPtr->End_GuiViewMatrix();
bridgePtr->EndScene();


De detailcode van het renderen en de camera rotatie code:
C++:
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
66
67
68
69
70
71
72
73
74
75
76
77
void CGraphicsBridgeSDLOGL::BeginScene(bool clearBackBuffer)
{
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    // clear screen and depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
}


void CGraphicsBridgeSDLOGL::EndScene()
{
    // swap the graphics buffers
    SDL_GL_SwapBuffers();
}

void CCameraMover::SetViewByRelMouse(const int iMouseRelX, const int iMouseRelY, const float fMouseSpeed)
{
    float fAngleY, fAngleZ;
    static float fCurrentRotX = 0.0f;

    if (!camPtr)
        return;

    fAngleY = (float)iMouseRelX * fMouseSpeed;
    fAngleZ = (float)iMouseRelY * fMouseSpeed;

    fCurrentRotX -= fAngleZ;  

    // restrict camera up/down view
    if (fCurrentRotX > 1.5f) // in radians
    {
        fCurrentRotX = 1.5f;
    } else if(fCurrentRotX < -1.5f) {
        fCurrentRotX = -1.5f;
    } else {
        // to find the axis we need to rotate around for up and down
        // movements and need to get a perpendicular vector from the
        // camera's view vector and up vector which will be the axis
        CVector3 vAxis = Cross(camPtr->GetLookAt(), camPtr->GetUpVector());
        NormalizeFast(vAxis);
        // rotate around perpendicular axis and along y-axis
        RotateView(fAngleZ, vAxis.coordinates[0], vAxis.coordinates[1], vAxis.coordinates[2]);
        RotateView(fAngleY, 0.0f, 1.0f, 0.0f);
    }
}


void CCameraMover::RotateView(const float fAngle, const float fX, const float fY, const float fZ)
{
    CVector3 vNewView;

    if (!camPtr)
        return;

    // Get the view vector (The direction we are facing)
    CVector3 vView = camPtr->GetLookAt();

    // Calculate the sine and cosine of the angle once
    float fCosTheta = (float)cos(fAngle);
    float fSinTheta = (float)sin(fAngle);

    // Find the new x position for the new rotated point
    vNewView.coordinates[0]  = (fCosTheta + (1.0f - fCosTheta) * fX * fX)    * vView.coordinates[0];
    vNewView.coordinates[0] += ((1.0f - fCosTheta) * fX * fY - fZ * fSinTheta) * vView.coordinates[1];
    vNewView.coordinates[0] += ((1.0f - fCosTheta) * fX * fZ + fY * fSinTheta) * vView.coordinates[2];
    // Find the new y position for the new rotated point
    vNewView.coordinates[1]  = ((1.0f - fCosTheta) * fX * fY + fZ * fSinTheta) * vView.coordinates[0];
    vNewView.coordinates[1] += (fCosTheta + (1.0f - fCosTheta) * fY * fY)        * vView.coordinates[1];
    vNewView.coordinates[1] += ((1.0f - fCosTheta) * fY * fZ - fX * fSinTheta) * vView.coordinates[2];
    // Find the new z position for the new rotated point
    vNewView.coordinates[2]  = ((1.0f - fCosTheta) * fX * fZ - fY * fSinTheta) * vView.coordinates[0];
    vNewView.coordinates[2] += ((1.0f - fCosTheta) * fY * fZ + fX * fSinTheta) * vView.coordinates[1];
    vNewView.coordinates[2] += (fCosTheta + (1.0f - fCosTheta) * fZ * fZ)     * vView.coordinates[2];

    // add the newly rotated vector to the position to set new rotated camera view
    camPtr->SetLookAt(vNewView);
}


[edit] Het probleem is dat de camerabeweging totaal niet klopt en ik vroeg me af waarom...

Hier is de tot waar ik gekomen ben(nieuwe demo):
http://users.pandora.be/novanet/coding/AlterNovaProb4.zip

[ Voor 175% gewijzigd door Verwijderd op 08-11-2004 22:57 . Reden: set_viewmatrix aangepast ]


  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Hoe wordt die RotateView functie aangeroepen?

www.madwizard.org


Verwijderd

Topicstarter
madwizard schreef op 06 november 2004 @ 20:13:
Hoe wordt die RotateView functie aangeroepen?
Oeps, die was ik vergeten posten :x

[code geschrapt om forum db te sparen, zie code bij TS]

Je geeft hier de relatieve coordinaten tov de vorige door aan de functie.

[ Voor 65% gewijzigd door Verwijderd op 07-11-2004 19:49 ]


  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

C++:
1
2
3
// rotate around perpendicular axis and along y-axis 
RotateView(fAngleZ, vAxis.coordinates[0], vAxis.coordinates[1], vAxis.coordinates[2]); 
RotateView(fAngleY, 1.0f, 1.0f, 0.0f); 

Die 2e RotateView draait zo om een diagonale as (1,1,0), niet om de Y as (0,1,0) zoals in het commentaar staat.

www.madwizard.org


Verwijderd

Topicstarter
madwizard schreef op 06 november 2004 @ 20:31:
C++:
1
2
3
// rotate around perpendicular axis and along y-axis 
RotateView(fAngleZ, vAxis.coordinates[0], vAxis.coordinates[1], vAxis.coordinates[2]); 
RotateView(fAngleY, 1.0f, 1.0f, 0.0f); 

Die 2e RotateView draait zo om een diagonale as (1,1,0), niet om de Y as (0,1,0) zoals in het commentaar staat.
Dat was inderdaad een fout bij het porteren van m'n coden nr de nieuwe engine, thanks!:)
...Maar het klopt nog steeds niet :/

  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Wat klopt er niet precies? Kun je anders een nieuwe demo maken?

www.madwizard.org


Verwijderd

Topicstarter
madwizard schreef op 07 november 2004 @ 00:51:
Wat klopt er niet precies? Kun je anders een nieuwe demo maken?
De rotatie vd camera (dmv de muis) klopt totaal niet.
http://users.pandora.be/novanet/coding/AlterNovaProb2.zip

Het kan wel zijn dat de beweging geinverteerd is, maar dan klopt het nog niet volgens mij.

  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Het enige dat ik nog kan bedenken is dat die GetUpPosition niet goed gaat, die rotatie om de Y-as zou je ook om de up-vector heen kunnen laten gaan, en ik zie de up-vector nergens geroteerd worden. Maar dat hangt ook af van wat voor camera je wilt maken, dat kan ik niet helemaal zien uit deze code. Wat voor camera wil je precies maken?

Als je zoiets wil als in een first-person shooter is het waarschijnlijk makkelijker niet een 'lookat' op te slaan maar een yaw en pitch hoek. Die hoeken update je dan aan de hand van de X en Y deltas (geinverteerd weer), de lookat vector kun je daaruit dan berekenen (yaw rotatie om Y-as, pitch rotatie om X-as).

Voor een volledig vrije camera die echt alle kanten uit kan kijken (alsof je vliegt dus) kun je waarschijnlijk het best met quaternions werken.

www.madwizard.org


Verwijderd

Topicstarter
De camera is een standaard first person shooter camera. De UpVector is steeds 0,1,0 totnogtoe, want die wordt niet aangepast (of nog niet aangepast). Hij wijst dus steeds naar boven.

  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Het lijkt toch wel te kloppen dan, ik neem aan dat de code gebaseerd is op die van gametutorials.com? Ik zie daar precies dezelfde code dus misschien ligt het probleem bij het renderen of het opzetten van de matrix?

edit: Wat ik wel zag in de orginele code is dat de up vector in de constructor op (0,0,1) werd gezet, dus met de Z-as als up-vector ipv de Y-as. Heb je die wel opnieuw ingesteld of meteen goed gezet?

[ Voor 34% gewijzigd door madwizard op 07-11-2004 15:19 ]

www.madwizard.org


Verwijderd

Topicstarter
madwizard schreef op 07 november 2004 @ 15:18:
Het lijkt toch wel te kloppen dan, ik neem aan dat de code gebaseerd is op die van gametutorials.com? Ik zie daar precies dezelfde code dus misschien ligt het probleem bij het renderen of het opzetten van de matrix?

edit: Wat ik wel zag in de orginele code is dat de up vector in de constructor op (0,0,1) werd gezet, dus met de Z-as als up-vector ipv de Y-as. Heb je die wel opnieuw ingesteld of meteen goed gezet?
Jups, daar baseer ik mij op. De UpVector is nu werkelijk 0,1,0, dus hij wijst naar boven zeg maar.
Ik heb ondertussen ook al een aanpassing gedaan zodat de "LookAt" vector relatief is tov de positie-vector.

Hier is een nieuwe demo:
http://users.pandora.be/novanet/coding/AlterNovaProb3.zip

Je kan de camera met de pijltjestoetsen verplaatsen (je moet voorlopig wel meermaals drukken op 1 toets om hem te verzetten, vr debugging redenen). Je ziet dat hij mooi strafed en mooi nr voren gaat. Het probleem ligt dus niet aan m'n scene, maar aan de rotatiefunctie vh zichtsveld.

Hier is de huidige code met relatieve "lookat" vector:

[code geschrapt om forum db te sparen, zie code bij TS]

De reden waarom ik het relatief doe is:
- ik moet geen rekening meer houden met de kijkhoek als ik de camera verplaats
- bij bovenstaande functies moest ik telkens terug de relatieve kijkhoek berekenen om dan dingen te berekenen en hem terug absoluut op te slaan. dat spaart mij nu telkens 2 conversies.

[edit] 'k Herinner me door dit topic steeds meer van statica en dynamica van school :9

[edit]belangrijk
Wat ik raar vind: als je steeds naar voren drukt(een tiental keren pijltje vooruit), dan gaat de driehoek na een tijd verdwijnen. De driehoek zelf is maar enkele units groot (1.5f) en de wereld kan tot 10000.0f renderen alvorens objecten te cullen zeg maar(opengl settings staan zo), dus daar kan het niet aan liggen...
Het is alsof iets die driehoek dan wegsnijdt (achter een doorzichtige muur).

[ Voor 49% gewijzigd door Verwijderd op 07-11-2004 19:49 ]


  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Zet je de matrix mode wel weer op GL_MODELVIEW voor dat je gaat renderen? Want Set_ViewMatrix laat dat op GL_PROJECTION staan.

www.madwizard.org


Verwijderd

Topicstarter
[quote]madwizard schreef op 07 november 2004 @ 17:22:

Dat prob is opgelost :) Maar 'k Heb nog steeds hetzelfde.

Nu ik de Look vectoor relatief heb gemaakt moest ik ook deze functie aanpassen:

C++:
1
2
3
4
5
6
7
void CGraphicsOGL::Set_Camera(CVector3f vPosition, CVector3f vLook, CVector3f vUpVector)
{
    CVector3f vLookAt = vLook + vPosition;
    gluLookAt(vPosition.coordinates[0],   vPosition.coordinates[1],   vPosition.coordinates[2], 
              vLookAt.coordinates[0],     vLookAt.coordinates[1],     vLookAt.coordinates[2],   
              vUpVector.coordinates[0], vUpVector.coordinates[1], vUpVector.coordinates[2] );
}


Het geeft niet direct een ander resultaat.

Wat ik ook fout deed was het volgende:
Bij CCameraMover::SetViewByRelMouse had ik de variabele fCurrentRotX, maar die moest static zijn en beginnen met 0.0f. Ook dat heb ik nu aangepast, maar 't werkt nog steeds niet...

Ik zet bij de topic start de volledig aangepast code neer, dat is wat duidelijker :)

De download url is nu:
http://users.pandora.be/novanet/coding/AlterNovaProb4.zip

[ Voor 41% gewijzigd door Verwijderd op 07-11-2004 19:53 ]


  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

C++:
1
2
3
        case VIEWMATRIX_PERSPECTIVE: 
            glMatrixMode(GL_PROJECTION);     
            glLoadIdentity(); 

Moet je hier niet weer gluPerspective aanroepen om de projection matrix goed te krijgen?

Dat je driehoek nu rond lijkt te draaien in plaats van de camera, en het clippen terwijl je tot 10000 zou moeten kunnen zien lijken er wel op te wijzen dat er ergens iets goed mis gaat met de projection of model-view matrix. De code die je tot nu toe gepost hebt klopt volgens mij allemaal wel, en met gluLookAt kan ook weinig mis gaan. Het moet dus wel aan een ander stuk code liggen maar ik denk toch eerder aan iets met de matrix (verkeerde mode, push/pop die niet matcht, vergeten terug te zetten, etc.). Loop die dingen nog een keer goed na, of probeer het zonder het hele ortho-gedeelte met alleen perspective view.

www.madwizard.org


Verwijderd

Topicstarter
Thanks, dat was een zeer goede tip. 'k Heb nog wat gezocht online en heb het als volgt opgelost (kzet hier enkel de render loop, met rechtstreeks opengl functies, want das het enkele relevante).

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        bridgePtr->BeginScene(false);

            glViewport(0, 0, 640, 480);
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            glFrustum(-1,1,-1,1,4,100); // first 4 param larger => larger viewing field
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();

            rendererPtr->SetCamera(camera.GetPosition(), camera.GetLookAt(), camera.GetUpVector());

            sceneObjectManagerPtr->RenderAll();
            rendererPtr->StartGuiViewMatrix();
            guiObjectManagerPtr->RenderAll();
            rendererPtr->EndGuiViewMatrix();

        bridgePtr->EndScene();


[edit] HEEL erg bedankt voor je moeite trouwens!!!

[ Voor 7% gewijzigd door Verwijderd op 08-11-2004 21:53 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:32

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het is overigens handiger het hele matrix gedeelte in eigen handen te nemen en vervolgens gewoon die matrices zetten met de betreffende functies, ipv dingen als glRotate etc.. Je gaat ze op een gegeven moment toch wel nodig hebben om bepaalde berekeningen te doen, en het opvragen van de huidige matrix in opengl is niet de manier om dat het efficientst te bewerkstelligen :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
.oisyn schreef op 08 november 2004 @ 22:25:
Het is overigens handiger het hele matrix gedeelte in eigen handen te nemen en vervolgens gewoon die matrices zetten met de betreffende functies, ipv dingen als glRotate etc.. Je gaat ze op een gegeven moment toch wel nodig hebben om bepaalde berekeningen te doen, en het opvragen van de huidige matrix in opengl is niet de manier om dat het efficientst te bewerkstelligen :)
Daar was ik gisteren over aan't nadenken, vermits je dat in een ander topic van mij ook vermeldde ik aan't nadenken was over eigenschappen van een object zoals "vScale" en "vRotate". Als ik die eigenschappen met opengl zou manipuleren, dan kan ik dat niet verhandelen met collisiedetectie.

Is dat nie quaternions of matrix-berekeningen? (berekeningen met de 4x4 matrix die de wereld/camera voorstelt?)

[edit] Toen had je het ook over scene graphs oid, zodat je objecten relatief kan positioneren tov root objecten. Zoiets van wereld->huis->kamer->deur->deurknop, met allemaal relatieve coordinaten tov de vorige?

[ Voor 16% gewijzigd door Verwijderd op 08-11-2004 22:54 ]

Pagina: 1