All pastes #926662 Raw Edit

graphics.cpp

public text v1 · immutable
·published 2008-03-03 20:08 UTC
rendered paste body
#include <GL/gl.h>
#include <GL/glext.h>

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>

#include <iostream>
#include <sstream>

#include "graphics.h"
#include "core.h"

using namespace std;

namespace gp2d {

// The one and only instance of the window.
// Firstly initialized to NULL, or else we get some errors :)
GP2DWindow* GP2DWindow::m_instance = NULL;

GP2DWindow* GP2DWindow::getInstance() {
    if(m_instance == NULL) { // instance not already created?
        // then create it!
        m_instance = new GP2DWindow();
        // Set the default video API to SDL
        m_instance->setRenderMode(GP2DWindow::GL2D_OPENGL);
    }
    // and return it.
    return m_instance;
}

/**
 * Create a window instance. Done by using GP2DWindow::getInstance(). 
 */
GP2DWindow::GP2DWindow() {
    m_fullScreen = false; // initially, fullscreen mode is OFF.
    m_videoAPI = GP2DWindow::GL2D_OPENGL; // defaults to opengl rendering, rox more.
}

/**
 * Destructor. Deletes some resources occupied by this object.
 */
GP2DWindow::~GP2DWindow() {
    SDL_FreeSurface(m_surfaceScreen);
}

/**
 * Toggles fullscreen mode on, or off. Internally, a bool will be set stating
 * whether the screen is currently in fullscreen mode.
 */
void GP2DWindow::toggleFullScreen() throw(GP2DException) {
    m_fullScreen = !m_fullScreen; // flip the fullscreen boolean indication
    if(m_surfaceScreen != NULL) {
        SDL_WM_ToggleFullScreen(m_surfaceScreen);
    } else {
        throw GP2DException("Fullscreen toggle failed");
    }
}

/**
 * Returns the height of the window.
 */
int GP2DWindow::getHeight() const {
    return m_screenHeight;
}

/**
 * Returns the width of the window.
 */
int GP2DWindow::getWidth() const {
    return m_screenWidth;
}

/**
 * Input grabbing of events.
 */
void GP2DWindow::setInputGrabEnabled(bool enabled) {
    if(enabled) {
        SDL_WM_GrabInput(SDL_GRAB_ON);
    } else {
        SDL_WM_GrabInput(SDL_GRAB_OFF);
    }
}

/**
 * Graphic defaults. Can be called at any time.
 */
void GP2DWindow::setGraphicsDefaults() {
    if(m_videoAPI == GP2D_SDL){
    } else {
        glShadeModel(GL_SMOOTH); // smooth shading.
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // black is the default clearing color.
    
        glEnable(GL_LINE_SMOOTH); // smooth lining (anti aliasing?)
        glEnable(GL_POINT_SMOOTH); // point smoothing
        glEnable(GL_POLYGON_SMOOTH); // polygon smoothing
        glEnable(GL_TEXTURE_2D); // enable 2D texturisation.
        glEnable(GL_BLEND); // enable (alpha) blending.
    }
}

/**
 * Sets the window title.
 */
void GP2DWindow::setWindowTitle(string title) {
    SDL_WM_SetCaption(title.c_str(), NULL);
}

/**
 * Sets the no-frame flag.
 */
void GP2DWindow::setFlagNoFrame() {
    m_videoFlags |= SDL_NOFRAME;
}

/**
 * Sets resizable flag.
 */
void GP2DWindow::setFlagResizable() {
    m_videoFlags |= SDL_RESIZABLE;
}

/**
 * Clear the screen.
 */
void GP2DWindow::clearScreen() {
    GP2DWindow* window = GP2DWindow::getInstance();
    if(window->getRenderMode() == GP2DWindow::GP2D_SDL){
    } else {
        glClear(GL_COLOR_BUFFER_BIT);
    }
}

/**
 * Synchronize buffers.
 */
void GP2DWindow::sync() {
    GP2DWindow* window = GP2DWindow::getInstance();
    if(window->getRenderMode() == GP2DWindow::GP2D_SDL){
    } else {
        glFlush(); // for single buffer only
        SDL_GL_SwapBuffers(); // for double buffer only. 
    }
}

/**
 * Check the status of the window if it is opened or not.
 */
bool GP2DWindow::isCreated() {
    return m_surfaceScreen != NULL ? true : false; 
}

/**
 * Does the actual work. Will throw an exception if GP2DEngine::initVideo() or
 * GP2DEngine::initAll() was not called first. 
 */
void GP2DWindow::createWindow(int width, int height, int bpp) throw(GP2DException) {
    const SDL_VideoInfo* m_videoInfo = SDL_GetVideoInfo();
    
    if(m_videoInfo == NULL) {
        throw GP2DException("Unable to create a window: video was not initialized.");
    }
    
    if(m_videoAPI == GP2D_SDL){
        m_videoFlags = SDL_HWPALETTE; // set default flags for SDL only
    } else {
        m_videoFlags = SDL_OPENGL | SDL_HWPALETTE; // set default flags for 
                                                   // OpenGL
    }
    
    // check to see if a surface can be stored in mem:
    if (m_videoInfo->hw_available) {
        m_videoFlags |= SDL_HWSURFACE;
    } else {
        m_videoFlags |= SDL_SWSURFACE;
    }

    // check to see if hardware blits can be done
    if (m_videoInfo->blit_hw) {
        m_videoFlags |= SDL_HWACCEL;
    }

    if(m_videoAPI == GP2D_SDL){
    } else {
        // Sets up OpenGL double buffering
        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, true);
    }

    // check whether the video mode is supported.
    int modeOK = SDL_VideoModeOK(width, height, bpp, m_videoFlags);
    
    if(modeOK != 0) {
        // this next function actually OPENS the window too!
        m_surfaceScreen = SDL_SetVideoMode(width, height, bpp, m_videoFlags);
        m_screenWidth = width;
        m_screenHeight = height;
        m_screenDepth = bpp;
    } else {
        // video mode here is not supported. Throw up an exception so we know
        // it is not supported.
        stringstream s;
        s << "Video mode " << width << "x" << height << "x" << bpp 
          << " is not supported. Bitmask video flags: " << m_videoFlags;
        throw GP2DException(s.str());
    }

}

void GP2DWindow::setRenderMode(const GP2DRenderMode mode) {
    m_videoAPI = mode;
}

GP2DWindow::GP2DRenderMode GP2DWindow::getRenderMode() const {
    return m_videoAPI;
}

//==============================================================================

/**
 * Create!
 */
GP2DCamera::GP2DCamera(int range) {
    initializeCamera(range);
}

/**
 * Destroy!
 */
GP2DCamera::~GP2DCamera() {   
}

/**
 * Initializes the camera.
 */
void GP2DCamera::initializeCamera(int range) throw(GP2DException) {
    GP2DWindow* window = GP2DWindow::getInstance();
    if(window->getRenderMode() == GP2DWindow::GP2D_SDL){

    } else {

        m_range = range;
    
    
        if(!window->isCreated()) {
            // well, the window cannot be allocated. Be sure to notify the 
            // programmer by throwing an exception.
            throw GP2DException("Window cannot be allocated.");
        }

        int height = window->getHeight();
        int width = window->getWidth();
        
        // no division by zeroes, plx!
        if (height == 0) {
            height = 1;
        }

        // the aspect ratio of the 'window'
        GLfloat aspectRatio = (GLfloat) width / (GLfloat)height;

        glViewport(0, 0, (GLsizei) width, (GLsizei) height);
        
        // make sure to change the projection matrix.
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
    
        if (width <= height) {
            glOrtho(-range, range, 
                    -range / aspectRatio, range / aspectRatio, 
                    -range, range);
        } else {
            glOrtho(-range * aspectRatio, range * aspectRatio, 
                    -range, range, 
                    -range, range);
        }
        
        // this translates the orthographic projection to the desired x and y.
        // don't know why exactly this works, but some website refer to it as 'working'. 
        glTranslatef((float) getX(), (float) getY(), 0.0f);
    
        // change the modelview matrix, and load it.
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

    }

}

/**
 * Updates the camera view.
 */
void GP2DCamera::updateCamera()  throw(GP2DException){
    try {
        initializeCamera(m_range);
    } catch(GP2DException) {
        throw; // re-throw the exception.
    }
}

/**
 * Set range.
 */
void GP2DCamera::setRange(int range) {
    m_range = range;
}

/**
 * Get range.
 */
int GP2DCamera::getRange() const {
    return m_range;
}

/**
 * Sets x, y positions.
 */
void GP2DCamera::setPosition(float x, float y) {
    m_posX = x;
    m_posY = y;
    updateCamera();
}

float GP2DCamera::getX() const {
    return m_posX;
}

float GP2DCamera::getY() const {
    return m_posY;
}

//==============================================================================

GP2DTexture::GP2DTexture(string file) throw(GP2DException) {
    GP2DWindow* window = GP2DWindow::getInstance();
    SDL_Surface* surf = IMG_Load(file.c_str());
    if(surf != NULL) {
        if(window->getRenderMode() == GP2DWindow::GP2D_SDL){
            m_surface = SDL_DisplayFormatAlpha(surf);

            m_width = m_surface->w;
            m_height = m_surface->h;
            m_pixels = m_surface->pixels;
        
            cout << "Texture loaded: " << file << ", " 
                 << m_width  << "x" << m_height << endl; 
        } else {
            m_surface = SDL_DisplayFormatAlpha(surf);
    
            glGenTextures(1, &m_texID);
            glBindTexture(GL_TEXTURE_2D, m_texID);
            glTexImage2D(GL_TEXTURE_2D, 0, 4, m_surface->w, m_surface->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, m_surface->pixels);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                
            m_width = m_surface->w;
            m_height = m_surface->h;
            m_pixels = m_surface->pixels;
        
            cout << "Texture loaded (OGL): " << file << ", " 
                 << m_width  << "x" << m_height << endl; 
        
            // free the OLD surface, but do not free the alpha surface m_surface.
            SDL_FreeSurface(surf);
        }
    } else {
        // Something bad happened. IMG_GetError probably returns some useful
        // information, so throw an exception indicating the problem. It might
         // for instance be a file which can not be found.
        throw GP2DException("Texture creation failed", IMG_GetError());
    }

}

/**
 * Deletes texture resources.
 */
GP2DTexture::~GP2DTexture() {
    GP2DWindow* window = GP2DWindow::getInstance();
    if(window->getRenderMode() == GP2DWindow::GP2D_SDL){
        SDL_FreeSurface(m_surface);
    } else {
        SDL_FreeSurface(m_surface);
        glDeleteTextures(1, &m_texID);
    }
}

unsigned int GP2DTexture::getId() const {
    return m_texID;
}

string GP2DTexture::getName() const {
    return m_texName;
}

float GP2DTexture::getWidth() const {
    return m_width;
}

float GP2DTexture::getHeight() const {
    return m_height;
}

void* GP2DTexture::getPixels() {
    return m_pixels;
}

SDL_Surface* GP2DTexture::getSurface() {
    return m_surface;
}

//==============================================================================

/**
 * GP2DObject constructor.
 */
GP2DObject::GP2DObject() {
    m_x = 0.0f; // initialize the coordinates and all that to 0.0f.
    m_y = 0.0f;
    m_z = 0.0f;

    init();
}

GP2DObject::GP2DObject(float x, float y) {
    m_x = x;
    m_y = y;
    m_z = 0.0f;
    
    init();
}

GP2DObject::GP2DObject(float x, float y, float z) {
    m_x = x;
    m_y = y;
    m_z = z;
    
    init();
}

/**
 * Destroy the object. Virtual destructor.
 */
GP2DObject::~GP2DObject() {
}

/**
 * Do some initializing here of local class members.
 */
void GP2DObject::init() {
    m_height = 0.0f;
    m_width = 0.0f;
    m_x_velocity = 0.0f;
    m_y_velocity = 0.0f;
    m_angle_X = 0.0f;
    m_angle_Y = 0.0f;
    m_angle_Z = 0.0f;
}

/*
 * Shitload of getters functions over here.
 */ 

float GP2DObject::getX() const {
    return m_x;
}
float GP2DObject::getY() const {
    return m_y;
}
float GP2DObject::getZ() const {
    return m_z;
}
float GP2DObject::getWidth() const {
    return m_width;
}
float GP2DObject::getHeight() const {
    return m_height;
}
float GP2DObject::getVelocity_X() const {
    return m_x_velocity;
}
float GP2DObject::getVelocity_Y() const {
    return m_y_velocity;
}
float GP2DObject::getRotation_X() const {
    return m_angle_X;
}
float GP2DObject::getRotation_Y() const {
    return m_angle_Y;
}
float GP2DObject::getRotation_Z() const {
    return m_angle_Z;
}

/*
 * Shitload of setter methods right here.
 */

void GP2DObject::setX(float x) {
    m_x = x;
}
void GP2DObject::setY(float y) {
    m_y = y;
}
void GP2DObject::setZ(float z) {
    m_z = z;
}
void GP2DObject::setWidth(float w) {
    m_width = w;
}
void GP2DObject::setHeight(float h) {
    m_height = h;
}
void GP2DObject::setVelocity_X(float xvel) {
    m_x_velocity = xvel;
}
void GP2DObject::setVelocity_Y(float yvel) {
    m_y_velocity = yvel;
}
void GP2DObject::setRotation_X(float angle) {
    m_angle_X = angle;
}
void GP2DObject::setRotation_Y(float angle) {
    m_angle_Y = angle;
}
void GP2DObject::setRotation_Z(float angle) {
    m_angle_Z = angle;
}

//==============================================================================

GP2DSprite::GP2DSprite(GP2DTexture* texture) {
    m_texture = texture;
    
    setWidth(m_texture->getWidth());
    setHeight(m_texture->getHeight());
}

GP2DSprite::~GP2DSprite() {
    
}

void GP2DSprite::draw() {

    GP2DWindow* window = GP2DWindow::getInstance();
    if(window->getRenderMode() == GP2DWindow::GP2D_SDL){

    } else {
        // blending function, used to make alpha parts transparent or some sort.
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glBindTexture(GL_TEXTURE_2D, m_texture->getId()); 
    
        // set the x and y positions based on the current velocity.
        setX(getX() + getVelocity_X());
        setY(getY() + getVelocity_Y());
    
        glMatrixMode(GL_MODELVIEW_MATRIX);
        glLoadIdentity();
        glTranslatef(getX(), getY(), getZ());

        glRotatef(getRotation_X(), 1.0f, 0.0f, 0.0f);
        glRotatef(getRotation_Y(), 0.0f, 1.0f, 0.0f);
        glRotatef(getRotation_Z(), 0.0f, 0.0f, 1.0f);

	float A=getWidth();
	float B=getHeight();
	float C=getZ();
            
        glBegin(GL_QUADS);
            glColor4f(1.0f, 1.0f, 1.0f, 1.0f);  // Set the sprite's alpha (for PNG)
            
            /* 
             * The following texture coordinate mappings look retarded. This is
             * because SDL flips the textures, vertically. 
             * 
             * Vertices:      Texture coordinates:
             *   1--4               2--3
             *   |  |               |  |
             *   2--3               1--4
             */             
            glTexCoord2f(0.0f, 0.0f);
            glVertex3f(0, 0, getZ());
            
            glTexCoord2f(0.0f, 1.0f);
            glVertex3f(0, 0 - getHeight(), getZ());
        
            glTexCoord2f(1.0f, 1.0f);
            glVertex3f(0 + getWidth(), 0 - getHeight(), getZ());
            
            glTexCoord2f(1.0f, 0.0f);
            glVertex3f(0 + getWidth(), 0, getZ());

    // Right face
    glTexCoord2f(1.0f, 0.0f); glVertex3f( A, -B, C-5.0);	// Bottom Right Of The Texture and Quad
    glTexCoord2f(1.0f, 1.0f); glVertex3f( A,  B, C-5.0);	// Top Right Of The Texture and Quad
    glTexCoord2f(0.0f, 1.0f); glVertex3f( A,  B,  C);	// Top Left Of The Texture and Quad
    glTexCoord2f(0.0f, 0.0f); glVertex3f( A, -B,  C);	// Bottom Left Of The Texture and Quad

        glEnd(); 


        glDisable(GL_BLEND);

//     glBegin(GL_QUADS);		                // begin drawing a cube
//     
//     // Front Face (note that the texture's corners have to match the quad's corners)
// //     glTexCoord2f(0.0f, 0.0f); glVertex3f(-A, -B,  C);	// Bottom Left Of The Texture and Quad
// //     glTexCoord2f(1.0f, 0.0f); glVertex3f( A, -B,  C);	// Bottom Right Of The Texture and Quad
// //     glTexCoord2f(1.0f, 1.0f); glVertex3f( A,  B,  C);	// Top Right Of The Texture and Quad
// //     glTexCoord2f(0.0f, 1.0f); glVertex3f(-A,  B,  C);	// Top Left Of The Texture and Quad
// 
//     glColor3ub(255, 0, 0);
//     glVertex3f(-A, -B,  C);	// Bottom Left Of The Texture and Quad
//     glVertex3f( A, -B,  C);	// Bottom Right Of The Texture and Quad
//     glVertex3f( A,  B,  C);	// Top Right Of The Texture and Quad
//     glVertex3f(-A,  B,  C);	// Top Left Of The Texture and Quad
// 
//     
// 
// /*    // Back Face
//     glTexCoord2f(1.0f, 0.0f); glVertex3f(-A, -B, -C);	// Bottom Right Of The Texture and Quad
//     glTexCoord2f(1.0f, 1.0f); glVertex3f(-A,  B, -C);	// Top Right Of The Texture and Quad
//     glTexCoord2f(0.0f, 1.0f); glVertex3f( A,  B, -C);	// Top Left Of The Texture and Quad
//     glTexCoord2f(0.0f, 0.0f); glVertex3f( A, -B, -C);	// Bottom Left Of The Texture and Quad
// 	
//     // Top Face
//     glTexCoord2f(0.0f, 1.0f); glVertex3f(-A,  B, -C);	// Top Left Of The Texture and Quad
//     glTexCoord2f(0.0f, 0.0f); glVertex3f(-A,  B,  C);	// Bottom Left Of The Texture and Quad
//     glTexCoord2f(1.0f, 0.0f); glVertex3f( A,  B,  C);	// Bottom Right Of The Texture and Quad
//     glTexCoord2f(1.0f, 1.0f); glVertex3f( A,  B, -C);	// Top Right Of The Texture and Quad
//     
//     // Bottom Face       
//     glTexCoord2f(1.0f, 1.0f); glVertex3f(-A, -B, -C);	// Top Right Of The Texture and Quad
//     glTexCoord2f(0.0f, 1.0f); glVertex3f( A, -B, -C);	// Top Left Of The Texture and Quad
//     glTexCoord2f(0.0f, 0.0f); glVertex3f( A, -B,  C);	// Bottom Left Of The Texture and Quad
//     glTexCoord2f(1.0f, 0.0f); glVertex3f(-A, -B,  C);	// Bottom Right Of The Texture and Quad
//     
//     
//     // Left Face
//     glTexCoord2f(0.0f, 0.0f); glVertex3f(-A, -B, -C);	// Bottom Left Of The Texture and Quad
//     glTexCoord2f(1.0f, 0.0f); glVertex3f(-A, -B,  C);	// Bottom Right Of The Texture and Quad
//     glTexCoord2f(1.0f, 1.0f); glVertex3f(-A,  B,  C);	// Top Right Of The Texture and Quad
//     glTexCoord2f(0.0f, 1.0f); glVertex3f(-A,  B, -C);	// Top Left Of The Texture and Quad*/
//     
//     glEnd();                                    // done with the polygon.

        
            
        // for debugging purposes, indicate a border of the sprite.
        glLineWidth(0.125f);
        glBegin(GL_LINES);
            // top left to right
            glColor3f(0.5f, 0.5f, 0.5f); glVertex3f(0.0f, 0.0f, -5.0f);
            glColor3f(0.5f, 0.5f, 0.5f); glVertex3f(getWidth(), 0.0f, -5.0f);
            // top left to bottom left
            glColor3f(0.5f, 0.5f, 0.5f); glVertex3f(0.0f, 0.0f, -5.0f);
            glColor3f(0.5f, 0.5f, 0.5f); glVertex3f(0.0f, -getHeight(), -5.0f);
            // bottom left to bottom right
            glColor3f(0.5f, 0.5f, 0.5f); glVertex3f(0.0f, -getHeight(), -5.0f);
            glColor3f(0.5f, 0.5f, 0.5f); glVertex3f(getWidth(), -getHeight(), -5.0f);
            // bottom right to top right
            glColor3f(0.5f, 0.5f, 0.5f); glVertex3f(getWidth(), -getHeight(), -5.0f);
            glColor3f(0.5f, 0.5f, 0.5f); glVertex3f(getWidth(), 0, -5.0f);
        glEnd();
    
        // and some points.
        glColor3f(1.0f, 1.0f, 1.0f);
        glPointSize(4.125f);
            glBegin(GL_POINTS);
            glVertex3f(0.0f, 0.0f, -4.0f);
            glVertex3f(getWidth(), 0.0f, -4.0f);
            glVertex3f(0.0f, -getHeight(), -4.0f);
            glVertex3f(getWidth(), -getHeight(), -4.0f);
        glEnd();

    }

}


} // namespace gp2d