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