Im implementing a Maze in 3d. It works fine, but now i have to put textures in it.
void Maze::draw3D(int w, int h){
if (rows == 0 || columns == 0)
throw std::out_of_range("Error: El numero columnas o filas no puede ser cero. Error división por cero");
if (rows > h || columns > w)
throw std::out_of_range("Error: La ventana tiene que tener un tamaño mayor a las fila por columnas");
int numberRow, numberColumn;
int widthRatio =int(w / columns);
int heightRatio = int(h / rows);
//int numberRow;
GLUquadric *sphere=gluNewQuadric();
for(numberRow=0;numberRow < rows; numberRow++)
for(numberColumn=0; numberColumn< columns;numberColumn++)
if(!isCenter(numberRow,numberColumn)){
if( map[numberRow][numberColumn]==WALL ) {
//Selecciona el color actual con el que dibujar. Parámetros R G y B, rango [0..1], así que estamos ante el color azul
//glColor3f(0.0, 0.0, 1.0);
/*glBegin() comienza una secuencia de vértices con los que se construirán primitivas. El tipo de primitivas viene dado por el parámetro de glBegin(), en este caso GL_QUADS.
* Al haber cuatro vértices dentro de la estructura, está definiendo un cuadrado. glEnd() simplemente cierra la estructura.
*
*/
//las x son iguales cambian las y
//ysim =(rows-numberRow);
//numberRow=numberRow;
//Pared suelo
glColor3f(1.0, 0.0, 0.0); // Red = rgb <1, 0, 0>
glBegin(GL_QUADS);
//Vertice arriba izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),0,(numberRow*heightRatio)-(HEIGHT/2));
//Vertice abajo izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),0,(numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice abajo derecha
glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),0,(numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice arriba derecha
glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),0,(numberRow)*heightRatio-(HEIGHT/2));
glEnd();
/*
//Pared techo
glColor3f(1.0, 0.0, 0.0); // Red = rgb <1, 0, 0>
glBegin(GL_QUADS);
//Vertice arriba izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),DEPTH,(numberRow*heightRatio)-(HEIGHT/2));
//Vertice abajo izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),DEPTH,(numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice abajo derecha
glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),DEPTH,(numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice arriba derecha
glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),DEPTH,(numberRow)*heightRatio-(HEIGHT/2));
//glVertex3i(50,-50,50);
glEnd();
*/
//Pared exterior (las x mas izquierda) (1)
glColor3f(0.0, 1.0, 0.0); //Green = rgb <0, 1, 0>
glBegin(GL_QUADS);
//Vertice arriba izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),0,(numberRow*heightRatio)-(HEIGHT/2));
//Vertice abajo izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),0,(numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice abajo derecha
glVertex3i( ((numberColumn)*widthRatio)-(WIDTH/2),DEPTH,(numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice arriba derecha
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),DEPTH,(numberRow*heightRatio)-(HEIGHT/2));
glEnd();
//Pared exterior ( las y mas abajo) (2)
glColor3f(0.0, 0.0, 1.0);//Blue = rgb <0, 0, 1>
glBegin(GL_QUADS);
//Vertice arriba izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),DEPTH,(numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice abajo izquierda
glVertex3i(((numberColumn)*widthRatio)-(WIDTH/2),0, (numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice abajo derecha
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),0, (numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice arriba derecha
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),DEPTH, (numberRow+1)*heightRatio-(HEIGHT/2));
glEnd();
//Pared exterior ( las x mas abajo) (3)106;90;205
glColor3f(1.0, 0.5, 0.0); //Orange = color red 1 green 0.5 blue 0.0
glBegin(GL_QUADS);
//Vertice arriba izquierda
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),DEPTH, (numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice abajo izquierda
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),0, (numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice abajo derecha
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),0, (numberRow)*heightRatio-(HEIGHT/2));
//Vertice arriba derecha
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),DEPTH, (numberRow)*heightRatio-(HEIGHT/2));
glEnd();
//Pared exterior ( las y mas arriba) (4)
glColor3f(0.752, 0.752, 0.752); //Grey = color red 0.752941 green 0.752941 blue 0.752941
glBegin(GL_QUADS);
//Vertice arriba izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),0, (numberRow)*heightRatio-(HEIGHT/2));
//Vertice abajo izquierda
glVertex3i(((numberColumn)*widthRatio)-(WIDTH/2),DEPTH, (numberRow)*heightRatio-(HEIGHT/2));
//Vertice abajo derecha
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),DEPTH, (numberRow)*heightRatio-(HEIGHT/2));
//Vertice arriba derecha
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),0, (numberRow)*heightRatio-(HEIGHT/2));
glEnd();
//Textura pared techo
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
LoadTexture("Groundplant64x64.jpg",64);
glBegin(GL_QUADS);
glTexCoord2f(-4.0,0.0); glVertex3i((numberColumn*widthRatio)-(WIDTH/2),DEPTH,(numberRow*heightRatio)-(HEIGHT/2));
glTexCoord2f(4.0,0.0); glVertex3i((numberColumn*widthRatio)-(WIDTH/2),DEPTH,(numberRow+1)*heightRatio-(HEIGHT/2));
glTexCoord2f(4.0,4.0); glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),DEPTH,(numberRow+1)*heightRatio-(HEIGHT/2));
glTexCoord2f(-4.0,4.0); glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),DEPTH,(numberRow)*heightRatio-(HEIGHT/2));
glEnd();
glDisable(GL_TEXTURE_2D);
}
else if(map[numberRow][numberColumn] == FOOD){
//Selecciona el color actual con el que dibujar. Parámetros R G y B, rango [0..1], así que estamos ante el color blanco
glColor3f(1.0,1.0,0.0); //Orange
/*glBegin() comienza una secuencia de vértices con los que se construirán primitivas. El tipo de primitivas viene dado por el parámetro de glBegin(), en este caso GL_QUADS.
* Al haber cuatro vértices dentro de la estructura, está definiendo un cuadrado. glEnd() simplemente cierra la estructura.
*
*/
//GLUquadric *sphere=gluNewQuadric();
gluQuadricDrawStyle( sphere, GLU_FILL);
gluQuadricNormals( sphere, GLU_SMOOTH);
gluQuadricOrientation( sphere, GLU_OUTSIDE);
gluQuadricTexture( sphere, GL_TRUE);
glPushMatrix();
glTranslated(((numberColumn+0.5)*widthRatio)-(WIDTH/2),DEPTH/3,(numberRow+0.5)*heightRatio-(HEIGHT/2) );
//glRotated(45,1,1,1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
LoadTexture("Flames64x64.jpg",64);
gluSphere(sphere,5.0,50,50);//(numberColumn+1)*widthRatio)-(WIDTH/2),0, (ysim)*heightRatio-(HEIGHT/2)
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
else if(map[numberRow][numberColumn] == PASSAGE){
//Selecciona el color actual con el que dibujar. Parámetros R G y B, rango [0..1], así que estamos ante el color blanco
glColor3f(1.0,0.5,0.0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
LoadTexture("FloorsMedieval64x64.jpg",64);
glBegin(GL_QUADS);
glTexCoord2f(-4.0,0.0); glVertex3i((numberColumn*widthRatio)-(WIDTH/2),2,(numberRow*heightRatio)-(HEIGHT/2));
glTexCoord2f(4.0,0.0); glVertex3i((numberColumn*widthRatio)-(WIDTH/2),2,(numberRow+1)*heightRatio-(HEIGHT/2));
glTexCoord2f(4.0,4.0); glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),2,(numberRow+1)*heightRatio-(HEIGHT/2));
glTexCoord2f(-4.0,4.0); glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),2,(numberRow)*heightRatio-(HEIGHT/2));
glEnd();
glDisable(GL_TEXTURE_2D);
}
}
}
Our teacher pass us the following code to use:
/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
void Maze::ReadJPEG(char *filename,unsigned char **image,int *width, int *height)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE * infile;
unsigned char **buffer;
int i,j;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
if ((infile = fopen(filename, "rb")) == NULL) {
printf("Unable to open file %s
",filename);
exit(1);
}
jpeg_stdio_src(&cinfo, infile);
jpeg_read_header(&cinfo, TRUE);
jpeg_calc_output_dimensions(&cinfo);
jpeg_start_decompress(&cinfo);
*width = cinfo.output_width;
*height = cinfo.output_height;
*image=(unsigned char*)malloc(cinfo.output_width*cinfo.output_height*cinfo.output_components);
buffer=(unsigned char **)malloc(1*sizeof(unsigned char **));
buffer[0]=(unsigned char *)malloc(cinfo.output_width*cinfo.output_components);
i=0;
while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines(&cinfo, buffer, 1);
for(j=0;j<cinfo.output_width*cinfo.output_components;j++)
{
(*image)[i]=buffer[0][j];
i++;
}
}
free(buffer);
jpeg_finish_decompress(&cinfo);
}
/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
void Maze::LoadTexture(char *filename,int dim)
{
unsigned char *buffer;
unsigned char *buffer2;
int width,height;
long i,j;
long k,h;
ReadJPEG(filename,&buffer,&width,&height);
buffer2=(unsigned char*)malloc(dim*dim*3);
//-- The texture pattern is subsampled so that its dimensions become dim x dim --
for(i=0;i<dim;i++)
for(j=0;j<dim;j++)
{
k=i*height/dim;
h=j*width/dim;
buffer2[3*(i*dim+j)]=buffer[3*(k*width +h)];
buffer2[3*(i*dim+j)+1]=buffer[3*(k*width +h)+1];
buffer2[3*(i*dim+j)+2]=buffer[3*(k*width +h)+2];
}
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,dim,dim,0,GL_RGB,GL_UNSIGNED_BYTE,buffer2);
free(buffer);
free(buffer2);
}
I got the error Unable to open file Groundplant64x64.jpg
Many times ive changed the file and still unable to open.
Dont know why it happens…the file is ok and the “first round” it draws all the maze with texture, but after 5 seconds or so gets closed.
I want to paint some textures depending if its wall or passage or food…
my display function from main:
void display()
{
/*Con esto se define el color con el que se borrara el buffer al hacer un glClear().
* Los 3 primeros parámetros son las componentes R, G y B, siguiendo un rango de [0..1]. La última es el valor alpha.
*/
glClearColor(0.0,0.0,0.0,0.0);
/* Borra un buffer o una combinación de varios. En este caso, borra el buffer de color (en realidad, cada componente
R G y B tienen un buffer distinto, pero aquí los trata como el mismo), el que se pinta después en pantalla.
Para borrarlos utiliza el color que ha sido previamente definido en init() mediante glClearColor(), en este caso,
el (0,0,0,0) es decir, pinta todo el buffer de negro.*/
//glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
PositionObserver(anglealpha,anglebeta,450);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//0,WIDTH-1,0,HEIGHT-1)
// glOrtho(-WIDTH*0.6,WIDTH*0.6,-HEIGHT*0.6,HEIGHT*0.6,10,2000);
glOrtho(-WIDTH/2,WIDTH/2,-HEIGHT/2,HEIGHT/2,10,2000);
glMatrixMode(GL_MODELVIEW);
glPolygonMode(GL_FRONT,GL_FILL);
glPolygonMode(GL_BACK,GL_LINE);
//draws
m.draw3D(WIDTH,HEIGHT);
myPacman.draw();
for(int i = 0; i < playingGhosts.size(); i++)
{
playingGhosts[i].draw();
}
glutSwapBuffers();
}
My main file:
int main (int argc, char *argv[])
{
srand(time(NULL));
anglealpha=90;
anglebeta=30;
m.setupMaze(ROWS, COLUMNS, LEVEL);
m.printMaze();
//myPacman.set_positionMap(rows/2][0);
/*Esta función es la que inicializa la GLUT y negocia con el sistema de ventanas para abrir una. Los parámetros deben ser los mismos argc y argv,
* sin modificar, de la función main(). Además, Glut entiende una serie de parámetros que pueden ser pasados por línea de comandos.*/
glutInit(&argc, argv);
/*En esta ocasión, utilizamos GLUT_DOUBLE en vez de GLUT_SIMPLE. Esto hace posible la utilización de la técnica de “double buffer”, con la utilizamos
* dos buffers para pintar en uno mientras se visualiza el otro. Con esto conseguimos una mayor fluidez en escenas.
*/
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
//glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
//Posición x e y de la esquina superior izquierda de la nueva ventana, con respecto al escritorio en el que se trabaje.
glutInitWindowPosition(WINDOW_X, WINDOW_Y);
//Comprobamos que el ancho y alto de nuestra ventana es menor que los pixeles de la pantalla.
//En ese caso no cabria nuestra ventana en la pantalla
if ( glutGet(GLUT_SCREEN_WIDTH) == 0 || glutGet(GLUT_SCREEN_WIDTH) < WIDTH)
throw out_of_range("Error: El ancho no puede ser cero. Error ancho pantalla");
if (glutGet(GLUT_SCREEN_HEIGHT) == 0 || glutGet(GLUT_SCREEN_HEIGHT) < HEIGHT)
throw std::out_of_range("Error: El alto no puede ser cero. Error alto pantalla");
//El ancho y alto de la nueva ventana.
glutInitWindowSize(WIDTH,HEIGHT);
// Esta función es la que propiamente crea la ventana y el parámetro es el nombre de la misma.
glutCreateWindow("Random Maze");
glEnable(GL_DEPTH_TEST);
//glEnable(GL_TEXTURE_2D);
int x= m.getRows();
int y =m.getColumns();
myPacman.set_positionMap((x/2),0);
direccion = 3;
Ghost g;
// playingGhosts.push_back(5,7);// Esto esta en mapa hay que traducirlo a pantalla o al reves...insertar en pantalla directamente
g.setIdGhost(ghosts);
g.set_positionMap((x/2) - 1, (y/2) -1); // Blinky
playingGhosts.push_back(g);
m.setGhost((x/2) - 1,(y/2) -1);
ghosts++;
g.setIdGhost(ghosts);
g.set_positionMap((x/2) - 1, (y/2)); // Pinky
playingGhosts.push_back(g);
m.setGhost((x/2) - 1,(y/2) -1);
ghosts++;
g.setIdGhost(ghosts);
g.set_positionMap((x/2), (y/2)-1); // Inky
playingGhosts.push_back(g);
m.setGhost((x/2) - 1,(y/2) -1);
ghosts++;
g.setIdGhost(ghosts);
g.set_positionMap((x/2),(y/2)); // Pokey
playingGhosts.push_back(g);
m.setGhost((x/2) - 1,(y/2) -1);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutSpecialFunc(specialkeyboard);
glutIdleFunc(idle);
/*Especifica la matriz actual para realizar la composición. En ogl las operaciones de rotación, translación, escalado, etc. se
* realizan a través de matrices de transformación. Dependiendo de lo que estemos tratando, hay tres tipos de matriz (que son
* los tres posibles flags que puede llevar de parámetro la función): matriz de proyección (GL_PROJECTION),
* matriz de modelo (GL_MODELVIEW) y matriz de textura (GL_TEXTURE). Con esta función indicamos a cual de estas tres deben
* afectar las operaciones. Concretamente, GL_PROJECTION afecta a las vistas o perspectivas o proyecciones.
*/
glMatrixMode(GL_PROJECTION);
/*glOrtho() define una perspectiva ortonormal. Esto quiere decir que lo que se ves será una proyección paralela en uno de los
* planos definidos por los ejes. Los parámetros sirven para delimitar el volumen de vista y son, por este orden:
* x_mínima, x_máxima, y_mínima, y_máxima, z_mínima, z_máxima, (estos dos últimos no son coordenadas como los cuatro primeros,
* son distancias desde el punto de vista, positivas hacia donde apunta y negativas hacia el lado contrario) considerando que,
* por defecto, el punto de vista está en el origen de coordenadas mirando hacia el eje negativo de z, estos valores son
* desplazamientos desde este punto. Con estos seis valores se define el volumen que incluirá los objetos que se proyecten.*/
// gluOrtho2D(0,WIDTH-1,0,HEIGHT-1);
// glBindTexture(GL_TEXTURE_2D,0);
//Esta función cede el control del flujo del programa a GLUT que, a partir de estos "eventos", irá llamando a las funciones que han sido pasadas como callbacks.
glutMainLoop();
return 0;
}
Any help would be apreciated. I ve put here the main things that affect the code, not the movement of pacman or ghosts. Just the error is related with textures and LoadTextures in concrete. LoadTextures in example of class is a global function in main as REadjpeg. But i have to use it in different classes to “paint” them with a texture.
If you need more information dont doubt to ask for…
I would upload the full project if necessary at dropbox or drive
Thanks in advance