Texturing in OpenGL

Started by
22 comments, last by Merowingian 16 years, 7 months ago
@Naxos:

sorry, the alignment thing doesn't make a difference.

And it's not really that I PREFER getSurface(surf) over surf = getSurface() etc., it's just that C++ seems to be too stupid to return a char* from a function.



@songho:

I see your point, but I was going to write a Texture class holding the width and height information later on, so I can retrieve that information from there.
As you can see in my code, the PPMReader gets discarded after loading the texture infomation into the shelf's surface attribute. So I can't get width and height from there.
I'm thinking of replacing the surface attribute of the Shelf class with an object of the Texture class (still to be written). As said, the Texture class will then hold the image data PLUS width and height information.
For the time being, I have to resort to predefined width and height values.

Omitting the memory allocation line unfortunately doesn't change anything. Actually, I already thought it might be totally unneccesary, but I thought that this way I could make C++ understand that whatever gets assigned to texture should BY NO MEANS be bigger than the array size defined in that statement. But obviously C++ doesn't work that way.
How can I tell C++ NEVER to allow an assignement bigger than x characters to the texture variable, or let's say to the surface variable? Obviously it's surface that is too big, causing the problem.
Look at my void PPMReader::loadPPMFile(char * filename) again, you'll see that image gets its predefined size at image = new char[imageBytes];.
But perhaps that line is unneccessary too, then, maybe the follwing read command is still allowed to place ANY number of characters into image.
Advertisement
Quote:Original post by Sharlin
Before you can call glTexImage, you must bind some valid texture name with glBindTexture. It is not until the first time you bind a previously-unused texture name, the corresponding texture object is actually created. You can then initialize said object by calling glTexImage.
That's true except for the first sentence. Texture object 0 (the default texture) is initially bound so any texture operations will operate on that unless you bind a different texture.
Quote:Original post by Merowingian
void setShelf(){     char* ppmFn = "holz.ppm";     PPMReader ppm = PPMReader(ppmFn);     char* surface;     ppm.getImage(surface);     shelf = Shelf(1.5, 1.5, 1.5, surface);}
So what happens with ppm goes out of scope? Does its destructor delete [] PPMReader::image?
Quote:Original post by Merowingian
Which is fine but without texture, unless I uncomment the line
shelf.getSurface(texture);
As I said, this would lead to an access violation error which I do not understand.
Since all PPMReader::getImage() and Shelf::getSurface() do is set some pointer to point to the same data as PPMReader::image, if PPMReader's destructor delete[]s that data, than trying to access it should cause an access violation.
Quote:Original post by Merowingian
And it's not really that I PREFER getSurface(surf) over surf = getSurface() etc., it's just that C++ seems to be too stupid to return a char* from a function.
C++'s stupidity is a subject of much debate/argument, but it has no trouble returning a char*.

And although I didn't notice anything wrong with this (I didn't really look though), since you're using C++, why not use std::string for strings instead of a char pointer?.
You're so right, Kalidor!!!

I haven't defined any destructor for PPMReader, so it will DESTROY the image!
Passing on the image pointer to the shelf therefore will cause "structure" to point to inaccessible memory when used outside the scope of setShelf().
Well I've tried to solve this problem by modifying the setShelf() function in my main.cpp like this:

void setShelf() {

char* ppmFn = "holz.ppm";
PPMReader ppm = PPMReader(ppmFn);
char* surface = new char[256 * 256 * 3];
char* image;
ppm.getImage(image);
memcpy(surface, image, 256 * 256 * 3);
shelf = Shelf(1.5, 1.5, 1.5, surface);

}


You see, I'm copying the whole image byte by byte into a new array, to be independent of ppm's existence.

The access violation error is now GONE, but the shelf remains WHITE. I'm trying to figure out how this is possible. Any hints?
Did you change the texture's minification filter? The default is GL_NEAREST_MIPMAP_LINEAR, which is a mipmapping minification filter. If the texture uses a mipmapping filter but doesn't have all mipmap levels specified than it's as if texturing were disabled for the texture unit that texture is bound to. It looks like you're only specifying level 0 of the texture so I would try setting GL_TEXTURE_MIN_FILTER to GL_NEAREST or GL_LINEAR. You can do that with glTexParameter*.
yeah, but i want to start without using mipmaps first.

mipmapping is just an optional improvement, you should be able to use texturing with just linear filtering. these are my opengl texturing settings:


glEnable(GL_TEXTURE_2D);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);


meanwhile, I have also applied changes to the Shelf constructor:

Shelf::Shelf(float x, float y, float z, char* surface) {
setPosition(x, y, z);
this->surface = new char[256 * 256 * 3];
memcpy((char*)(this->surface), surface, 256 * 256 * 3);
}


All this hasn't helped yet, sorry :





Hhmmm...

well, just to remind you, this isn't about memory access violation any more.

It's just that the textures are not seen on my objects at all, they just remain plain white.

Any new hints at where the problem could be?

Can you show the code involving the drawing of the object?
Yeah, here it is:



void drawShelf() {

Dimensions dims = Shelf::getDimensions();
float innerWidth = dims.width - 2 * Shelf::getThickness();
float innerHeight = dims.height - 2 * Shelf::getThickness();

glPushMatrix();
Position position = shelf.getPosition();
glTranslatef(position.x, position.y, position.z);
bool textFlags[6] = { true, true, true, true, true, true };
GLuint* textures = (GLuint*)(malloc(sizeof(GLuint)));
glGenTextures(1, textures);
glBindTexture(GL_TEXTURE_2D, textures[0]);
const unsigned int textWidth = 256;
const unsigned int textHeight = 256;
const unsigned int bytesPerPix = 3;
const unsigned int textBytes = textWidth * textHeight * bytesPerPix;
char* texture = new char[textBytes];
shelf.getSurface(texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textWidth, textHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);

// zeichne linkes Seitenbrett
drawTextQuad(Shelf::getThickness(), dims.height, dims.length, textFlags);

// zeichne rechtes Seitenbrett
glPushMatrix();
glTranslatef(Shelf::getThickness() + innerWidth, 0.0f, 0.0f);
drawTextQuad(Shelf::getThickness(), dims.height, dims.length, textFlags);
glPopMatrix();

// zeichne unteres Brett
glPushMatrix();
glTranslatef(Shelf::getThickness(), 0.0f, 0.0f);
drawTextQuad(innerWidth, Shelf::getThickness(), dims.length, textFlags);

// zeichne oberes Brett
glTranslatef(0.0f, Shelf::getThickness() + innerHeight, 0.0f);
drawTextQuad(innerWidth, Shelf::getThickness(), dims.length, textFlags);
glPopMatrix();

glPopMatrix();
glDeleteTextures(1, textures);

}



void drawQuad(float width, float height, float length) {

drawLRQuadWall(height, length);

glPushMatrix();
glTranslatef(width, 0.0f, 0.0f);
drawLRQuadWall(height, length);
glPopMatrix();

drawBTQuadWall(width, length);

glPushMatrix();
glTranslatef(0.0f, height, 0.0f);
drawBTQuadWall(width, length);
glPopMatrix();

drawBFQuadWall(width, height);

glPushMatrix();
glTranslatef(0.0f, 0.0f, length);
drawBFQuadWall(width, height);
glPopMatrix();

}




void drawTextQuad(float width, float height, float length, textFlagAr textFlags) {

if (textFlags[0]) drawTextLRQuadWall(height, length); else drawLRQuadWall(height, length);

glPushMatrix();
glTranslatef(width, 0.0f, 0.0f);
if (textFlags[1]) drawTextLRQuadWall(height, length); else drawLRQuadWall(height, length);
glPopMatrix();

if (textFlags[2]) drawTextBTQuadWall(width, length); else drawBTQuadWall(width, length);

glPushMatrix();
glTranslatef(0.0f, height, 0.0f);
if (textFlags[3]) drawTextBTQuadWall(width, length); else drawBTQuadWall(width, length);
glPopMatrix();

if (textFlags[4]) drawTextBFQuadWall(width, height); else drawBFQuadWall(width, height);

glPushMatrix();
glTranslatef(0.0f, 0.0f, length);
if (textFlags[5]) drawTextBFQuadWall(width, height); else drawBFQuadWall(width, height);
glPopMatrix();

}

void drawLRQuadWall(float height, float length) {
glBegin(GL_POLYGON);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, height, 0.0f);
glVertex3f(0.0f, height, length);
glVertex3f(0.0f, 0.0f, length);
glEnd();
}

void drawBTQuadWall(float width, float length) {
glBegin(GL_POLYGON);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(width, 0.0f, 0.0f);
glVertex3f(width, 0.0f, length);
glVertex3f(0.0f, 0.0f, length);
glEnd();
}

void drawBFQuadWall(float width, float height) {
glBegin(GL_POLYGON);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, height, 0.0f);
glVertex3f(width, height, 0.0f);
glVertex3f(width, 0.0f, 0.0f);
glEnd();
}

void drawTextLRQuadWall(float height, float length) {
glBegin(GL_POLYGON);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, height, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(0.0f, height, length);
glTexCoord2f(1.0f, 0.0f); glVertex3f(0.0f, 0.0f, length);
glEnd();
}

void drawTextBTQuadWall(float width, float length) {
glBegin(GL_POLYGON);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(width, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(width, 0.0f, length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, 0.0f, length);
glEnd();
}

void drawTextBFQuadWall(float width, float height) {
glBegin(GL_POLYGON);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(width, 0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(width, height, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, height, 0.0f);
glEnd();
}
Sorry, forgot the definitions:


const unsigned int numOfQuadSides = 6;

typedef bool textFlagAr[numOfQuadSides];

void drawQuad(float width, float height, float length);

void drawTextQuad(float width, float height, float length, textFlagAr textFlags);

void drawLRQuadWall(float height, float length);

void drawBTQuadWall(float width, float length);

void drawBFQuadWall(float width, float height);

void drawTextLRQuadWall(float height, float length);

void drawTextBTQuadWall(float width, float length);

void drawTextBFQuadWall(float width, float height);
BT = "bottom and top"

LR = "left and right"

BF = "back and front"

This topic is closed to new replies.

Advertisement