Hola gente, estoy haciendo un juego tipo pc futbol y la parte programación esta bastante aceptable ya, pero me quise adentrar a la programación Básica y resulta que no puedo poner por ejemplo en un rectángulo una imagen de una cancha de futbol que quiero poner, alguien me puede dar una mano?
Muchas gracias.
La pagina de Nehe tiene buenas guías mírate estos:
http://nehe.gamedev.net/tutorial/lessons_06__10/17010/
1ro debes cargar la imagen:
glGenTextures(1 , &this->uiID); // Generamos la ID de la textura
glBindTexture(GL_TEXTURE_2D , this->uiID-1);
glTexParameteri(GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR);
// Una vez creado el ID para la tectura debes cargarla y asignarla a este ID...
::glBindTexture( GL_TEXTURE_2D, this->uiID);
::glTexImage2D(GL_TEXTURE_2D,
0,
3,
oBMPReader.getInfo().bmiHeader.biWidth,
oBMPReader.getInfo().bmiHeader.biHeight,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
(GLvoid*)oBMPReader.getBytes().lpData);
Para implementarla debes usar
if(this->uiID > 0 && this->enabled)
::glBindTexture(GL_TEXTURE_2D , this->uiID - 1);
else
::glBindTexture(GL_TEXTURE_2D , 0);
Para poderla dibujar debes definir antes los vértices que definen la textura a implementar y (estos vertices pueden inclusive estirar la textura) de la textura:
glTexCoord3f();
Antes de llamar a
glVertex3f();
Te dejo mis clases con las que realizo estas acciones:
CTexture.h
#ifndef CTexture_H
#define CTexture_H
#include "native.h"
#include "_Formatos/mBitmap/CBMPReader.h"
#include <windows.h>
#include <GL/glut.h>
class CGL_Texture;
typedef CGL_Texture CGL_TEXTURE, *LPCGL_TEXTURE;
class CGL_Texture: public Object
{
private:
unsigned int uiID;
void create();
bool bLoadBMP;
public:
CGL_Texture();
~CGL_Texture();
bool itsLoad();
bool enabled;
void remove();
void use();
bool loadBMP(const char* szFile);
};
#endif // CTexture_H
CTexture.cpp
#include "OpenGL/ctexture.h"
//---------------------------------------------------------------
// Nombre: Constructor
// Descripcion: Constructor de la clase. Inicializa las variables
// Parametros: Ninguno
//---------------------------------------------------------------
CGL_Texture::CGL_Texture():
Object()
{
this->uiID = 0;
this->enabled = false;
this->bLoadBMP = false;
}
//---------------------------------------------------------------
// Nombre: Destructor
// Descripcion: Destructor de la clase. Elimina la textura
// Parametros: Ninguno
//---------------------------------------------------------------
CGL_Texture::~CGL_Texture()
{
this->remove();
}
//---------------------------------------------------------------
// Nombre: Crear
// Descripcion: Establece los parámetros GL para cargar
// Parametros:
// char* szNombreFichero: Nombre del fichero a cargar
//---------------------------------------------------------------
void CGL_Texture::create()
{
this->remove();
::glGenTextures(1 , &this->uiID); // Generamos la ID de la textura
this->uiID++; // Usamos un offset de +1 para diferenciar del estado no-inicializado
::glBindTexture(GL_TEXTURE_2D , this->uiID-1);
::glTexParameteri(GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR);
}
//---------------------------------------------------------------
// Nombre: Elimina
// Descripcion: Elimina la textura
// Parametros: Ninguno
//---------------------------------------------------------------
void CGL_Texture::remove()
{
if( this->uiID > 0)
::glDeleteTextures(1 , &(--this->uiID));
this->uiID = 0;
this->bLoadBMP = false;
}
//---------------------------------------------------------------
// Nombre: Usa
// Descripcion: Usa la textura actual
// Parametros: Ninguno
//---------------------------------------------------------------
void CGL_Texture::use()
{
if(this->uiID > 0 && this->enabled)
::glBindTexture(GL_TEXTURE_2D , this->uiID - 1);
else
::glBindTexture(GL_TEXTURE_2D , 0);
}
//---------------------------------------------------------------
// Nombre: CargarBMP
// Descripcion: Carga un fichero BMP y almacena los datos
// Parametros: Ninguno
//---------------------------------------------------------------
bool CGL_Texture::loadBMP(const char *szFile)
{
CBMPReader oBMPReader;
this->remove();
if(oBMPReader.loadBMP(szFile) != NULL)
{
this->create();
::glBindTexture( GL_TEXTURE_2D, this->uiID);
::glTexImage2D(GL_TEXTURE_2D,
0,
3,
oBMPReader.getInfo().bmiHeader.biWidth,
oBMPReader.getInfo().bmiHeader.biHeight,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
(GLvoid*)oBMPReader.getBytes().lpData);
return this->bLoadBMP = true;
}
return this->bLoadBMP = false;
}
//---------------------------------------------------------------
// Nombre: itsLoad
// Descripcion: Esta cargada la textura en memoria?.
// Parametros: Ninguno
//---------------------------------------------------------------
bool
CGL_Texture::itsLoad()
{
return this->bLoadBMP;
}
CDrawn.h
#ifndef CGL_DRAWN_H
#define CGL_DRAWN_H
#include <windows.h>
#include <stack>
#include "native.h"
#include "OpenGL/cglobject.h"
using namespace std;
class CGL_Drawn;
typedef CGL_Drawn CGL_DRAWN, *LPCGL_DRAWN;
class CGL_Drawn: public Object, public stack<LPCGL_OBJECT>
{
public:
CGL_Drawn();
CGL_Drawn(int idWin);
virtual ~CGL_Drawn();
int draw();
int draw(int idWin);
protected:
int idWin;
private:
};
#endif // CGL_DRAWN_H
CDrawn.cpp
#include "OpenGL/cdrawn.h"
#include <iostream>
#include <algorithm>
using namespace std;
CGL_Drawn::CGL_Drawn(int idWin):
Object()
{
this->idWin = idWin;
//ctor
}
CGL_Drawn::CGL_Drawn():
Object(), idWin(0)
{
//ctor
}
CGL_Drawn::~CGL_Drawn()
{
//dtor
}
int CGL_Drawn::draw()
{
return this->draw(idWin);
}
int CGL_Drawn::draw(int idWin)
{
LPCGL_OBJECT lpCGL_Object = NULL;
LPCASE_MATERIAL lpMaterial = NULL;
LPCASE_MESH lpCASE_Mesh = NULL;
TAnimObject* lpAniObj = NULL;
int iRet = 0,
n = 0,
tv = 0,
v = 0;
int i = 0,
j = 0;
float fMax = 0.0f;
::glutPushWindow();
::glutSetWindow(idWin);
while(!this->empty())
{
::glPushMatrix();
lpCGL_Object = this->top();
lpCASE_Mesh = lpCGL_Object->lpCASE_Object->lpMesh;
::glTranslatef(lpCGL_Object->x, lpCGL_Object->y, lpCGL_Object->z);
/// Animación...
lpAniObj = &lpCGL_Object->lpCASE_Object->udtAnimate.udtAnimObject;
if (lpAniObj->iPosCount)
{
if (lpAniObj->iStepPos >= lpAniObj->iPosCount)
lpAniObj->iStepPos = 0;
::glTranslatef(lpAniObj->lpPosTrack[i]->fPosition[0],
lpAniObj->lpPosTrack[i]->fPosition[1],
lpAniObj->lpPosTrack[i]->fPosition[2]);
lpAniObj->iStepPos++;
}
else
{
::glTranslatef(lpCGL_Object->lpCASE_Object->lpNodeTM->fTMPos[0],
lpCGL_Object->lpCASE_Object->lpNodeTM->fTMPos[1],
lpCGL_Object->lpCASE_Object->lpNodeTM->fTMPos[2]);
}
if (lpAniObj->iRotCount)
{
if (lpAniObj->iStepRot >= lpAniObj->iRotCount)
lpAniObj->iStepRot = 0;
::glRotatef(lpAniObj->lpRotTrack[lpAniObj->iStepRot]->fAngle,
lpAniObj->lpRotTrack[lpAniObj->iStepRot]->fAxis[0],
lpAniObj->lpRotTrack[lpAniObj->iStepRot]->fAxis[1],
lpAniObj->lpRotTrack[lpAniObj->iStepRot]->fAxis[2]);
lpAniObj->iStepPos++;
}
else
{
::glRotatef(lpCGL_Object->lpCASE_Object->lpNodeTM->fTMRotAngle,
lpCGL_Object->lpCASE_Object->lpNodeTM->fTMRotAxis[0],
lpCGL_Object->lpCASE_Object->lpNodeTM->fTMRotAxis[1],
lpCGL_Object->lpCASE_Object->lpNodeTM->fTMRotAxis[2]);
}
/// End
//cout << lpCGL_Object->lpCASE_Object->sNodeName << "\t" << lpCGL_Object->lpCASE_Object->iMaterialRef <<endl;
if (lpCGL_Object->lpCASE_Object->iMaterialRef != -1)
lpMaterial = lpCGL_Object->lpCASE_Object->lpModels->listMaterials[lpCGL_Object->lpCASE_Object->iMaterialRef];
if (lpMaterial)
{
::glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, lpMaterial->fMaterialAmbient);
::glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, lpMaterial->fMaterialDiffuse);
::glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, lpMaterial->fMaterialSpecular);
::glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, lpMaterial->fMaterialShine);
}
if (lpMaterial)
::glColor3fv(lpMaterial->fMaterialDiffuse);
// Aplicar color o Textura al objeto.
::glColor3fv(lpCGL_Object->lpCASE_Object->fWireFameColor);
// Malla de Poligonos.
for(v = 0 ; v < lpCASE_Mesh->listFace.size(); ++v)
{
::glBegin(GL_TRIANGLES);
for(n = 0 ; n < 3 ; ++n) // Vertices(Triangulos).
{
if(lpCGL_Object->oTexture.itsLoad())// && lpCGL_Object->oTexture.enabled) // Textura.
{
switch(n)
{
case 0: tv = lpCASE_Mesh->listTFace[v]->ia; break;
case 1: tv = lpCASE_Mesh->listTFace[v]->ib; break;
case 2: tv = lpCASE_Mesh->listTFace[v]->ic; break;
}
lpCGL_Object->oTexture.use();
::glTexCoord3f(lpCASE_Mesh->listTVertex[tv]->fx,
lpCASE_Mesh->listTVertex[tv]->fy,
lpCASE_Mesh->listTVertex[tv]->fz);
} // Textura
//cout << lpCASE_Mesh->listFace.size() << "\t" << n << "\t" << v << "\t" << endl;
switch(n)
{
case 0: tv = lpCASE_Mesh->listFace[v]->ia; break;
case 1: tv = lpCASE_Mesh->listFace[v]->ib; break;
case 2: tv = lpCASE_Mesh->listFace[v]->ic; break;
}
::glVertex3f(lpCASE_Mesh->listVertex[tv]->fx,
lpCASE_Mesh->listVertex[tv]->fy,
lpCASE_Mesh->listVertex[tv]->fz);
}
} // v < lpCASE_Mesh->ListFace.size();
::glEnd();
iRet++;
this->pop();
::glPopMatrix();
}
// cout << fMax << endl;
::glutPopWindow();
return iRet;
}
P.D.: No son todos los archivos de mi proyecto... solo te los dejo para/como Guía.
Dulces Lunas!¡.
Muchísimas gracias Man! ya las voy a leer tranquilo y voy a intentar, si tengo alguna duda te consulto. Muchísimas gracias por respodener tan rápido un abrazo.
Buenas acabo de ver el post que me pasaste y sigo con una duda muy grande. Cuando le paso el archivo? por que es como si esa parte todo el mundo se la salteara y la verdad que se me complica mucho. Muchos tutoriales me dicen que cargue la imagen en memoria y ninguna de las que hago me funciona. Un abrazo.
Saludos
Aver mirando un tutorial trate de hacer esto pero sigue sin aparecer mi textura, me esta volviendo loco...
#include <stdio.h>
#include <windows.h>
#include "GL/glut.h"
typedef struct // Utilizamos esta estructura
{
GLubyte *imageData;
GLuint bpp;
GLuint width;
GLuint height;
GLuint texID;
} Imagen;
int textura;
void *CargaTGA(char *cancha,int *tam)
{
GLubyte TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0};
GLubyte TGAcompare[12];
GLubyte header[6];
GLuint bytesPerPixel;
GLuint imageSize;
GLuint temp,i;
GLuint type=GL_RGBA;
Imagen texture;
GLubyte *aux;
FILE *file = fopen(cancha, "rb");
if (file == NULL)
return NULL;
/* Esto abre y comprueba que es un TGA */
fread(TGAcompare,1,sizeof(TGAcompare),file);
if (memcmp(TGAheader,TGAcompare,sizeof(TGAheader))!=0)
return NULL;
/* Leemos la cabecera*/
fread(header,1,sizeof(header),file);
/* Determinamos el tamaño */
texture.width = header[1] * 256 + header[0];
texture.height = header[3] * 256 + header[2];
/* Vemos las características y comprobamos si son correctas*/
if( texture.width <=0 ||texture.height <=0 ||texture.width >256 ||texture.height !=texture.width ||( header[4]!=32))
{
fclose(file);
return NULL;
}
/* Calculamos la memoria que será necesaria */
texture.bpp = header[4];
bytesPerPixel = texture.bpp/8;
imageSize = texture.width*texture.height*bytesPerPixel;
/* Reservamos memoria */
texture.imageData=(GLubyte *)malloc(imageSize);
/* Cargamos y hacemos alguna comprobaciones */
if( texture.imageData==NULL ||
fread(texture.imageData, 1, imageSize, file)!=imageSize)
{
if(texture.imageData!=NULL)
free(texture.imageData);
fclose(file);
return NULL;
}
/* El TGA viene en formato BGR, lo pasamos a RGB */
for(i=0; i<(GLuint)(imageSize); i+=bytesPerPixel)
{
temp=texture.imageData;
texture.imageData = texture.imageData[i + 2];
texture.imageData[i + 2] = temp;
}
fclose (file);
/* Ahora, cambiamos el orden de las líneas, como si hiciesemosun flip vertical. */
aux=(GLubyte *)malloc(imageSize);
for(i=0; i<texture.height; i++)
memcpy(&aux[imageSize-((i+1)*texture.width*4)],&texture.imageData[i*texture.width*4],texture.width*4);
/* tam devolverá el tamaño */
*tam=texture.width;
/* Liberamos memoria */
free(texture.imageData);
/* Todo fue bien!*/
return aux;
}
int carga_texturas(void) {
Imagen texture;
int tam;
texture.imageData=(char *)CargaTGA("cancha.tga",&tam);if (texture.imageData == NULL) {
return -1;
}
/* Genera una textura, referenciada por el entero textura */
glGenTextures (1, &textura);
/* Esta función indica que será una textura en 2D. Las siguientes funciones hará referncia a esta textura */
glBindTexture (GL_TEXTURE_2D, textura);
/* Aquí ajustamos algunos parámetros de la textura, concretamente los filtros */
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
/* Con esta función de GLU, creamos un mipmap. Nótese que especificamos el tamaño con tam, que devolvia la función CargaTGA*/
gluBuild2DMipmaps (GL_TEXTURE_2D, 4, tam, tam, GL_RGBA,GL_UNSIGNED_BYTE, texture.imageData);
/* Liberamos la memoria que ya no utilizaremos */
free(texture.imageData);
return 0;
}
void display()
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
glColor4f(0.0, 0.5, 0.2,0.0);
glBindTexture(GL_TEXTURE_2D, textura);
glBegin(GL_POLYGON);
glTexCoord2f(0.0, 0.0);
glVertex2f(-0.5, 0.9);
glTexCoord2f(1.0, 0.0);
glVertex2f(0.5, 0.9);
glTexCoord2f(1.0, 1.0);
glVertex2f(0.5, -0.9);
glTexCoord2f(0.0, 1.0);
glVertex2f(-0.5,-0.9);
glEnd();
glColor3f(1.0, 1.0, 1.0);
glTranslatef(0.1,0.1,0);
glPushMatrix();
glTranslatef(0.1,0.1,0.1);
glutSolidSphere(0.02,300,300);
glPopMatrix();
glutSolidSphere(0.02,300,300);
glFlush();
}
void init()
{
glClearColor(0.000, 0.110, 0.392, 0.0); // JMU Gold
glColor3f(0.314, 0.314, 0.000); // JMU Purple
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(640, 480);
glutInitWindowPosition(0, 0);
glutCreateWindow("Test");
glutDisplayFunc(display);
init();
glutMainLoop();
}
Aver si me pueden ayudar. Saludos.