Vertex arrays and colors

I have a kind of funky color problem with vertex arrays. I load arrays of vertices, colors, and triangle indices as in the following code. The vertices and color arrays are of the same size and have a 1-to-1 correspondence. The triangle array contains a set of faces defined in terms of indices in the vertices array. I compute the color RGB components according to the height (z) value of each vertex. As it turns out, I get a bogus color scheme when rendering the model, all the colors are mixed up. I suspect that my understanding of vertex arrays is flawed so if you see something blatant in the following code please let me know.

Thanks in advance!

// Define a 3D vertex
struct Vertex
{
float x,y,z;
};

// Define a 4 component color
struct Color
{
float r,g,b,a;
};

// Define a triangular face in terms of indices in an external vertex pool
struct IndexedTriangle
{
unsigned int vertices[3];
};

// Define the renderer
struct Renderer
{
// Construct given references to external data
Renderer(
unsigned int vCount,
unsigned int fCount,
Vertex* v,
Color* v,
IndexFace* f
)
{
vertices = v;
colors = c;
faces = f;
vertexCount = vCount;
faceCount = fCount;
}

// Number of vertices in vertex pool
unsigned int vertexCount;

// Number of faces
unsigned int faceCount;

// The external vertex pool
Vertex* vertices;

// The external color array
Color* colors;

// The external faces
IndexFace* faces;

// Prepare for rendering
void initialize();

// Render the model
void render();
};

void Renderer::initialize()
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3,GL_FLOAT,sizeof(Vertex),vertices);

glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4,GL_FLOAT,sizeof(Color),colors);
}

void Renderer::render()
{
glDrawElements(
GL_TRIANGLES,
3*faceCount,
GL_UNSIGNED_INT,
faces
);
}

[This message has been edited by Iceman (edited 02-20-2002).]

Try with stride = 0

That made no difference for some reason. I posted some pix at http://www.magnacom-inc.com/pleopard/Dev/VtxColorAryProb/default.htm

I don’t understand why you don’t have a problem with your vertices, as well as your colours. Stride should be 0 for both glVertexPointer and glColorPointer given your structures.

Iceman,

The pictures seem to show several bands of color. Are you sure the color calculations are correct and do not need a scale-factor in the z direction (which from the pictures I see seems to run from left to right)?

HTH

Jean-Marc

knackered - stride is the offset between consecutive vertices (it’s not a space between vertices), so putting sizeof(Vertex) will work fine, as his Vertex object is just 3 floats.

Setting the stride to 0 is also good, and a little easier to read (don’t have to check the size of Vertex to understand it).

maular

[This message has been edited by maular (edited 02-21-2002).]

No, sorry maular, but you’re wrong on this one.
Stride is the gap (in bytes) between n floats. A zero stride means no gap.
Check the docs if you don’t believe me.

stride
The byte offset between consecutive vertices. When stride is zero, the vertices are tightly packed in the array.

You’ve already told gl how many bytes your vertex takes up with the first 2 arguments to glVertexPointer(3, GL_FLOAT…
The stride byte count will be added onto the vertex pointer AFTER the 3 floats have been accounted for.

Or maybe I’m wrong. I’ve never tested it. I’ve always worked with tightly packed arrays.

[This message has been edited by knackered (edited 02-21-2002).]

From the spec:
The values within each array element are stored sequentially in memory. If stride is specified as zero, then array elements are stored sequentially as well. Otherwise pointers to the ith and (i+1)st elements of an array differ by stride basic machine units (typically unsigned bytes), the pointer to the (i + 1)st element being greater.

Setting stride=0 is valid only if your data is tightly packed, whereas stride=sizeof(Vertex) works all the time. I personally prefer the latter.

Anyway, back to the problem at hand. Iceman, your vertex array setup code looks correct, but you could try rendering everything in immediate mode (glVertex3f, glColor4f) to rule out problems in that part of the code.

– Tom

knackered, it’s very easy to try. Use the following vertex array (pseudo array)

float va = {x0, y0, z0, 0, 0, x1, y1, z1, 0, 0, x2, y2, z2, 0, 0};

Where x0 to z2 is some coordinates for a triangle, and the zeros are dummy elements. Try set that one up with a stride of 8 (2 * sizeof float). It should work better with a stride of 20 (5 * sizeof float), which is the distance from the beginning of one vertex to the beginning of the next vertex.

Stride = 0 is only a special case.

Oh right, cheers. Sorry iceman and maular - talking out of my arse again.

hello,

void Renderer::initialize()
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3,GL_FLOAT,sizeof (Vertex),vertices);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4,GL_FLOAT,sizeof(Color),colors);
}
I think (not remember correctly, that you may have an error here), just a suspicion.

Do you tell opengl to use RGBA colors, or does it use RGB colors ?
just in the case where…

anyway, good luck

jide

[QUOTE]Originally posted by Iceman:

Renderer(
unsigned int vCount,
unsigned int fCount,
> Vertex* v,
> Color* v,
IndexFace* f
)
{
vertices = v;
colors = c;
faces = f;
vertexCount = vCount;
faceCount = fCount;
}

Maybe doesn’t fix your problem, but you seem to have some variables with the same name. (or was it a typo when copying code?)

Originally posted by JML:
Iceman,
The pictures seem to show several bands of color. Are you sure the color calculations are correct and do not need a scale-factor in the z direction (which from the pictures I see seems to run from left to right)?
HTH
Jean-Marc

The color scheme is a pseudo-color mapping that I have been using for years (code tested many times). Using a linear interpolation and the extreme values of Z, I compute the slope and intercept of a function that maps the z values onto the range [0, 255]. The color mapping function simply takes that mapping and uses it as an index into an array of colors. The colors range from blue->cyan->green->yellow->red. An example of its use can be found at the following URL which shows the project that I am trying to adapt to use vertex arrays …
http://www.magnacom-inc.com/pleopard/Gallery/DGNView5Snaps/Snapshot02.jpg

Thanks!
Paul

BTW:
Iceman = PLeopard @ Home
PLeopard = Iceman @ Work

Originally posted by jide:
[b]hello,

void Renderer::initialize()
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3,GL_FLOAT,sizeof (Vertex),vertices);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4,GL_FLOAT,sizeof(Color),colors);
}
I think (not remember correctly, that you may have an error here), just a suspicion.

Do you tell opengl to use RGBA colors, or does it use RGB colors ?
just in the case where…

anyway, good luck

jide[/b]

RGBA is enabled

Originally posted by seu:
[b][QUOTE]Originally posted by Iceman:

Renderer(
unsigned int vCount,
unsigned int fCount,
> Vertex* v,
> Color* v,
IndexFace* f
)
{
vertices = v;
colors = c;
faces = f;
vertexCount = vCount;
faceCount = fCount;
}

Maybe doesn’t fix your problem, but you seem to have some variables with the same name. (or was it a typo when copying code?)

[/b]

Not an error, that is a C++ method called a constructor and it is initializing the class pointers to the external vertex arrays.

Iceman,

I get the idea of using a ‘rainbow’ mapping between 0.0 and 1.0 (or some other range); I use that myself. It’s just that from the pictures you posted it looked to me as if there were multiple wraps across the range…

And as to seu’s comment on your constructor:

[quote]

Renderer(
unsigned int vCount,
unsigned int fCount,
> Vertex* v,
> Color* v,
IndexFace* f
)

[/QUOTE]

You DO have a typo here, the line ‘Color* v,’ should read ‘Color *c,’ IMHO.

HTH

Jean-Marc

Oops, my apologies … I was in a hurry and missed that typo … thx for pointing that out.

JML the z values are the altitude of the points on the terrain mesh. Referring to the God’s eye view (pic #2), X runs down and Y runs from left to right. I see the bands you speak of but I do not quite understand what you mean about scaling in the [Y] direction. The X and Y values are not used in the color calculation at all. First I check the Z value of each vertex and find the minimum and maximum elevations, then I compute a linear function to map the range [zMin, zMax] onto the range [0,255]. Next I create the color array of equal size to the vertex array. Each color array element corresponds to the same indexed vertex in the vertex array. I loop through the vertex array, taking each vertex’s z value and applying the mapping function to it to get an index into my color table. I pass that index to my color table class and it hands me back the appropriate RGBA values for the vertex.

I may be pointing out the obvious here – but when using floats for rgba, they should be range 0…1 – only use 0…255 for type UNSIGNED_BYTE, or you will get mostly white except for the odd vertex where r, g, or b was <= 1.0f/255…

That’s not it, the elevation values are used to compute an index in the range [0,255] and that index is used in my color table to get the rgba values in the range [0,1].

Thx tho …

i just did this like 5 minutes ago… and i was just going to ask about performance for texture map verses vertex coloring. anyhow i’m fairly certain that setting the stride to size of your structure will make the vertext array skip every other object. i did get mine to work btw. eventhough the first time i got a really cool striated rainbow effect cause my colors weren’t computed proper. make sure you are computing your colors right. sounds like you are basing it on height in an heat scale format. so just make sure you are computing your colors right pending your y component of the vertex and set the stride to zero and it should work Aok. can be tricky squeezing the color values inbetween unity and 0 or 0-255 in my case. one trick is to know the y-range of your function and just divide your y-component by that value to get the percentage, that will get it between 0 and 1. then you can multiply it by a value between 0-255, and type cast it unsigned char. that is the simplest way it can be more complicated if that heuristic won’t do. that is probably the trickiest part and probably where the wrench in your algorithm is lodged maybe.

hope that helped

Michael