top of page

3D Objects with OpenGL & SDL

  • YouTube Social  Icon

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();
}

© 2016 by Daniel Bognar. Proudly created with Wix.com

  • Facebook Social Icon
bottom of page