Avatar billede zerohero Nybegynder
31. oktober 2001 - 00:28 Der er 14 kommentarer og
1 løsning

OpenGL - Haster

Jeg rotere en box omkring (world coordinate system) 0,0,0 ved at gøre følgende:

eksempel:

  glpushmatrix;
  glrotatef(25.0,1.0,0.0,0.0);
  gltranslatef(5.0,5.0,5.0);
  DrawBox();
  glpopmatrix;

nu er boxen roteret og flyttet til nye (x,y,z) koordinater, men hvordan kan jeg nu få koordinaterne af vide?
Og skal jeg virklig til at lave en beregning med cosinus og sinus for at finde alle de nye (x,y,z) koordinater på mine vertices i min box?
Findes der et eller andet smart OpenGL kald eller kan jeg kalde dem frem fra min matrix-stack?

Håber I forstår mit spørgsmål...
Avatar billede soreno Praktikant
31. oktober 2001 - 07:41 #1
Kunne du ikke uddybe:
hvorfor vil du vide kordinaterne?
Hvad skal det bruges til?
Avatar billede jpk Nybegynder
31. oktober 2001 - 08:41 #2
I DirectX kan du:
1) Lave en rotationsmatrix
2) Lave en translationsmatrix
3) Gange dem sammen
4) Transformere hver vertex af dit 3D-objekt med den resulterende matrix
5) Aflæse de ny koordinater...

Måske du kan gøre noget lign. i Open GL..?
Avatar billede zerohero Nybegynder
31. oktober 2001 - 09:23 #3
soreno>> Jo grunden er at jeg er ved at lave en modellerings program. Så når jeg rotere forskellige objekter, vertex osv. skal jeg bruge alle koordinater når jeg skal gemme scenen i en fil.

jpk>> det lyder som en mulighed. Kan du lave et hurtigt eksempel?
Avatar billede zerohero Nybegynder
31. oktober 2001 - 09:28 #4
soreno>> Desuden vil det være meget godt at vide når jeg senere vil lave en kollisions-detekter...
Avatar billede jpk Nybegynder
31. oktober 2001 - 10:42 #5
Følgende er et udpluk fra en klasse jeg har lavet til ca. samme formål.
Metoderne er selvfølgelig DirectX8 specifikke, idet jeg kalder metoder so fx D3DXMatrixRotationYawPitchRoll, men måske der eksisterer der lign. metoder i OpenGL?


// MoveTo : Moves object to a specific location (based on the objects center)
HRESULT CMeshObject::MoveTo(float x, float y, float z)
{
    LPDIRECT3DVERTEXBUFFER8 pVB;
    D3DVERTEX* pVertices;
    // Gain access to the model\'s vertices
    GetSysMemMesh()->GetVertexBuffer(&pVB);
    pVB->Lock(0, 0, (BYTE**)&pVertices, 0);
    DWORD dwNumVertices = GetSysMemMesh()->GetNumVertices();

    D3DXVECTOR3  vCenter;
    FLOAT        fRadius;
    D3DXComputeBoundingSphere(pVertices, dwNumVertices, D3DFVF_MODELVERTEX, &vCenter, &fRadius);

    D3DXVECTOR3 move(x, y, z);
    move -= vCenter;
    for( DWORD i=0; i<dwNumVertices; i++ )
    {
        pVertices[i].p += move;
    }

    // Done with the vertex buffer
    pVB->Unlock();
    pVB->Release();

    return S_OK;
}

// MoveBy : Moves object in the direction given by x, y and z
HRESULT CMeshObject::MoveBy(float x, float y, float z)
{
    LPDIRECT3DVERTEXBUFFER8 pVB;
    D3DVERTEX* pVertices;
    // Gain access to the model\'s vertices
    GetSysMemMesh()->GetVertexBuffer(&pVB);
    pVB->Lock(0, 0, (BYTE**)&pVertices, 0);

    D3DXVECTOR3 move(x, y, z);
    DWORD dwNumVertices = GetSysMemMesh()->GetNumVertices();
    for(DWORD i=0; i<dwNumVertices; i++)
    {
        pVertices[i].p += move;
    }

    // Done with the vertex buffer
    pVB->Unlock();
    pVB->Release();

    return S_OK;
}

HRESULT CMeshObject::RotateYawPitchRoll(float x, float y, float z)
{
    D3DXMATRIX rot;
    D3DXMatrixRotationYawPitchRoll(&rot, x, y, z);

    return DoTransform(rot);
}

HRESULT CMeshObject::RotateAxis(D3DXVECTOR3* pV, float angle)
{
    D3DXMATRIX rot;
    D3DXMatrixRotationAxis(&rot, pV, angle);
   
    return DoTransform(rot);
}

HRESULT CMeshObject::RotateX(float angle)
{
    D3DXMATRIX rot;
    D3DXMatrixRotationX(&rot, angle);

    return DoTransform(rot);
}

HRESULT CMeshObject::RotateY(float angle)
{
    D3DXMATRIX rot;
    D3DXMatrixRotationY(&rot, angle);

    return DoTransform(rot);
}

HRESULT CMeshObject::RotateZ(float angle)
{
    D3DXMATRIX rot;
    D3DXMatrixRotationZ(&rot, angle);

    return DoTransform(rot);
}

HRESULT CMeshObject::DoTransform(D3DXMATRIX& mat)
{
    LPDIRECT3DVERTEXBUFFER8 pVB;
    D3DVERTEX* pVertices;
    // Gain access to the model\'s vertices
    GetLocalMesh()->GetVertexBuffer(&pVB);
    pVB->Lock(0, 0, (BYTE**)&pVertices, 0);
    DWORD dwNumVertices = GetSysMemMesh()->GetNumVertices();

    D3DXVECTOR4 pOut;
    for(DWORD i=0; i<dwNumVertices; i++)
    {
        D3DXVec3Transform(&pOut, &pVertices[i].p, &mat);
        pVertices[i].p.x = pOut.x;
        pVertices[i].p.y = pOut.y;
        pVertices[i].p.z = pOut.z;
    }

    // Done with the vertex buffer
    pVB->Unlock();
    pVB->Release();

    return S_OK;
}
Avatar billede jpk Nybegynder
31. oktober 2001 - 10:45 #6
Jeg bruger så nedenstående funktioner til at afgøre om man vælger et objekt med musen:

// IntersectObject : Returns wheather or not the line described by
//                    the vectors orig and dir intersects with the object
BOOL CMeshObject::IntersectObject(const D3DXVECTOR3& orig, const D3DXVECTOR3& dir)
{
    BOOL RetVal = FALSE;
    LPDIRECT3DVERTEXBUFFER8 pVB;
    LPDIRECT3DINDEXBUFFER8 pIB;

    GetLocalMesh()->GetVertexBuffer(&pVB);
    GetLocalMesh()->GetIndexBuffer(&pIB);

    struct VERTEX { D3DXVECTOR3 p, n; FLOAT tu; FLOAT tv; };
    DWORD dwFVF = GetLocalMesh()->GetFVF();

    WORD*      pIndices;
    VERTEX*    pVertices;
    DWORD      dwNumFaces = GetLocalMesh()->GetNumFaces();
    pIB->Lock( 0,0,(BYTE**)&pIndices, 0 );
    pVB->Lock( 0,0,(BYTE**)&pVertices, 0 );

    for(DWORD i=0; i<dwNumFaces; i++)
    {
        D3DXVECTOR3 v0 = pVertices[pIndices[3*i+0]].p;
        D3DXVECTOR3 v1 = pVertices[pIndices[3*i+1]].p;
        D3DXVECTOR3 v2 = pVertices[pIndices[3*i+2]].p;

        // Check if the pick ray passes through this point
        if( IntersectTriangle(orig, dir, v0, v1, v2))
        {
            RetVal = TRUE;
            //break; // If we break, we are not sure of getting the closest triangle
        }
    }

    pVB->Unlock();
    pIB->Unlock();

    pVB->Release();
    pIB->Release();

    return RetVal;
}

// IntersectTriangle : Given a ray origin (orig) and direction (dir), and three vertices of
//                      of a triangle, this function returns TRUE and the interpolated texture
//                      coordinates if the ray intersects the triangle
BOOL CMeshObject::IntersectTriangle(const D3DXVECTOR3& orig, const D3DXVECTOR3& dir, D3DXVECTOR3& v0, D3DXVECTOR3& v1, D3DXVECTOR3& v2)
{
    //float t, u, v;

    // Find vectors for two edges sharing vert0
    D3DXVECTOR3 edge1 = v1 - v0;
    D3DXVECTOR3 edge2 = v2 - v0;

    // Begin calculating determinant - also used to calculate U parameter
    D3DXVECTOR3 pvec;
    D3DXVec3Cross(&pvec, &dir, &edge2);

    // If determinant is near zero, ray lies in plane of triangle
    FLOAT det = D3DXVec3Dot(&edge1, &pvec);
    if(det < 0.0001f)
        return FALSE;

    // Calculate distance from vert0 to ray origin
    tvec = orig - v0;

    // Calculate U parameter and test bounds
    u = D3DXVec3Dot(&tvec, &pvec);
    if(u < 0.0f || u > det)
        return FALSE;

    // Prepare to test V parameter
    D3DXVECTOR3 qvec;
    D3DXVec3Cross(&qvec, &tvec, &edge1);

    // Calculate V parameter and test bounds
    v = D3DXVec3Dot(&dir, &qvec);
    if(v < 0.0f || u + v > det)
        return FALSE;

    // Calculate t, scale parameters, ray intersects triangle
    t = D3DXVec3Dot( &edge2, &qvec );
    FLOAT fInvDet = 1.0f / det;
    t *= fInvDet;
    u *= fInvDet;
    v *= fInvDet;


    return TRUE;
}
Avatar billede kamikaze Nybegynder
01. november 2001 - 14:10 #7
Jamen, du ved jo hvor du tegner objektet (i forhold til (0.0, 0.0, 0.0)) og du ved hvor meget du translater. De to tal lagt sammen er vel dit objekts nye koordinater?!?!? (Eller har jeg misforstået noget?)
Avatar billede zerohero Nybegynder
01. november 2001 - 20:44 #8
Kamikaze>> ja, problemet er når jeg rotere et objekt, så bliver jeg nærmest nødt til at brug cosinus eller sinus hvis jeg vil, som du foreslår, beregne de nye koordinater... Men hvis der nu fandtes et eller smart trick til at hive koordinater frem (uden brug af \"avanceret\" matematik - eventuelt matrix-stacken) ville det være langt det nemmeste. Jeg mener, grafik kortet må jo nærmest vide det - da den ellers ikke ville kunne rendere scenen.

jpk>> tak for dit indslag men jeg kan ikke rigtigt få det til at fungere i OpenGL...

ZeroHero
Avatar billede soreno Praktikant
01. november 2001 - 20:59 #9
hvordan rotere du dit objekt? du må da udfra roteringen kunne finde frem til kordinaterne?
Avatar billede soreno Praktikant
01. november 2001 - 21:00 #10
jeg mener er det bare noget tilfældigt, eller er det bruger styret (mus, keyboard..) eller hvad?
Avatar billede zerohero Nybegynder
01. november 2001 - 21:05 #11
Jeg rotere via musen - og jeg ved godt, hvad du vil hentyde til (så brug Sinus og Cosinus eller hvad!!!)... :-)
Avatar billede soreno Praktikant
01. november 2001 - 21:18 #12
nu kender jeg ikke dit program, men hvis jeg selv skulle til at lege med opengl igen, så ville jeg lave en lag-delt ting:

en modelkomponent der indeholder mine objekter med de data jeg synes relevant, samt evt. strukturer til andre objekter.
en funktionskomponent der render modellen udfra dataene i modellen
en grænsefaldekomponent der lader brugeren manipulere med dataene i modellen.

- Helt efter ålborgbogens principper..
Avatar billede jpk Nybegynder
01. november 2001 - 21:41 #13
=> soreno
Nu er ålborgbogens principper ikke særlig anvendelige i high performance 3D applikationer (man kan vel i øvrigt diskutere om dens fremgangsmåde i det hele taget er særlig anvendelig...).
Nå men jeg er ikke ude på at starte en religionskrig, så hver sin smag!
Avatar billede zerohero Nybegynder
06. november 2001 - 19:27 #14
Nå, men hvis der ikke er nogen der ved det må jeg nok hellere til at lukke mit spørgsmål...
Avatar billede zerohero Nybegynder
02. januar 2002 - 17:05 #15
Jeg har ikke helt fundet ud af det endnu, men jeg synes nu at jpk har fortjent points i lige vel for hans hjælpsomme sjæl :-))

(undskyld den lange vente tid)...

ZeroHero
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester