miércoles, 1 de junio de 2011

GameEngine: Capitulo 3. Graphics 3D Manager

Hola a todos...

Bienvenidos a una nueva entrega de como crear un game engine ...

Estos dias hemos estado picando código vital para nuestro game engine ya que hemos asentado los cimientos de lo que será todo nuestro proyecto, pero sinceramente, lo que hemos hecho hasta ahora es poco espectacular o como mínimo poco gratificante.

Hoy implementaremos el inicio del manager de gráficos 3D (3D Engine también se le puede llamar). A grande rasgos no es más que una especialización del manager general de gráficos que ya tenemos, para el caso concreto de 3D. A fin de que al menos podamos ver algo, he usurpado un poco de código de nehe, concretamente de la lección 5 os recomiendo que le echeis un ojo, es muy interesante.

A nivel de código esta entrega es muy sencilla (si estás familiarizado con OpenGL, de no ser así, te recomiendo que busques por internet manuales o tutoriales, los hay a cientos y lo básico lo aprendes en un dia). Hemos incluido unos archivos nuevos que son el Graphics3DManager (.cpp y .h) y hemos modificado ligeramente el GraphicsManager.cpp para que llame a este nuevo módulo.

Espero que lo disfruteis:

GraphicsManager.c:
/**************************************************************************************************/
// Código creado por F.Bordas (LordPakus) como ejemplo de creación de un game engine
// para el blog LordPakus (http://lordpakus.blogspot.com/).
// Prohibida la distribución fuera de este blog sin el permiso expreso del autor
/**************************************************************************************************/

/**************************************************************************************************/
// GraphicsManager.cpp : Código del motor gráfico.
/**************************************************************************************************/

#include "GraphicsManager.h"
#include "MyGL.h"

#include "Graphics3DManager.h" //Parte de 3D del motor gráfico

#include <iostream> //Usada para imprimir por consola

using namespace std;

//Instancia única del graphics manager
GraphicsManager GraphicsManager::instance;

//Constructor
GraphicsManager::GraphicsManager()
{
}

//Destructor
GraphicsManager::~GraphicsManager()
{
}

//Devolvemos el puntero al singleton
GraphicsManager& GraphicsManager::singleton()
{
return instance;
}

//Funcion para inicializar el motor gráfico
void GraphicsManager::Init(int* argc, char* argv[])
{
cout << "Inicializamos el Graphics Manager\n";
//Creamos la ventana principal del programa utilizando la libreria GLUT
glutInit(argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(0, 0);
glutInitWindowSize(640, 480);
int mainWindow = glutCreateWindow("Lord Pakus Engine!!!"); //Viva la originalidad!!! :)
glutSetWindow(mainWindow);

//Asignamos todas las funciones gráficas de callback del glut
//a las funciones que definiremos posteriormente
glutDisplayFunc(Render);
// glutReshapeFunc(Reshape); //Por ahora la dejamos comentada por que no nos hace falta

Graphics3DManager::singleton().Init(argc,argv); //Inicializamos la parte de 3D
}

//Funcion para desinicializar el bucle principal
void GraphicsManager::DeInit()
{
Graphics3DManager::singleton().DeInit(); //Desinicializamos la parte de 3D

cout << "Desinicializamos el Graphics Manager\n";
}

//CALLBACKS DE GLUT, por ahora

//Funcion que se ejecuta automaticamente desde glut (por ahora)
void GraphicsManager::Render()
{
//Pintado de la parte de 3D
Graphics3DManager::singleton().Render();

//IMPORTANTE: Función encargada de realizar el double-buffering
glutSwapBuffers();
}

//Funcion que se ejecuta automaticamente desde glut (por ahora). Por el momento la dejamos comentada por que no nos hace falta
//void GraphicsManager::Reshape()
//{
// //AQUI IRÁ NUESTRA FUNCIÓN DE REESCALADO. Por ahora vacia
//}


Graphics3DManager.cpp:
/**************************************************************************************************/
// Código creado por F.Bordas (LordPakus) como ejemplo de creación de un game engine
// para el blog LordPakus (http://lordpakus.blogspot.com/).
// Prohibida la distribución fuera de este blog sin el permiso expreso del autor
/**************************************************************************************************/

/**************************************************************************************************/
// Graphics3DManager.cpp : Código de la parte del motor gráfico 3D
/**************************************************************************************************/

#include "Graphics3DManager.h"
#include "MyGL.h"

#include <iostream> //Usada para imprimir por consola

using namespace std;

//Instancia única del graphics 3D manager
Graphics3DManager Graphics3DManager::instance;

//Constructor
Graphics3DManager::Graphics3DManager()
{
}

//Destructor
Graphics3DManager::~Graphics3DManager()
{
}

//Devolvemos el puntero al singleton
Graphics3DManager& Graphics3DManager::singleton()
{
return instance;
}

//Funcion para inicializar el motor gráfico
void Graphics3DManager::Init(int* argc, char* argv[])
{
cout << "Inicializamos el Graphics 3D Manager\n";
//Inicializamos openGL
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations

glViewport(0,0,640,480); // Reset The Current Viewport
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)640/(GLfloat)480,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity();
}

//Funcion para desinicializar el bucle principal
void Graphics3DManager::DeInit()
{
cout << "Desinicializamos el Graphics 3D Manager\n";
}

//Funcion que se ejecuta automaticamente desde glut (por ahora)
void Graphics3DManager::Render()
{
//AQUI IRÁ NUESTRA FUNCIÓN DE PINTADO.
//Este es un ejemplo sacado de Nehe lección 5
//http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=05

static float rtri = 0.0f;
static float rquad = 0.0f;

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(-1.5f,0.0f,-6.0f); // Move Left And Into The Screen

glRotatef(rtri,0.0f,1.0f,0.0f); // Rotate The Pyramid On It's Y Axis

glBegin(GL_TRIANGLES); // Start Drawing The Pyramid
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Front)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Left Of Triangle (Front)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f( 1.0f,-1.0f, 1.0f); // Right Of Triangle (Front)

glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Right)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f( 1.0f,-1.0f, 1.0f); // Left Of Triangle (Right)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Right Of Triangle (Right)

glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Back)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Left Of Triangle (Back)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f, -1.0f); // Right Of Triangle (Back)

glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Left)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f,-1.0f); // Left Of Triangle (Left)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Right Of Triangle (Left)
glEnd(); // Done Drawing The Pyramid

glLoadIdentity();
glTranslatef(1.5f,0.0f,-7.0f); // Move Right And Into The Screen

glRotatef(rquad,1.0f,1.0f,1.0f); // Rotate The Cube On X, Y & Z

glBegin(GL_QUADS); // Start Drawing The Cube
glColor3f(0.0f,1.0f,0.0f); // Set The Color To Green
glVertex3f( 1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Top)
glVertex3f(-1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Top)
glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Quad (Top)
glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Quad (Top)
glColor3f(1.0f,0.5f,0.0f); // Set The Color To Orange
glVertex3f( 1.0f,-1.0f, 1.0f); // Top Right Of The Quad (Bottom)
glVertex3f(-1.0f,-1.0f, 1.0f); // Top Left Of The Quad (Bottom)
glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Bottom)
glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Bottom)
glColor3f(1.0f,0.0f,0.0f); // Set The Color To Red
glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Front)
glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Front)
glVertex3f(-1.0f,-1.0f, 1.0f); // Bottom Left Of The Quad (Front)
glVertex3f( 1.0f,-1.0f, 1.0f); // Bottom Right Of The Quad (Front)

glColor3f(1.0f,1.0f,0.0f); // Set The Color To Yellow
glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Back)
glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Back)
glVertex3f(-1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Back)
glVertex3f( 1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Back)

glColor3f(0.0f,0.0f,1.0f); // Set The Color To Blue
glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Left)
glVertex3f(-1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Left)
glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Left)
glVertex3f(-1.0f,-1.0f, 1.0f); // Bottom Right Of The Quad (Left)

glColor3f(1.0f,0.0f,1.0f); // Set The Color To Violet
glVertex3f( 1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Right)
glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Right)
glVertex3f( 1.0f,-1.0f, 1.0f); // Bottom Left Of The Quad (Right)
glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Right)
glEnd(); // Done Drawing The Quad

rtri+=0.2f; // Increase The Rotation Variable For The Triangle
rquad-=0.15f; // Decrease The Rotation Variable For The Quad
}

//Por el momento la dejamos comentada por que no nos hace falta
//void Graphics3DManager::Reshape()
//{
// //AQUI IRÁ NUESTRA FUNCIÓN DE REESCALADO. Por ahora vacia
//}


Graphics3DManager.h
/**************************************************************************************************/
// Código creado por F.Bordas (LordPakus) como ejemplo de creación de un game engine
// para el blog LordPakus (http://lordpakus.blogspot.com/).
// Prohibida la distribución fuera de este blog sin el permiso expreso del autor
/**************************************************************************************************/

/**************************************************************************************************/
// Graphics3DManager.h : Código de la parte de 3D del motor gráfico.
// Caracteristicas especiales: Esta clase implementa un singleton, es decir, solo podrá existir un objeto de esta clase en todo el proyecto
/**************************************************************************************************/

#ifndef __Graphics3DManager__
#define __Graphics3DManager__

class Graphics3DManager
{
private:
// Constructor y destructor de la clase
static Graphics3DManager instance;
Graphics3DManager();
~Graphics3DManager();

public:
static Graphics3DManager& singleton();

public:
//Funcion para inicializar el motor de gráficos
void Init(int* argc, char* argv[]);

//Funcion para desinicializar el motor de gráficos
void DeInit();
//Funcion para pintar nuestros gráficos
void Render();
//Función para reescalar los gráficos
void Reshape();

private:
//Aqui irán los diferentes objetos que complementen el graphics3Dmanager
};

#endif

Resultados:
Si todo lo habeís hecho bien (que no veo por que no :) , si teneis problemas recordad que tenemos el “repositorio” para bajaros el proyecto funcional) al ejecutar tendriais que ver alguna cosa de este estilo:

Y con esto es todo, recordad, si teneis cualquier problema, preguntad.

LordPakusBlog
 Nos vemos, hasta el siguiente capítulo

2 comentarios :

  1. Me da la siguiente excepción exception throw 0x10009505 glut32.dll , el código que tengo es el mismo que el tuyo por que como dio esta excepción he hecho un copy paste de todo por si acaso.

    ResponderEliminar
    Respuestas
    1. Desconozco el motivo.... has hecho otras prácticas con glut y te han funcionado?
      Igual tienes algún problema con la instalación de glut o los drivers de la tarjeta gráfica antes que con el código.

      Ya me diras

      Eliminar

Entradas populares