| PRINCIPAL | GRAFICOS 3D | GRAFICOS 2D | MATEMATICAS | TUTORIALES | FRACTALES | FUENTES | LINKS |

Mapeado de Texturas en OpenGL

Ya basta de aplicar texturas planas a los típicos cubitos 3D, en este ejemplo voy a hacer lo mismo :-) pero a un objeto mas complicado, en este caso una malla 3D que la tengo definida en un archivo de texto head.dat, que tiene todos sus datos, vértices, caras, coordenadas de textura definidas en ese archivo.
La imagen que utilizo como textura esta en formato BMP de 512x512 pixels, al aplicarse la textura esta es filtrada para que se produzca un ajuste exacto entre los pixels de la textura y los pixels de la pantalla también tengo una fuente de luz, y utilizo smoothing (suavizado de caras) para que se vea mejor. Gran parte del código es similar al de mis ejemplos anteriores.
La imagen de abajo es una captura del programa, si observan hacia los costados hay un estiramiento de la textura, por eso mismo puse la grilla para tener esa referencia, eso se debe a que el mapeo de textura es del tipo plano, la idea es que la textura envuelva al modelo, eso se logra aplicando un mapeo UV, cosa que voy a hacer en el próximo ejemplo de texturas.

face_tex.jpg


Formato del archivo head.dat

El formato es el siguiente, primero indico el numero total de vértice de la malla, después en cada linea las coordenadas de los vértice y textura.
Al finalizar de listar todos los vértice, indico el numero de caras que tiene , la siguientes lineas me indica que vértice forman esa cara, un flag que me identifica el material y finalmente el grupo de suavizado.

El archivo con los datos de la malla están aquí.

Vertices: 1469
-1.688360 -4.163916 2.318413 0.413706 0..288504
-1.713966 -4.156930 2.296686 0.412293 0..288905
-1.675014 -4.160190 2.301188 0.414442 0..288718
......
......
......
1.456195 0.323630 1.695802 0.587216 0.546147
1.869924 0.433806 1.828177 0.610045 0.552473
2.244856 0.414572 1.811106 0.630733 0.551368
Faces: 2849
0 1 2
MaterialID: 0
Smoothing: 1
3 4 5
MaterialID: 0
Smoothing: 1
......
......
......
1135 1332 743
MaterialID: 0
Smoothing: 1

La Textura

La imagen de abajo es la que utilizo como textura, aquí la tengo en 360x360 pixels y en formato JPG, para poder usarla desde el programa la tienes que redimensionar a 512x512 pixel y grabarla como BMP, con cualquier programa de adición de imágenes, ejemplo Photoshop.

textura.jpg


EL Código Fuente

El programa tiene los siguientes archivos.

El código fuente, con el proyecto para VisualC++ 6.0 lo podes bajar de aquí.

main.cpp

#include <GL/glaux.h>
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "textures.h"

struct Point3f
	{
	float x, y, z;
	float u, v;
	};

struct Face
	{
	int material;				
	int vertexIndices[3];
	int smoothingGroup;
	Point3f normal[3];
	Point3f faceNormal;
	};

struct Object3D
	{
	int nVertices;
	Point3f *pVertices;			
	int nFaces;
	Face *pFaces;						
	};

//parametros y ubicacion de la fuente de luz
float LightPos[] = { 0.25f, 0.2f, 1.0f, 0.0f};  
float LightAmb[] = { 0.1f, 0.1f, 0.1f, 1.0f}; 
float LightDif[] = { 1.0f, 1.0f, 1.0f, 1.0f};   
float LightSpc[] = { 1.0f, 1.0f, 1.0f, 1.0f};  

Object3D	obj;
COGLTexture MyTextura;
GLfloat	angulo=0.0f;

void CargarModelo(char *filename, Object3D &object)
{
 .........
 .........
}

void CalcularNormales(Object3D &object)
{
 .........
 .........
}

void applySmoothingGroups(Object3D &object)
{
.........
.........
}

void killObject(Object3D &object)
{
 delete[] object.pFaces;
 object.pFaces = NULL;
 object.nFaces = 0;
 delete[] object.pVertices;
 object.pVertices = NULL;
 object.nVertices = 0;
}

void InitTextures(void)
{
 MyTextura.LoadFromFile("textura.bmp");
 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}

void reshape(int w, int h)
{
 if (!h)
	return;
 glViewport(0, 0,  (GLsizei) w, (GLsizei) h);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluPerspective(45.0, (GLfloat) w/(GLfloat) h, 1.0, 100.0);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
}

void display(void)
{
 int a, b, c;
 int i;

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glLoadIdentity();	
 glEnable(GL_TEXTURE_2D);
 MyTextura.SetActive();
 gluLookAt (0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
 glRotatef(angulo,0.0f,1.0f,0.0f);
 glBegin(GL_TRIANGLES);
 for (i=0; i<obj.nFaces; i++)
	{
	const Face& face = obj.pFaces[i];
	a=face.vertexIndices[0];
	b=face.vertexIndices[1];
	c=face.vertexIndices[2];
	glNormal3f(face.normal[0].x, face.normal[0].y, face.normal[0].z); 
	glTexCoord2f(obj.pVertices[a].u, obj.pVertices[a].v);
	glVertex3f(obj.pVertices[a].x, obj.pVertices[a].y, obj.pVertices[a].z);
	glNormal3f(face.normal[1].x, face.normal[1].y, face.normal[1].z); 
	glTexCoord2f(obj.pVertices[b].u, obj.pVertices[b].v);
	glVertex3f(obj.pVertices[b].x, obj.pVertices[b].y, obj.pVertices[b].z);
	glNormal3f(face.normal[2].x, face.normal[2].y, face.normal[2].z); 
	glTexCoord2f(obj.pVertices[c].u, obj.pVertices[c].v);
	glVertex3f(obj.pVertices[c].x, obj.pVertices[c].y, obj.pVertices[c].z);
	}
 glEnd();
 glutSwapBuffers();
}

void init(void)
{
 glClearColor(0.0, 0.0, 0.0, 0.0);
 glCullFace(GL_BACK);
 glEnable(GL_DEPTH_TEST);
 glEnable(GL_CULL_FACE);
 glLightfv(GL_LIGHT0, GL_POSITION, LightPos);     
 glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmb);         
 glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDif);        
 glLightfv(GL_LIGHT0, GL_SPECULAR, LightSpc);       
 glEnable(GL_LIGHT0);                               
 glEnable(GL_LIGHTING);
 CargarModelo("head.dat", obj);
 CalcularNormales(obj);
 applySmoothingGroups(obj);
 InitTextures();
}

void keyboard(unsigned char key, int x, int y)
{
 switch (key)
   {
   case 27: exit(0);
             break;
   }
}

void Idle(void)
{
 angulo += 1.0;
 display();
}

int main(int argc, char **argv)
{
 glutInit(&argc, argv);
 glutInitWindowSize(400, 400);
 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
 glutCreateWindow("Texturas en OpenGL");
 init();
 glutDisplayFunc(display);
 glutReshapeFunc(reshape);
 glutKeyboardFunc(keyboard);
 glutIdleFunc(Idle);
 glutMainLoop();
 killObject(obj);
 return 0;
}


   
 

textures.h

#include <GL\glaux.h>

class COGLTexture
{
public:
	_AUX_RGBImageRec *Image;
	unsigned int GetID();
	void LoadFromFile(char *filename);
	void SetActive();
	int GetWidth();
	int GetHeight();
private:
	int Width, Height;
	unsigned int ID;
};

textures.cpp

#include "textures.h"

void COGLTexture::LoadFromFile(char *filename)
{
 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 glGenTextures(1,&ID); 
 glBindTexture( GL_TEXTURE_2D, ID);
 Image = auxDIBImageLoadA( (const char*) filename );
 Width = Image->sizeX;
 Height = Image->sizeY;
 gluBuild2DMipmaps(	GL_TEXTURE_2D, 
					3, 
					Image->sizeX,
					Image->sizeY,
					GL_RGB,
					GL_UNSIGNED_BYTE,
					Image->data);
 delete Image;
}

void COGLTexture::SetActive()
{
 glBindTexture( GL_TEXTURE_2D, ID);
}

unsigned int COGLTexture::GetID()
{
 return ID;
}

| PRINCIPAL | GRAFICOS 3D | GRAFICOS 2D | MATEMATICAS | TUTORIALES | FRACTALES | FUENTES | LINKS |

Copyright© 2002, Ramiro, Argentina
valcoey@hotmail.com