D3D And Opengl Conversions


Pickle

Mega GP Mania
Joined
May 30, 2006
Messages
5,518
Location
Detroit, Michigan
Website
Visit site
This was meant as a learning exercise for myself to push my openGL knowledge and attempt to learn some D3D while im at it. Im hitting a wall and im hoping some more experienced people can help straighten me out.

Im porting a pretty basic game, which was intentional. Its some puzzle game with a bunch of cubes. I think I have a good replacement for the geometry using VBO's and vertex arrays and textures. I think my hang up is the matrices. I tried to convert with openGL-ES in mind, but at the moment I do what ever it takes to work, then readjust later.

Im going to try to post the most important code, but it may take some grabbing my entire source and giving it a look through. Im using SDL/GL and GLU to replace D3D API.

This first part is the basic setup of the screen/viewport/perspective and starting the camera.

Code:
bool CGameApp::CreateDisplay() {
 
     bool isFullscreen       = false;
     uint16_t ScreenWidth    = 640;
     uint16_t ScreenHeight   = 480;
     uint16_t ScreenDepth    = 32;
     uint32_t flags          = SDL_SWSURFACE|SDL_OPENGL;
 
     // Initialize defaults, Video and Audio subsystems
     printf( "Initializing SDL.n" );
     if (SDL_Init( SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_TIMER|SDL_INIT_JOYSTICK )==-1)
     {
         printf( "Failed to initialize SDL: %s.n", SDL_GetError() );
         return false;
     }
     printf( "SDL initialized.n" );
 
     // Setup SDL Screen
     if (isFullscreen == true)
     {
         flags |= SDL_FULLSCREEN;
     }
     Screen = SDL_SetVideoMode( ScreenWidth, ScreenHeight, ScreenDepth, flags );
     if (Screen == NULL)
     {
         printf( "Failed to %dx%dx%d video mode: %sn", ScreenWidth, ScreenHeight, ScreenDepth, SDL_GetError() );
         return false;
     }
 
     /* Init OpenGL */
     GLfloat mat_ambient[] = { 1.0f, 1.0f, 1.0f, 1.0f };
     GLfloat mat_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
     GLfloat light_ambient[] = { 1.0f, 1.0f, 1.0f, 1.0f };
     GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
     GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
     GLfloat light_position[] = { 0.0f, 0.0f, 10.0f, 0.0f };
     GLfloat light_attenuation[] = { 1.0f, 0.5f, 0.5f };
 
     glShadeModel( GL_SMOOTH );                              /* Enable smooth shading */
     glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );                 /* Set the background black */
     glClearDepth( 1.0f );                                   /* Depth buffer setup */
 
     // Setup light and material
     //glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
     //glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
 /*
     glLightfv( GL_LIGHT0, GL_AMBIENT, light_ambient );
     glLightfv( GL_LIGHT0, GL_DIFFUSE, light_diffuse );
     glLightfv( GL_LIGHT0, GL_SPECULAR, light_specular );
     glLightfv( GL_LIGHT0, GL_POSITION, light_position );
     glLightf( GL_LIGHT0, GL_CONSTANT_ATTENUATION, light_attenuation[0] );
     glLightf( GL_LIGHT0, GL_LINEAR_ATTENUATION, light_attenuation[1] );
     glLightf( GL_LIGHT0, GL_QUADRATIC_ATTENUATION, light_attenuation[2] );
 */
     glEnable( GL_LIGHTING );
     glEnable( GL_LIGHT0 );
     glEnable( GL_TEXTURE_2D );
     //glEnable( GL_DEPTH_TEST );                              /* Enables Depth Testing */
     //glDepthFunc( GL_LEQUAL );                               /* The Type Of Depth Test To Do */
     glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );    /* Really Nice Perspective Calculations */
 
     glViewport( 0, 0, (GLsizei)ScreenWidth, (GLsizei)ScreenHeight );    /* Setup our viewport. */
 
     glMatrixMode( GL_PROJECTION );    /* change to the projection matrix and set our viewing volume. */
     glLoadIdentity();
     gluPerspective( 45.0f, (GLfloat)ScreenWidth / (GLfloat)ScreenHeight, 1.0f, 10.0f );    /* Set our perspective */
 
     glMatrixMode( GL_MODELVIEW );   /* Make sure we're changing the model view and not the projection */
     glLoadIdentity();               /* Reset The View */
     //glScalef( 1.0f, 1.0f, -1.0f );  /* Switch to a LH coord system */
 
     camera = new GDtSphericCamera();
     camera->GetViewMatrix();
 
     return true;
 }


The camera using gluLookAt to setup the view (I believe this should modify the MODELVIEW matrix) I then use glScale to invert the Z axis to convert from RH to LH.

Code:
D3DXMATRIXA16* GDtSphericCamera::GetViewMatrix() {
 ...
     // Update matrix if something changed
     if (updateCamera) {
 #if defined(PLATFORM_WIN32)
         D3DXMatrixLookAtLH(&matView, m_pCameraLoc3D, m_pLookatPt, m_pUpVector3D);
 #elif defined(PLATFORM_LINUX)
         glMatrixMode( GL_MODELVIEW );
         glLoadIdentity();
         gluLookAt( m_pCameraLoc3D->x,   m_pCameraLoc3D->x,  m_pCameraLoc3D->z,
                    m_pLookatPt->x,      m_pLookatPt->y,     m_pLookatPt->z,
                    m_pUpVector3D->x,    m_pUpVector3D->y,   m_pUpVector3D->z );
         glScalef( 1.0f, 1.0f, -1.0f ); /* Switch to a LH coord system */
 #endif
         time = nowtime;
     }
 ....
 }

Next comes the object placement, in the source there is a base cube class and a bunch of other cubes that inherit the base class. Each cube class sets up its position.
Ive tried different things here, either starting with the Identity Matrix or using the current matrix (camera position). Neither has seems to work yet.

Code:
#if defined(PLATFORM_WIN32)
     D3DXMATRIXA16 matTmp;
     D3DXMatrixScaling(&matWorld, 0.1f, 0.1f, 0.1f);
     D3DXMatrixTranslation(&matTmp, worldx, worldy, worldz);
     D3DXMatrixMultiply(&matWorld, &matWorld, &matTmp);
 
     // Load the box texture
     D3DXCreateTextureFromFile(m_pD3DDevice, "Textures\BlackBlock.jpg",    &m_pTex);
 #elif defined(PLATFORM_LINUX)
     glMatrixMode( GL_MODELVIEW );
     glPushMatrix();
         //glLoadIdentity();
         //glScalef( 1.0f, 1.0f, -1.0f );
         glScalef( 0.1f, 0.1f, 0.1f );
         glTranslatef( worldx, worldy, worldz );
         glGetFloatv( GET_MODELVIEW_MATRIX, matWorld.matrix );
     glPopMatrix();
 
     m_pTex = loadTexture( "Textures/BlackBlock.jpg" );
 #endif

Once a cube is defined it can be rendered. Again ive tried different combos with the matrices.

Code:
 bool GDtQube::Render() {
 #if defined(PLATFORM_WIN32)
     D3DXMATRIX matTmp1,matTmp2;
 #elif defined(PLATFORM_LINUX)
     glMatrixMode( GL_MODELVIEW );
     glPushMatrix();
 
     //D3DXMATRIXA16 matTemp;
     //glGetFloatv( GET_MODELVIEW_MATRIX, matTemp.matrix );
     glLoadMatrixf( matWorld.matrix );
 #endif
 
     // Get current time
     DWORD nowtime = GetTickCount();
 
     // do nothing if this qube isn't active
     if (!m_bActive) return false;
 
     // Do the fall, if qube has rolled off the edge
     if (posz < 0) {
         // If the box is off the stage, make it fall
 #if defined(PLATFORM_WIN32)
         D3DXMatrixTranslation(&matTmp1, 0.0f, -0.05f, 0.0f);
         D3DXMatrixMultiply(&matWorld, &matWorld, &matTmp1);
 #elif defined(PLATFORM_LINUX)
         glTranslatef( 0.0f, -0.05f, 0.0f );
 #endif
         worldy -= 0.05f;
 
         if (worldy < -20.0f) m_bActive = FALSE;
 
     } else if (m_bCollapsing) {
         //scaling -= 0.001f;
 #if defined(PLATFORM_WIN32)
         D3DXMatrixTranslation(&matTmp1, 0.0f, 0.0f, 0.0f);
         D3DXMatrixMultiply(&matWorld, &matTmp1, &matWorld);
 #elif defined(PLATFORM_LINUX)
         glTranslatef( 0.0f, 0.0f, 0.0f );
 #endif
         //if (scaling <= 0.0f) m_bActive = FALSE;
 
     } else if (nextz < posz) {
         // Do the advance, if required
         amtRotated += (float)( (D3DX_PI / 2.0f) / advTime * (nowtime - time));
 
         // Do rotation
 #if defined(PLATFORM_WIN32)
         D3DXMatrixTranslation(&matTmp1, 0.0f, 1.0f, +1.0f);
         D3DXMatrixRotationX(&matTmp2, -(float)( (D3DX_PI / 2.0f) / advTime * (nowtime - time)));
         D3DXMatrixMultiply(&matTmp2, &matTmp1, &matTmp2);
 
         D3DXMatrixTranslation(&matTmp1, 0.0f, -1.0f, -1.0f);
         D3DXMatrixMultiply(&matTmp2, &matTmp2, &matTmp1);
 
         D3DXMatrixMultiply(&matWorld, &matTmp2, &matWorld);
 #elif defined(PLATFORM_LINUX)
         glTranslatef( 0.0f, 1.0f, +1.0f );
         glRotatef( -(float)( (D3DX_PI / 2.0f) / advTime * (nowtime - time)), 1.0f, 0.0f, 0.0f );
         glTranslatef( 0.0f, -1.0f, -1.0f );
 #endif
         // if we've rotated 45 degrees, reset the world matrix to the new position, and also
         // set posz = newz and m_bAdvancing = FALSE
         if (amtRotated >= D3DX_PI / 2.0f && m_bAdvancing) {
             posz = nextz;
             worldz = ftlz + 0.2f * posz;
 
 #if defined(PLATFORM_WIN32)
             D3DXMatrixRotationX(&matTmp2, -(float)(D3DX_PI / 2.0f) );
             D3DXMatrixScaling(&matWorld, 0.1f, 0.1f, 0.1f);
             //D3DXMatrixMultiply(&matWorld, &matWorld, &matTmp2);
 
             D3DXMatrixTranslation(&matTmp1, worldx, worldy, worldz);
             D3DXMatrixMultiply(&matWorld, &matWorld, &matTmp1);
 #elif defined(PLATFORM_LINUX)
             glRotatef( -(float)(D3DX_PI / 2.0f), 1.0f, 0.0f, 0.0f );
             glScalef( 0.1f, 0.1f, 0.1f );
             glTranslatef( worldx, worldy, worldz );
 #endif
 
             m_bAdvancing = FALSE;
         }
 
         // Update time
         time = nowtime;
     }
 
 #if defined(PLATFORM_WIN32)
     m_pD3DDevice->SetStreamSource(0, m_pVB, 0, sizeof(CUSTOMVERTEX));
     m_pD3DDevice->SetTexture(0, m_pTex);
 
     m_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
 
     m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 12);        //top
 #elif defined(PLATFORM_LINUX)
     //glMultMatrixf( matTemp.matrix );
     glGetFloatv( GET_MODELVIEW_MATRIX, matWorld.matrix );
 
     glBindTexture( GL_TEXTURE_2D, m_pTex );
     glBindBuffer( GL_ARRAY_BUFFER, m_pVB );
 
     glEnableClientState( GL_VERTEX_ARRAY );
     glEnableClientState( GL_COLOR_ARRAY );
     glEnableClientState( GL_TEXTURE_COORD_ARRAY );
 
     glVertexPointer( 3, GL_FLOAT, STRIDE, BUFFER_OFFSET(0) );
     glColorPointer( 4, GL_FLOAT, STRIDE, BUFFER_OFFSET(3) );
     glTexCoordPointer( 2, GL_FLOAT, STRIDE, BUFFER_OFFSET(7) );
     glDrawArrays( GL_TRIANGLES, 0, 36 );
 
     glDisableClientState( GL_TEXTURE_COORD_ARRAY );
     glDisableClientState( GL_COLOR_ARRAY );
     glDisableClientState( GL_VERTEX_ARRAY );
 
     glBindBuffer( GL_ARRAY_BUFFER, 0 );
     glPopMatrix();
 #endif
     return true;
 }

Its a lot, but im hoping someone can help get over the hump. And let me know if i should post more bits.

Update: from a suggestion im going to try and redo the matrix handling with a 3rd party option.
 
If the code in question already has the drawing operations abstracted (judging from the snippets this seems to be the case - there are abstractions for a cube, a camera, and "display creation"), I would
rather refactor the code into seperate D3D and GL implementations - ie NOT do line-by-line #ifdefs, but rather figure out what the calling code
excepts to happen and then have two separate implementations of each class.
 
at a first glance --

Code:
#elif defined(PLATFORM_LINUX)
     glMatrixMode( GL_MODELVIEW );
     glPushMatrix();
 
     //D3DXMATRIXA16 matTemp;
     //glGetFloatv( GET_MODELVIEW_MATRIX, matTemp.matrix );
     glLoadMatrixf( matWorld.matrix );
 #endif
 
     // Get current time
     DWORD nowtime = GetTickCount();
 
     // do nothing if this qube isn't active
     if (!m_bActive) return false;

there's glPush + glLoadMatrix but the glPopMatrix is missing in the case if the "if (!m_bActive) " condition is met. so you're screwing the matrix stack here.
 
crow_riot said:
there's glPush + glLoadMatrix but the glPopMatrix is missing in the case if the "if (!m_bActive) " condition is met. so you're screwing the matrix stack here.

Your right, i fixed it, but nothing improved. So i continued on with the plan to switch a 3rd party tool and its paid off. im using CML : http://cmldev.net/
Its turning out to be a very clean change as Ive been able to redefine most D3D calls to CML calls and then load the final matrix to opengl. I can now make out my skybox and geometry. Textures are not being drawn correctly, so i will have to continue to look into it.
 
Last edited by a moderator:
Back
Top