   Trouble with textures and how do I detect a mouse click?
  Hi all,I've done a little 3D Opengl at Uni, but now I've finished, I'm finding it hard to get back into.Firstly, I'm trying to load a texture. I'm using tga files as it's easy to handle, but for some reason the textures seem to be corrupting. However, the same TGA importing code works perfectly else where.Here is what I've got so far: http://www.npc-gaming.co.uk/Lottery.zipAnd here is how to looks. http://www.npc-gaming.co.uk/corrupted.jpgAlso, when I finally do get this problem sorted, I'd like to detect when one of the squares are clicked with the mouse. There will be lots of squares and each will have a different value ie 100 squares with a value of 1 to 100.How do I go about doing this? As you may see, I've tried using glutMouseFunc() but it never did work.I hope someone can help me out here.Thanks.   
  I'm no GL expert (D3D guy) but it looks like you could be either:1) The GL texture is 32-bit (RGBA channels, regardless of whether the A is used or not) the TGA texture is 24-bit (so you can't do a direct copy with memcpy) or 16-bit (you'll have to do the conversion)2) The GL texture doesn't have width = pitch. I don't know if OGL hides this from the programmer, but in D3D the pitch might be higher than the width for alignment purposes, which means after completing each pixel row you have to skip a few bytes in order to start with the next row.3) There's another bug in your code where the height and/or width from the GL texture and TGA file don't match or you're iterating incorrectly through the pixels from both buffers.CheersDark Sylinc   ;  Firstly, a slightly large example would've been appreciated.Basically hitting on what Matias has said but in OpenGL speak.You need to check when loading the TGA that it's either 24-bit (RGB) or 32-bit (RGBA) formats, and specify the appropriate OpenGL Internal Format for the glTexture2d() call.You also need to work out whether your image is encoded as RGB or BGR (or BGRA) as the big- and little- endian ness isn't specified in the file, I've usually found that TGA files from Photoshop and things are BGR encoded.You also need to make sure that the TGA isn't RLE encoded, and if it is, account for it accordingly.TGA files shouldn't have any packing between each line (what Matias was referring to as the pitch) but there is an OpenGL call to set the OpenGL Packing (you'll have to google for that).If you're still having problems, let me know, and I'll take a closer look at your code. I'm currently at work and can't download it to have a good look.   ;  Thanks for the replies guys.I'll look into OpenGL Packing.As far as the TGA file, I've tried 24 and 32 bit and also with and without RLE.I used the exact same code which I used for my last piece of coursework at Uni for the TGA handling and that worked flawlessly with and without RLE but in this project I get the result you have seen above.CTargaImage.h#ifndef __TARGA_LIB#define __TARGA_LIBenum TGATypes{TGA_NODATA = 0,TGA_INDEXED = 1,TGA_RGB = 2,TGA_GRAYSCALE = 3,TGA_INDEXED_RLE = 9,TGA_RGB_RLE = 10,TGA_GRAYSCALE_RLE = 11};// Image Data Formats#defineIMAGE_RGB  0#define IMAGE_RGBA 1#define IMAGE_LUMINANCE 2// Image data types#defineIMAGE_DATA_UNSIGNED_BYTE 0// Pixel data transfer from file to screen:// These masks are AND'd with the imageDesc in the TGA header,// bit 4 is left-to-right ordering// bit 5 is top-to-bottom#define BOTTOM_LEFT  0x00// first pixel is bottom left corner#define BOTTOM_RIGHT 0x10// first pixel is bottom right corner#define TOP_LEFT0x20// first pixel is top left corner#define TOP_RIGHT    0x30// first pixel is top right corner// TGA headerstruct tgaheader_t{unsigned char  idLength;unsigned char  colorMapType;unsigned char  imageTypeCode;unsigned char  colorMapSpec[5];unsigned short xOrigin;unsigned short yOrigin;unsigned short width;unsigned short height;unsigned char  bpp;unsigned char  imageDesc;};struct rgba_t{unsigned char r;unsigned char g;unsigned char b;unsigned char a;};struct rgb_t{unsigned char r;unsigned char g;unsigned char b;};class CTargaImage{private:unsigned char  m_colorDepth;unsigned char  m_imageDataType;unsigned char  m_imageDataFormat;unsigned char *m_pImageData;unsigned short m_width;unsigned short m_height;unsigned long  m_imageSize;// swap the red and blue components in the image datavoid SwapRedBlue();public:CTargaImage();virtual ~CTargaImage();// loading and unloadingbool Load(const char *filename);void Release();// flips image verticallybool FlipVertical();unsigned short GetWidth() { return m_width; }unsigned short GetHeight() { return m_height; }unsigned char  GetImageFormat() { return m_imageDataFormat; }// converts RGB format to RGBA format and vice versabool ConvertRGBAToRGB();bool ConvertRGBToRGBA(unsigned char alphaValue);// returns the current image dataunsigned char *GetImage() { return m_pImageData; }};#endifCTargaImage.cpp#include <iostream>#include "CTargaImage.h"CTargaImage::CTargaImage() : m_pImageData(NULL){}CTargaImage::~CTargaImage(){Release();}void CTargaImage::SwapRedBlue(){switch (m_colorDepth){case 32:{unsigned char temp;rgba_t* source = (rgba_t*)m_pImageData;for (int pixel = 0; pixel < (m_width * m_height); ++pixel){temp = source[pixel].b;source[pixel].b = source[pixel].r;source[pixel].r = temp;}} break;case 24:{unsigned char temp;rgb_t* source = (rgb_t*)m_pImageData;for (int pixel = 0; pixel < (m_width * m_height); ++pixel){temp = source[pixel].b;source[pixel].b = source[pixel].r;source[pixel].r = temp;}} break;default:// ignore other color depthsbreak;}}bool CTargaImage::Load(const char *filename){FILE *pFile = fopen(filename, "rb");if (!pFile)return false;tgaheader_t tgaHeader;// read the TGA headerfread(&tgaHeader, 1, sizeof(tgaheader_t), pFile);// see if the image type is one that we support (RGB, RGB RLE, GRAYSCALE, GRAYSCALE RLE)if ( ((tgaHeader.imageTypeCode != TGA_RGB) && (tgaHeader.imageTypeCode != TGA_GRAYSCALE) &&  (tgaHeader.imageTypeCode != TGA_RGB_RLE) && (tgaHeader.imageTypeCode != TGA_GRAYSCALE_RLE)) || tgaHeader.colorMapType != 0){fclose(pFile);return false;}// get image width and heightm_width = tgaHeader.width;m_height = tgaHeader.height;// colormode -> 3 = BGR, 4 = BGRAint colorMode = tgaHeader.bpp / 8;// we don't handle less than 24 bitif (colorMode < 3){fclose(pFile);return false;}m_imageSize = m_width * m_height * colorMode;// allocate memory for TGA image datam_pImageData = new unsigned char[m_imageSize];// skip past the id if there is oneif (tgaHeader.idLength > 0)fseek(pFile, SEEK_CUR, tgaHeader.idLength);// read image dataif (tgaHeader.imageTypeCode == TGA_RGB || tgaHeader.imageTypeCode == TGA_GRAYSCALE){fread(m_pImageData, 1, m_imageSize, pFile);}else {// this is an RLE compressed imageunsigned char id;unsigned char length;rgba_t color = { 0, 0, 0, 0 };unsigned int i = 0;while (i < m_imageSize){id = fgetc(pFile);// see if this is run length dataif (id >= 128)// & 0x80){// find the run lengthlength = (unsigned char)(id - 127);// next 3 (or 4) bytes are the repeated valuescolor.b = (unsigned char)fgetc(pFile);color.g = (unsigned char)fgetc(pFile);color.r = (unsigned char)fgetc(pFile);if (colorMode == 4)color.a = (unsigned char)fgetc(pFile);// save everything in this runwhile (length > 0){m_pImageData[i++] = color.b;m_pImageData[i++] = color.g;m_pImageData[i++] = color.r;if (colorMode == 4)m_pImageData[i++] = color.a;--length;}}else{// the number of non RLE pixelslength = unsigned char(id + 1);while (length > 0){color.b = (unsigned char)fgetc(pFile);color.g = (unsigned char)fgetc(pFile);color.r = (unsigned char)fgetc(pFile);if (colorMode == 4)color.a = (unsigned char)fgetc(pFile);m_pImageData[i++] = color.b;m_pImageData[i++] = color.g;m_pImageData[i++] = color.r;if (colorMode == 4)m_pImageData[i++] = color.a;--length;}}}}fclose(pFile);switch(tgaHeader.imageTypeCode){case TGA_RGB:case TGA_RGB_RLE:if (3 == colorMode){m_imageDataFormat = IMAGE_RGB;m_imageDataType = IMAGE_DATA_UNSIGNED_BYTE;m_colorDepth = 24;}else{m_imageDataFormat = IMAGE_RGBA;m_imageDataType = IMAGE_DATA_UNSIGNED_BYTE;m_colorDepth = 32;}break;case TGA_GRAYSCALE:case TGA_GRAYSCALE_RLE:m_imageDataFormat = IMAGE_LUMINANCE;m_imageDataType = IMAGE_DATA_UNSIGNED_BYTE;m_colorDepth = 8;break;}if ((tgaHeader.imageDesc & TOP_LEFT) == TOP_LEFT)FlipVertical();// swap the red and blue components in the image dataSwapRedBlue();return (m_pImageData != NULL);}bool CTargaImage::FlipVertical(){if (!m_pImageData)return false;if (m_colorDepth == 32){rgba_t* tmpBits = new rgba_t[m_width];if (!tmpBits)return false;int lineWidth = m_width * 4;rgba_t* top = (rgba_t*)m_pImageData;rgba_t* bottom = (rgba_t*)(m_pImageData + lineWidth*(m_height-1));for (int i = 0; i < (m_height / 2); ++i){memcpy(tmpBits, top, lineWidth); memcpy(top, bottom, lineWidth);memcpy(bottom, tmpBits, lineWidth);top = (rgba_t*)((unsigned char*)top + lineWidth);bottom = (rgba_t* )((unsigned char*)bottom - lineWidth);}delete [] tmpBits;tmpBits = 0;}else if (m_colorDepth == 24){rgb_t* tmpBits = new rgb_t[m_width];if (!tmpBits)return false;int lineWidth = m_width * 3;rgb_t* top = (rgb_t*)m_pImageData;rgb_t* bottom = (rgb_t*)(m_pImageData + lineWidth*(m_height-1));for (int i = 0; i < (m_height / 2); ++i){memcpy(tmpBits, top, lineWidth); memcpy(top, bottom, lineWidth);memcpy(bottom, tmpBits, lineWidth);top = (rgb_t*)((unsigned char*)top + lineWidth);bottom = (rgb_t*)((unsigned char*)bottom - lineWidth);}delete [] tmpBits;tmpBits = 0;}return true;}void CTargaImage::Release(){delete [] m_pImageData;m_pImageData = NULL;}bool CTargaImage::ConvertRGBToRGBA(unsigned char alphaValue){if ((m_colorDepth == 24) && (m_imageDataFormat == IMAGE_RGB)){rgba_t *newImage = new rgba_t[m_width * m_height];if (!newImage)return false;rgba_t *dest = newImage;rgb_t *src = (rgb_t*)m_pImageData;for (int x = 0; x < m_height; x++){for (int y = 0; y < m_width; y++){dest->r = src->r;dest->g = src->g;dest->b = src->b;dest->a = alphaValue;++src;++dest;}}delete [] m_pImageData;m_pImageData = (unsigned char*)newImage;m_colorDepth = 32;m_imageDataType = IMAGE_DATA_UNSIGNED_BYTE;m_imageDataFormat = IMAGE_RGBA;return true;}return false;}bool CTargaImage::ConvertRGBAToRGB(){if ((m_colorDepth == 32) && (m_imageDataFormat == IMAGE_RGBA)){rgb_t *newImage = new rgb_t[m_width * m_height];if (!newImage)return false;rgb_t *dest = newImage;rgba_t *src = (rgba_t*)m_pImageData;for (int x = 0; x < m_height; x++){for (int y = 0; y < m_width; y++){dest->r = src->r;dest->g = src->g;dest->b = src->b;++src;++dest;}}delete [] m_pImageData;m_pImageData = (unsigned char*)newImage;m_colorDepth = 24;m_imageDataType = IMAGE_DATA_UNSIGNED_BYTE;m_imageDataFormat = IMAGE_RGB;return true;}return false;}And the part of my main file where I import the texture.void display(void){/* clear all pixels  */   glClear (GL_COLOR_BUFFER_BIT);   CTargaImage * m_TextureObject = new CTargaImage;   glEnable(GL_TEXTURE_2D);glPushMatrix();glGenTextures(1, &Textures[0]);if(!m_TextureObject->Load("tex.tga")){MessageBox(NULL, TEXT("Can't load textures: 1.tga"), NULL, MB_OK);PostQuitMessage(1);}glBindTexture(GL_TEXTURE_2D, Textures[0]);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_TextureObject->GetWidth(), m_TextureObject->GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, m_TextureObject->GetImage());glPopMatrix();   //glColor3f(red,green,blue);glBindTexture(GL_TEXTURE_2D,Textures[0]);glBegin(GL_POLYGON);  glTexCoord2f(0.0, 0.0);  glVertex3f (75, 75, 0.0);  glTexCoord2f(0.0, 1.0);  glVertex3f (75, 100, 0.0);  glTexCoord2f(1.0, 1.0);  glVertex3f (100, 100, 0.0);  glTexCoord2f(1.0, 0.0);  glVertex3f (100, 75, 0.0);glEnd();/* don't wait!   * start processing buffered OpenGL routines  */   glFlush ();}The TGA is 25x25 pixels, 32 bit (also tried 24 bit) and is created in Photoshop CS4.Cheers   ;Quote:Original post by Largo84The TGA is 25x25 pixelsDo your OpenGL support non-power-of-2 textures?I tested your code and it works fine for me with other texture sizes.By the way, you would probably want to not reload/recreate your textures each time you display them.;Quote:glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_TextureObject->GetWidth(), m_TextureObject->GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, m_TextureObject->GetImage());If your texture is really 32 bit, than this is wrong. 32 bit means that there is 4 components per pixel, but you're specifying GL_RGB which is only 24-bit (8R 8G 8B).You need to use a four channel texture (RGBA for one), and also make sure that your texture is in RGB and not BGR or something. Although if you tried 24 bit also then there must be something else as well.   ;Quote:Original post by rneckelmannQuote:Original post by Largo84The TGA is 25x25 pixelsDo your OpenGL support non-power-of-2 textures?I tested your code and it works fine for me with other texture sizes.By the way, you would probably want to not reload/recreate your textures each time you display them.Genius! Stupid me!I plan to have a load textures function, so as you rightly said, I don't want to load them on each display.Quote:Original post by karwostsQuote:glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_TextureObject->GetWidth(), m_TextureObject->GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, m_TextureObject->GetImage());If your texture is really 32 bit, than this is wrong. 32 bit means that there is 4 components per pixel, but you're specifying GL_RGB which is only 24-bit (8R 8G 8B).You need to use a four channel texture (RGBA for one), and also make sure that your texture is in RGB and not BGR or something. Although if you tried 24 bit also then there must be something else as well.Thanks for pointing this out too. Textures work as 24 bit now.Thank you, it now works.Now, on to my other question. How would I detect when somebody clicks that square or any other square I may add as mentioned in my original post?I know I can check for if greater then X and less than width ect, but doing that over 60 times in code can't be the best way to go about it.thanks.   ;  Come across another problem now.I'm trying to load 60 textures by the following method:CTargaImage * m_TextureObject = new CTargaImage;char file[6];char buf[2];   glEnable(GL_TEXTURE_2D);   for(int i=0; i<60; i++)   {_itoa_s(i,buf,2,10);file = buf + ".tga";   glPushMatrix();cout << file << endl;glGenTextures(1, &Textures);if(!m_TextureObject->Load(file)){MessageBox(NULL, TEXT("Can't load textures"), NULL, MB_OK);PostQuitMessage(1);}glBindTexture(GL_TEXTURE_2D, Textures);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_TextureObject->GetWidth(), m_TextureObject->GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, m_TextureObject->GetImage());glPopMatrix();   }Now apparantly, "main.cpp(26) : error C2110: '+' : cannot add two pointers".I wasn't aware I was adding pointers. The line it refers to is file = buf + ".tga";I tried a test program#include <iostream>#include <string>using namespace std;int main(){string test,that,all;char buf[2];int i=1;test = "THIS";that = "THAT";cout << test << " and " << that << endl;all = test + " and " + that;cout << all << endl;_itoa_s(i,buf,2,10);all = all + buf;cout << all << endl;return 0;}It works perfectly.I really don't understand what the hell is going on.I'm really frustrated at all this right now.   ;  Whenever you have a "abc" string literal in your code, this is a char* type. This code:char buf[2];file = buf + ".tga";is trying to add two char*'s together, which is illegal.This works:string test,that,all;char buf[2];all = test + " and " + that;Because std::string has an overloaded + operator that understands that when you add a char* to a string it means to append the characters to the end.In your code, you can do something like this:file = std::string(std::string(buf) + ".tga").c_str();You convert buf to a string, add the ".tga", and then convert it back to a c_string.   ;  Thanks for clearing that up. I decided to create one big texture and just load each part onto the polygon instead. Just trying to figure out the maths for it all.   