3D Objects with OpenGL & SDL
Terrain Source
#include "Terrain.h"
//#include <GL\gl.h>
//#include <GL\glu.h>
//#include "../gl/glut.h"
#include <cstdio>
//-----------------------------------------------------------------------------------------------
Terrain::Terrain()
{
}
//-----------------------------------------------------------------------------------------------
Terrain::~Terrain()
{
}
//-----------------------------------------------------------------------------------------------
bool Terrain::Initialise()
{
const char heightmapFilename[] = "heightmap.raw";
FILE *pFile;
fopen_s(&pFile, heightmapFilename, "rb");
if (!pFile)
return false;
fread(&heightmap, TERRAIN_SIZE * TERRAIN_SIZE, 1, pFile);
fclose(pFile);
return true;
}
//-----------------------------------------------------------------------------------------------
void Terrain::Render()
{
glPolygonMode(GL_FRONT, GL_LINE);
//Draw the terrain
for (int z = 0; z < TERRAIN_SIZE - 1; ++z)
{
glBegin(GL_TRIANGLE_STRIP);
for (int x = 0; x < TERRAIN_SIZE; ++x)
{
//Render two vertices of the strip at once
float scaledHeight = heightmap[z * TERRAIN_SIZE + x] / SCALE_FACTOR;
float nextScaledHeight = heightmap[(z + 1)* TERRAIN_SIZE + x] / SCALE_FACTOR;
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)z/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), scaledHeight, static_cast<GLfloat>(z - TERRAIN_SIZE/2));
glTexCoord2f((GLfloat)x/TERRAIN_SIZE*8, (GLfloat)(z+1)/TERRAIN_SIZE*8);
glVertex3f(static_cast<GLfloat>(x - TERRAIN_SIZE/2), nextScaledHeight, static_cast<GLfloat>(z + 1 - TERRAIN_SIZE/2));
}
glEnd();
}
//draw the water
/* glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex3f(-TERRAIN_SIZE/2.1f, WATER_HEIGHT, TERRAIN_SIZE/2.1f);
glTexCoord2f(TERRAIN_SIZE/4.0f, 0.0);
glVertex3f(TERRAIN_SIZE/2.1f, WATER_HEIGHT, TERRAIN_SIZE/2.1f);
glTexCoord2f(TERRAIN_SIZE/4.0f, TERRAIN_SIZE/4.0f);
glVertex3f(TERRAIN_SIZE/2.1f, WATER_HEIGHT, -TERRAIN_SIZE/2.1f);
glTexCoord2f(0.0, TERRAIN_SIZE/4.0f);
glVertex3f(-TERRAIN_SIZE/2.1f, WATER_HEIGHT, -TERRAIN_SIZE/2.1f);
glEnd();*/
}
//-----------------------------------------------------------------------------------------------
void Terrain::Update(float deltaTime)
{
}
//-----------------------------------------------------------------------------------------------
Main Source
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_mixer.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include "Constants.h"
#include "Commons.h"
#include "GameScreenManager.h"
using namespace::std;
//-----------------------------------------------------------------------------------------------------
//Local function prototypes.
bool InitSDL();
SDL_Surface* LoadSurface(string path);
void LoadMusic(string path);
void CloseSDL();
void Render();
bool Update();
//-----------------------------------------------------------------------------------------------------
//Globals.
SDL_Window* gWindow = NULL;
SDL_GLContext gGLContext = NULL;
//SDL_Renderer* gRenderer = NULL;
SDL_Surface* gSurface = NULL;
Mix_Music* gMusic = NULL;
Uint32 gOldTime;
GameScreenManager* gameScreenManager;
//-----------------------------------------------------------------------------------------------------
int main(int argc, char* args[])
{
//Initialise SDL.
if(InitSDL())
{
//Set up the game screen manager - Start with Level1
gameScreenManager = new GameScreenManager(SCREEN_LEVEL1);
//Start the music.
//LoadMusic("Music/bubble-bobble.mp3");
if(Mix_PlayingMusic() == 0)
{
Mix_PlayMusic(gMusic, -1);
}
bool quit = false;
gOldTime = SDL_GetTicks();
//Game Loop.
while(!quit)
{
Render();
quit = Update();
}
}
//Close Window and free resources.
CloseSDL();
return 0;
}
//-----------------------------------------------------------------------------------------------------
bool InitSDL()
{
//Setup SDL.
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
cout << "SDL did not initialise. Error: " << SDL_GetError();
return false;
}
else
{
//Attempt to set texture filtering to linear.
if(!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
{
cout << "Warning: Linear texture filtering not available";
}
//All good, so attempt to create the window.
gWindow = SDL_CreateWindow("OpenGL SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
gGLContext = SDL_GL_CreateContext(gWindow);
//Did the window get created?
if(gWindow != NULL)
{
/* //Initialise the Mixer.
if(Mix_OpenAudio( 44100, MIX_DEFAULT_FORMAT, 2, 2048 ) < 0)
{
cout << "Mixer could not initialise. Error: " << Mix_GetError();
return false;
}*/
}
else
{
//Nope.
cout << "Window was not created. Error: " << SDL_GetError();
return false;
}
}
return true;
}
//-----------------------------------------------------------------------------------------------------
SDL_Surface* LoadSurface(string path)
{
SDL_Surface* pLoadedSurface = NULL;
SDL_Surface* pOptimizedSurface = NULL;
//Load the image.
pLoadedSurface = IMG_Load(path.c_str());
if(pLoadedSurface == NULL)
{
cout << "Failed to load image. Error: " << SDL_GetError();
return NULL;
}
else
{
//Convert the surface to the screen format.
pOptimizedSurface = SDL_ConvertSurface( pLoadedSurface, gSurface->format, NULL);
if(pOptimizedSurface == NULL)
{
cout << "Unable to optimize the surface. Error: " << SDL_GetError();
return NULL;
}
//Free the memory used for the loaded surface.
SDL_FreeSurface(pLoadedSurface);
}
return pOptimizedSurface;
}
//-----------------------------------------------------------------------------------------------------
void LoadMusic(string path)
{
gMusic = Mix_LoadMUS(path.c_str());
if(gMusic == NULL)
{
cout << "Failed to load background music! Error: " << Mix_GetError() << endl;
}
}
//-----------------------------------------------------------------------------------------------------
void CloseSDL()
{
//Destroy the game screen manager.
delete gameScreenManager;
gameScreenManager = NULL;
//Destroy the window.
//SDL_DestroyRenderer(gRenderer);
//gRenderer = NULL;
SDL_DestroyWindow(gWindow);
gWindow = NULL;
SDL_GL_DeleteContext(gGLContext);
gGLContext = NULL;
//Release music.
Mix_FreeMusic(gMusic);
gMusic = NULL;
//Quit SDL subsystems.
IMG_Quit();
SDL_Quit();
}
//-----------------------------------------------------------------------------------------------------
void Render()
{
gameScreenManager->Render();
//Update the screen.
SDL_GL_SwapWindow(gWindow);
}
//-----------------------------------------------------------------------------------------------------
bool Update()
{
//Get the new time.
Uint32 newTime = SDL_GetTicks();
//Event Handler.
SDL_Event e;
//Get the events.
SDL_PollEvent(&e);
//Handle any events.
switch(e.type)
{
//Click the 'X' to quit.
case SDL_QUIT:
return true;
break;
default:
gameScreenManager->Update((float)(newTime-gOldTime)/1000.0f, e);
break;
}
//Set the current time to be the old time.
gOldTime = newTime;
return false;
}
//-----------------------------------------------------------------------------------------------------
3D Object Source
#include "object3DS.h"
#include "../gl/glut.h"
#include"3dsLoader.h"
#include <iostream>
#include <fstream>
using namespace::std;
Object3DS::Object3DS(Vector3D startPosition, string modelFileName)
{
//Start position
mPosition = startPosition;
//3ds file load
std::strcpy(fileName, modelFileName.c_str());
loadModel();
}
//------------------------------------------------------------------------
void Object3DS::loadModel()
{
if (fileName[0] != '-')
Load3DS(&object, fileName);
}
//------------------------------------------------------------------------
void Object3DS::loadTexture(char* path)
{
//TODO: Load a texture to map to the object
ifstream inFile;
inFile.open(path);
if (!inFile.good())
{
cerr << "Cannot open model file! " << path << endl;
return;
}
inFile >> numVertices;
if (numVertices > 0)
{
indexedVertices = new vertex_type[numVertices];
for (int i = 0; i < numVertices; i++)
{
inFile >> indexedVertices[i].x;
inFile >> indexedVertices[i].y;
inFile >> indexedVertices[i].z;
}
}
int numTriangles;
inFile >> numTriangles;
indexCount = numTriangles * 3;
if (indexCount > 0)
{
indices = new GLushort[indexCount];
for (int i = 0; i < indexCount; i++)
{
inFile >> indices[i];
}
}
inFile.close();
return;
}
//------------------------------------------------------------------------
void Object3DS::update(float deltaTime)
{
//TODO: Move object here
mCurrentTime += deltaTime;
rotation += 0.1f;
}
//------------------------------------------------------------------------
void Object3DS::render()
{
glPushMatrix();
glTranslatef(mPosition.x, mPosition.y, mPosition.z);
//glBindTexture(GL_TEXTURE_2D, object.id_texture); //We set the active texture
glBegin(GL_TRIANGLES);
for (int l_index = 0; l_index < object.polygon_qty; l_index++)
{
//-------------FIRST_VERTEX------------------
//Texture coordinates of the first vertex
//glTexCoord2f(object.mapcoord[object.polygon[l_index].a ].u'
// object.mapcoord[object.polygon[l_index].a ].v);
//Coordinates of the first vertex
glVertex3f(object.vertex[object.polygon[l_index].a].x,
object.vertex[object.polygon[l_index].a].y,
object.vertex[object.polygon[l_index].a].z); //Vertex definition
//-------------SECOND_VERTEX------------------
//Texture coordinates of the first vertex
//glTexCoord2f(object.mapcoord[object.polygon[l_index].b ].u'
// object.mapcoord[object.polygon[l_index].b ].v);
//Coordinates of the second vertex
glVertex3f(object.vertex[object.polygon[l_index].b].x,
object.vertex[object.polygon[l_index].b].y,
object.vertex[object.polygon[l_index].b].z); //Vertex definition
//-------------THIRD_VERTEX------------------
//Texture coordinates of the first vertex
//glTexCoord2f(object.mapcoord[object.polygon[l_index].c ].u'
// object.mapcoord[object.polygon[l_index].c ].v);
//Coordinates of the third vertex
glVertex3f(object.vertex[object.polygon[l_index].c].x,
object.vertex[object.polygon[l_index].c].y,
object.vertex[object.polygon[l_index].c].z); //Vertex definition
}
glEnd();
glPopMatrix();
}