Cómo cargar y rellenar cubos con textura de imagen en openGL

Tengo una cuadrícula con cubos y quiero llenar los cubos con dos colores diferentes y con 3 imágenes diferentes (.bmp). Así que cada cubo está lleno de colores o imágenes. Escribí un código y cuando presiono el botón , la cuadrícula se llena con 5 colores diferentes. ¿Alguien puede decirme cómo puedo cambiar mi código para llenar la cuadrícula con 3 imágenes diferentes (al azar)? Aquí está mi código:

void randomFilling(); void myprint(); struct square{ int v1x, v1y; int v2x, v2y; int v3x, v3y; int v4x, v4y; int color; }; struct square Squares[12][15]; struct flags{ int b; }flags; void drawScene(); void findVerticesPosition(){ int counter=0; for(int i=0; i<600; i+=40){ for(int j=0; j<480; j+=40){ Squares[j/40][i/40].v1x = i; Squares[j/40][i/40].v1y = j; Squares[j/40][i/40].v2x = i; Squares[j/40][i/40].v2y = j+40; Squares[j/40][i/40].v3x = i+40; Squares[j/40][i/40].v3y = j+40; Squares[j/40][i/40].v4x = i+40; Squares[j/40][i/40].v4y = j; } } for(int i=0; i<12; i++){ for(int j=0; j<15; j++){ Squares[i][j].color = rand()%5 + 1; } } } void handleKeypress(unsigned char key, int x, int y) { switch (key) { case 27: //Escape key exit(0); case 98: //b randomFilling(); flags.b = 1; drawScene(); } } void randomFilling(){ int randomNumber; srand(time(NULL)); //randomNumber = rand() % 5 + 1; for(int i=0; i<12; i++){ for(int j=0; j<15; j++){ randomNumber = Squares[i][j].color; if(randomNumber == 1){ glBegin(GL_QUADS); glColor3f(1.0,0.9,0.1); glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y); glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y); glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y); glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y); glEnd(); } else if(randomNumber == 2){ glBegin(GL_QUADS); glColor3f(1.0,0.0,0.1); glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y); glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y); glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y); glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y); glEnd(); } else if(randomNumber == 3){ glBegin(GL_QUADS); glColor3f(0,0.9,0.1); glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y); glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y); glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y); glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y); glEnd(); } else if(randomNumber == 4){ glBegin(GL_QUADS); glColor3f(0,0,1); glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y); glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y); glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y); glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y); glEnd(); } else if(randomNumber == 5){ glBegin(GL_QUADS); glColor3f(0,0.9,1); glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y); glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y); glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y); glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y); glEnd(); } else{ printf("WTF\n"); } } } } //Initialize OpenGL void init(void) { glClearColor(1.0,1.0,1.0,1.0); glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0,600.0,-60.0,480.0); flags.b=0; } void drawScene(void) { glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.0,0.0,0.0); //glPointSize(3.0); if(flags.b==1){ randomFilling(); //------------ } glColor3f(0,0,0); glBegin(GL_LINES); for(int i = 0; i <= 600; i += 40) { glVertex2f((float)i, 0.0f); glVertex2f((float)i, 480.0f); glVertex2f(0.0f, (float)i); glVertex2f(600.0f, (float)i); } glEnd(); glFlush(); } int main(int argc, char**argv) { findVerticesPosition(); //myprint(); glutInit(&argc, argv); glutInitWindowPosition(300,80); glutInitWindowSize(600,540); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutCreateWindow("BraXaPsa II"); init(); glutDisplayFunc(drawScene); //glutDisplayFunc(randomFilling); glutKeyboardFunc(handleKeypress); glutMainLoop(); } 

Aquí publico código para mostrar imágenes (texturas) en lugar de colores.

 // relative path to texture bitmaps char* texture_names[] = { "textures\\grass.tga", "textures\\wood\\brown wood.tga", "textures\\ceiling.tga" }; void randomFilling(); void myprint(); struct square{ int v1x, v1y; int v2x, v2y; int v3x, v3y; int v4x, v4y; int texture; }; struct square Squares[12][15]; struct flags{ int b; }flags; void drawScene(); void findVerticesPosition(){ int counter=0; for(int i=0; i<600; i+=40){ for(int j=0; j<480; j+=40){ Squares[j/40][i/40].v1x = i; Squares[j/40][i/40].v1y = j; Squares[j/40][i/40].v2x = i; Squares[j/40][i/40].v2y = j+40; Squares[j/40][i/40].v3x = i+40; Squares[j/40][i/40].v3y = j+40; Squares[j/40][i/40].v4x = i+40; Squares[j/40][i/40].v4y = j; } } for(int i=0; i<12; i++){ for(int j=0; j<15; j++){ Squares[i][j].texture = rand()%3; } } } void handleKeypress(unsigned char key, int x, int y) { switch (key) { case 27: //Escape key exit(0); case 98: //b randomFilling(); flags.b = 1; drawScene(); } } // creating texture objects array GLuint g_pnTextures[3]; void randomFilling(){ for(int i=0; i<12; i++){ for(int j=0; j<15; j++){ glColor3f(1.0f, 1.0f, 1.0f); glBindTexture(GL_TEXTURE_2D, g_pnTextures[Squares[i][j].texture]); glBegin(GL_QUADS); // specify texture coords glTexCoord2f(0.0f, 0.0f); glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y); // specify texture coords glTexCoord2f(0.0f, 1.0f); glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y); // specify texture coords glTexCoord2f(1.0f, 1.0f); glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y); // specify texture coords glTexCoord2f(1.0f, 0.0f); glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y); glEnd(); } } } //Initialize OpenGL void init(void) { GLbyte* pImage = NULL; GLint width = 0; GLint height = 0; GLint components = 0; GLenum format; glClearColor(1.0,1.0,1.0,1.0); glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0,600.0,-60.0,480.0); flags.b=0; // Generate texture object glGenTextures(3, g_pnTextures); for (int i = 0; i < 3; i++) { // bind current texture object glBindTexture(GL_TEXTURE_2D,g_pnTextures[i]); // load texture data pImage = gltLoadTGA(texture_names[i],&width,&height,&components,&format); glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,GL_TRUE); printf("texture: \"%s\" - %p\n",texture_names[i],pImage); // Load texture data to video memory glTexImage2D(GL_TEXTURE_2D,0,GL_COMPRESSED_RGB_S3TC_DXT1_EXT, width,height,0,format,GL_UNSIGNED_BYTE,pImage); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,8); glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE); delete [] pImage; pImage = NULL; } glEnable(GL_TEXTURE_2D); } void drawScene(void) { glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.0,0.0,0.0); //glPointSize(3.0); if(flags.b==1){ randomFilling(); //------------ } glColor3f(0,0,0); glBegin(GL_LINES); for(int i = 0; i <= 600; i += 40) { glVertex2f((float)i, 0.0f); glVertex2f((float)i, 480.0f); glVertex2f(0.0f, (float)i); glVertex2f(600.0f, (float)i); } glEnd(); glFlush(); } int main(int argc, char**argv) { findVerticesPosition(); //myprint(); glutInit(&argc, argv); glutInitWindowPosition(300,80); glutInitWindowSize(600,540); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutCreateWindow("BraXaPsa II"); init(); glutDisplayFunc(drawScene); //glutDisplayFunc(randomFilling); glutKeyboardFunc(handleKeypress); glutMainLoop(); // Unload texture data glDeleteTextures(3, g_pnTextures); } 

El resultado será como:

introduzca la descripción de la imagen aquí

Las dos partes esenciales son cargar texturas en la memoria y especificar coordenadas de texturas a primitivas para un ajuste de textura adecuado.

El proceso de carga de texturas se muestra aquí.

  for (int i = 0; i < 3; i++) { // bind current texture object glBindTexture(GL_TEXTURE_2D,g_pnTextures[i]); // load texture data pImage = gltLoadTGA(texture_names[i],&width,&height,&components,&format); glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,GL_TRUE); printf("texture: \"%s\" - %p\n",texture_names[i],pImage); // Load texture data to video memory glTexImage2D(GL_TEXTURE_2D,0,GL_COMPRESSED_RGB_S3TC_DXT1_EXT, width,height,0,format,GL_UNSIGNED_BYTE,pImage); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,8); glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE); delete [] pImage; pImage = NULL; } 

Y proceso de mapeo de coordenadas de texturas.

  glBegin(GL_QUADS); // specify texture coords glTexCoord2f(0.0f, 0.0f); glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y); // specify texture coords glTexCoord2f(0.0f, 1.0f); glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y); // specify texture coords glTexCoord2f(1.0f, 1.0f); glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y); // specify texture coords glTexCoord2f(1.0f, 0.0f); glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y); glEnd(); 

Como no puedes cargar tga bitmaps directamente. Publico código para lidiar con este problema.

 // Define targa header. #pragma pack(1) typedef struct { GLbyte identsize; // Size of ID field that follows header (0) GLbyte colorMapType; // 0 = None, 1 = paletted GLbyte imageType; // 0 = none, 1 = indexed, 2 = rgb, 3 = grey, +8=rle unsigned short colorMapStart; // First colour map entry unsigned short colorMapLength; // Number of colors unsigned char colorMapBits; // bits per palette entry unsigned short xstart; // image x origin unsigned short ystart; // image y origin unsigned short width; // width in pixels unsigned short height; // height in pixels GLbyte bits; // bits per pixel (8 16, 24, 32) GLbyte descriptor; // image descriptor } TGAHEADER; #pragma pack(8) GLbyte *gltLoadTGA(const char *szFileName, GLint *iWidth, GLint *iHeight, GLint *iComponents, GLenum *eFormat) { FILE *pFile; // File pointer TGAHEADER tgaHeader; // TGA file header unsigned long lImageSize; // Size in bytes of image short sDepth; // Pixel depth; GLbyte *pBits = NULL; // Pointer to bits // Default/Failed values *iWidth = 0; *iHeight = 0; *eFormat = GL_BGR_EXT; *iComponents = GL_RGB8; // Attempt to open the fil pFile = fopen(szFileName, "rb"); if(pFile == NULL) return NULL; // Read in header (binary) fread(&tgaHeader, 18/* sizeof(TGAHEADER)*/, 1, pFile); // Do byte swap for big vs little endian #ifdef __APPLE__ BYTE_SWAP(tgaHeader.colorMapStart); BYTE_SWAP(tgaHeader.colorMapLength); BYTE_SWAP(tgaHeader.xstart); BYTE_SWAP(tgaHeader.ystart); BYTE_SWAP(tgaHeader.width); BYTE_SWAP(tgaHeader.height); #endif // Get width, height, and depth of texture *iWidth = tgaHeader.width; *iHeight = tgaHeader.height; sDepth = tgaHeader.bits / 8; // Put some validity checks here. Very simply, I only understand // or care about 8, 24, or 32 bit targa's. if(tgaHeader.bits != 8 && tgaHeader.bits != 24 && tgaHeader.bits != 32) return NULL; // Calculate size of image buffer lImageSize = tgaHeader.width * tgaHeader.height * sDepth; // Allocate memory and check for success pBits = new GLbyte[lImageSize]; if(pBits == NULL) return NULL; // Read in the bits // Check for read error. This should catch RLE or other // weird formats that I don't want to recognize if(fread(pBits, lImageSize, 1, pFile) != 1) { free(pBits); return NULL; } // Set OpenGL format expected switch(sDepth) { case 3: // Most likely case *eFormat = GL_BGR_EXT; *iComponents = GL_RGB8; break; case 4: *eFormat = GL_BGRA_EXT; *iComponents = GL_RGBA8; break; case 1: *eFormat = GL_LUMINANCE; *iComponents = GL_LUMINANCE8; break; }; // Done with File fclose(pFile); // Return pointer to image data return pBits; }