Pickle
Mega GP Mania
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.
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.
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.
Once a cube is defined it can be rendered. Again ive tried different combos with the matrices.
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.
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.