Problem with texturing and Xlib

I’m having a hard time getting a simple program to work right. I’m just trying to draw a rectangle and then apply a texture map to it. The rectangle comes out fine, but it’s not textured; also strange is that it’s colored a sort of brownish-orange color for no good reason that I can tell. The color of the rectangle seems to depend on which bitmap I use to try to texture the surface with. Anyway, here’s the code…I’d be VERY grateful for any help you could give me. Oh - before anyone asks - yes, my bitmap’s dimensions are powers of 2 (256 x 256, to be exact).

#include <iostream.h>
#include <string>

#include <GL/glx.h>
#include <GL/glu.h>

#include “bitmap.h”

int main() {

Display* dpy;
string dpyName;
XVisualInfo* vi;
int viAttribList[] = {
GLX_RGBA, GLX_DEPTH_SIZE, 16, None
};
GLXContext cx;
Colormap cmap;
XSetWindowAttributes swa;
Bitmap* bmp;
Window win;
XEvent event;
GLuint texName;

/**

  • Open the connection to the appropriate X server.
    */
    dpyName = getenv(“DISPLAY”);
    dpy = XOpenDisplay(dpyName.c_str());
    if (dpy == NULL) {
    cerr << "Error: couldn’t connect to X server " << dpyName << endl;
    exit(1);
    }

/**

  • Make sure this X server has an OpenGL GLX extension.
    */
    if (!glXQueryExtension(dpy, NULL, NULL)) {
    cerr << "Error: X server "
    << dpyName
    << “has no OpenGL GLX extension” << endl;
    exit(1);
    }

/**

  • Set up the visual for a double-buffered, RGBA format, 16-bit depth
  • display.
    */
    vi = glXChooseVisual(dpy, DefaultScreen(dpy), viAttribList);
    if (vi == NULL) {
    cerr << “Error: no appropriate visual” << endl;
    exit(1);
    }

/**

  • Create the GLX rendering context that renders directly to the graphics
  • system if it can.
    */
    cx = glXCreateContext(dpy, vi, NULL, GL_TRUE);
    if (cx == NULL) {
    cerr << “Error: couldn’t create rendering context” << endl;
    exit(1);
    }

/**

  • Create the color map.
    */
    cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
    vi->visual, AllocNone);

/**

  • Set up the window attributes.
    */
    swa.colormap = cmap;
    swa.border_pixel = 0;
    swa.event_mask = (ExposureMask |
    StructureNotifyMask);

bmp = new Bitmap(“bmp.bmp”);

/**

  • Create the window.
    */
    win = XCreateWindow(dpy,
    RootWindow(dpy, vi->screen),
    0, 0,
    640, 480,
    0,
    vi->depth,
    InputOutput,
    vi->visual,
    CWBorderPixel | CWColormap | CWEventMask,
    &swa);

/**

  • Display the window, and bind the rendering context to it.
    */
    XMapWindow(dpy, win);
    glXMakeCurrent(dpy, win, cx);

/**

  • Set up OpenGL.
    */
    glEnable(GL_DEPTH_TEST);
    glClear(GL_DEPTH_BUFFER_BIT);
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);

// Set up shading
glShadeModel(GL_SMOOTH);

// Set up lights
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

// Define the texture
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_2D, texName);
glEnable(GL_TEXTURE_2D);
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);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bmp->GetWidth(), bmp->GetHeight(),
0, GL_RGB, GL_UNSIGNED_BYTE, (GLubyte*)(bmp->GetData()));

GLenum e = glGetError();
if (e != GL_NO_ERROR)
cout << "Error result: " << gluErrorString(e) << endl;

glMatrixMode(GL_PROJECTION);
gluPerspective(60.0, float(640)/float(480), 1.0, 4000.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(320.0, 240.0, 2.0,
320.0, 240.0, -1.0,
0.0, 1.0, 0.0);

while (true) {
XNextEvent(dpy, &event);
switch (event.type) {
case Expose:
if (event.xexpose.count > 0) break;
// Draw the textured image
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, texName);
glBegin(GL_QUADS);
glColor3f(0.0, 1.0, 0.0);
glTexCoord2f(0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glTexCoord2f(1.0, 0.0);
glVertex3f(640.0, 0.0, 0.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(640.0, 320.0, 0.0);
glTexCoord2f(0.0, 1.0);
glVertex3f(0.0, 320.0, 0.0);
glEnd();

  glFlush();
  glWaitGL();
  
  break;

}

}

delete bmp;

return 0;
}

All the GL stuff looks correct.

How certain are you that your Bitmap class is doing the right thing?

Originally posted by rts:
[b]All the GL stuff looks correct.

How certain are you that your Bitmap class is doing the right thing?[/b]

Fairly certain - here’s the code for that, too, if you’re interested. I’d really appreciate it! (I’ve omitted the typedefs.h file - I guarantee that those are correct. )

// ----------

/**

*/

#ifndef BITMAP_H
#define BITMAP_H

#include <string>
#include “typedefs.h”

const WORD BM = 0x4D42;

#pragma pack(1)
struct BITMAPFILEHEADER {
WORD bfType; // type of file (must be BM)
DWORD bfSize; // size of bitmap file, in bytes
WORD bfReserved1; // reserved; must be 0
WORD bfReserved2; // reserved; must be 0
DWORD bfOffBits; // offset, in bytes, from this structure to the data
};

struct BITMAPINFOHEADER {
DWORD biSize; // size of structure, in bytes
LONG biWidth; // bitmap width, in pixels
LONG biHeight; // bitmap height, in pixels
WORD biPlanes; // number of planes for target device (must be 1)
WORD biBitCount; // number of bits per pixel (must be 1, 4, 8, or 24)
DWORD biCompression; // type of compression (BI_RGB, BI_RLE8, BI_RLE4, or
// BI_BITFIELDS)
DWORD biSizeImage; // size, in bytes, of the image
LONG biXPelsPerMeter; // horizontal resolution in pixels per meter
LONG biYPelsPerMeter; // vertical resolution in pixels per meter
DWORD biClrUsed; // number of indices in color table used
DWORD biClrImportant; // number of “critical” indices in color table
};

struct RGBQUAD {
BYTE rgbBlue; // intensity of blue color
BYTE rgbGreen; // intensity of green color
BYTE rgbRed; // intensity of red color
BYTE rgbReserved; // reserved; must be 0
};

struct BITMAPINFO {
BITMAPINFOHEADER bmiHeader; // info about dimensions & color format
RGBQUAD bmiColors[1]; // color table
};

#pragma pack()

using namespace std;

class Bitmap {
public:
Bitmap();
Bitmap(const string& fileName);
Bitmap(const Bitmap& origBitmap);
~Bitmap();
Bitmap& operator=(const Bitmap& origBitmap);

bool OpenFile(const string& fileName);

int GetSize() const;
int GetWidth() const;
int GetHeight() const;
int GetBitCount() const;
const BYTE* const GetData() const;

private:
BITMAPFILEHEADER _bmpFileHeader;
BITMAPINFO _bmpInfo;
BYTE* _bmpData;
};

#endif

// --------------

/**

*/

#include <fstream>
#include <iostream>
#include “bitmap.h”

Bitmap::Bitmap() {
_bmpData = NULL;
}

Bitmap::Bitmap(const string& fileName) {
_bmpData = NULL;
OpenFile(fileName);
}

Bitmap::Bitmap(const Bitmap& origBitmap) {
int size;

_bmpFileHeader = origBitmap._bmpFileHeader;
_bmpInfo = origBitmap._bmpInfo;
size = origBitmap.GetSize();
if (size == 0)
_bmpData = NULL;
else
memcpy(_bmpData, origBitmap._bmpData, size);
}

Bitmap::~Bitmap() {
if (_bmpData != NULL)
delete _bmpData;
}

Bitmap& Bitmap: perator=(const Bitmap& origBitmap) {
int size;

if (&origBitmap != this) {
_bmpFileHeader = origBitmap._bmpFileHeader;
_bmpInfo = origBitmap._bmpInfo;
size = origBitmap.GetSize();
if (size == 0)
_bmpData = NULL;
else
memcpy(_bmpData, origBitmap._bmpData, size);
}

return (*this);
}

bool Bitmap::OpenFile(const string& fileName) {
ifstream fin;

fin.open(fileName.c_str());
if (!fin) {
cerr << "Error: Bitmap::OpenFile() - cannot open file "
<< fileName
<< endl;
return (false);
}

// read the BITMAPFILEHEADER structure
fin.read((char*)&(_bmpFileHeader), sizeof(BITMAPFILEHEADER));

if (_bmpFileHeader.bfType != BM) {
cerr << “Error: Bitmap::OpenFile() - file "
<< fileName
<< " is not a Windows bitmap file”
<< endl;
return (false);
}

// read the BITMAPINFOHEADER
fin.read((char*)&(_bmpInfo.bmiHeader), sizeof(BITMAPINFOHEADER));

// forget about the color palette - we only support high-color bitmaps
fin.seekg(-(int)(_bmpInfo.bmiHeader.biSizeImage), ios::end);
_bmpData = new BYTE[_bmpInfo.bmiHeader.biSizeImage];
fin.read((char*)(_bmpData), (streamsize)(_bmpInfo.bmiHeader.biSizeImage));

return (true);
}

int Bitmap::GetSize() const {
return (_bmpInfo.bmiHeader.biSizeImage);
}

int Bitmap::GetWidth() const {
return (_bmpInfo.bmiHeader.biWidth);
}

int Bitmap::GetHeight() const {
return (_bmpInfo.bmiHeader.biHeight);
}

int Bitmap::GetBitCount() const {
return (_bmpInfo.bmiHeader.biBitCount);
}

const BYTE* const Bitmap::GetData() const {
return (_bmpData);
}

Nothing immediately jumps out as wrong there either, although I will say that #pragma is evil. That’s a Visual C+±ism. You should really use:

struct BITMAPFILEHEADER
{

} attribute((packed));

etc.

instead.

When I get home I’ll grab your source and try it out to see if there’s something going on that I’m just not noticing in a cold code reading.

Originally posted by rts:
[b]Nothing immediately jumps out as wrong there either, although I will say that #pragma is evil. That’s a Visual C+±ism. You should really use:

[quote]

struct BITMAPFILEHEADER
{

} attribute((packed));

etc.

instead.

When I get home I’ll grab your source and try it out to see if there’s something going on that I’m just not noticing in a cold code reading.[/b][/QUOTE]

Hmm. Okay - I didn’t know about the attribute thing. Can you tell I haven’t been programming under Linux much? But thank you very much for looking at this for me - it’s been driving me CRAZY. I appreciate it.

-Will

BTW - here’s that typedefs.h file; it’s not too hard to figure out what’s in it, but this’ll save you from having to type it out, anyway.

#ifndef TYPEDEFS_H
#define TYPEDEFS_H

typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef long LONG;
typedef unsigned char BYTE;

#endif

Step away from the quad…

Change your gluLookAt to something like:

gluLookAt(320.0, 240.0, 500.0,
          320.0, 240.0, -1.0,
          0.0, 1.0, 0.0);

(Note the 500.0). You were standing really really close to your quad.

God. Thank you. I was working on solving the problem myself just now and had just managed to narrow it down to a problem with my viewing. Now that I think about it, it makes perfect sense - I was so close that the brownish-orange I was seeing was the color of a small part of the bitmap, blown up to fill the entire field of vision. Sigh.

Thanks very much again - I truly appreciate it!

-Will

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.