PDA

View Full Version : LINE_STIPPLE problem



TEWarehouse
12-16-2012, 12:57 PM
I am drawing an array of lines.

I have some lines that need to be stippled and the rest just regular lines.

Im doing something like this (i just hand coded this obviously)

while(thereAreLines)
{

glbegin(lines)

//draw lines

glend()

glbegin

glenable stipple

//draw stipple lines

gldisable stipple

glend()
}

swapBuffer(my_openGL)


If i comment out the enable stipple part then the program runs just fine just without my stippled lines....

If i leave the enable stipple in there, then it draws everything just fine but crashes....

Im using VC++ 6.0 over a remote desktop connection. Im assuming its crashing my laptop video card and not able to do much debugging. i won't have access to the main PC till after the new year. I can't seem to get any debug info. At the office it was giving me some kind of nVidia errors... I can't remember what the error was because i was working on other parts of the software at the time.

Aestivae
12-17-2012, 04:06 PM
As far as I know, the problem is that you can't glEnable(GL_LINE_STIPPLE) inside of a glBegin()/glEnd() block. In immediate mode OpenGL doesn't like it much when you do anything except pass specific drawing commands.

TEWarehouse
12-18-2012, 09:14 AM
As far as I know, the problem is that you can't glEnable(GL_LINE_STIPPLE) inside of a glBegin()/glEnd() block. In immediate mode OpenGL doesn't like it much when you do anything except pass specific drawing commands.

Besides that, is there a problem with calling the glBegin/glEnd say 6000 times? Otherwise, is there another way with doing the line stipple? I have thousands of lines to draw all in an array and a lot of them need to be stippled.

Aestivae
12-18-2012, 10:18 AM
There's no reason you should call glBegin()/glEnd() that many times. OpenGL is a state machine at heart; when you call glBegin(GL_LINES) you go into immediate mode, where all subsequent calls are interpreted accordingly until glEnd(). In your case, if you must use immediate mode, you need to place your for loop inside glBegin() and glEnd().

I don't have any definite reference to point you to, but generally it's not good to call any OpenGL functions more than a few hundred times per frame, since each call takes some CPU time and some bus transfer time. The point of OpenGL is hardware acceleration, so too many OpenGL function calls defeats the purpose, since it occupies the CPU.

I'm bad at explaining in words, so I'll write code. You can do it somewhat like this (I'm assuming a lot of things, like orthographic projection). Unfortunately the closest thing I can write to C++ is C89, so please bear with me.


// Given line data in the following struct
typedef struct {
int x0;
int y0;
int x1;
int y1;
char stippled; // Functions as a boolean, 1 true, 0 false
} line;


// Given an array of lines "lines" and length "length"
int i;
glBegin(GL_LINES);
for (i = 0; i < length; i++) {
if (lines[i].stippled == 0) {
glVertex2f(lines[i].x0, lines[i].y0); // Each pair of vertices is interpreted as the beginning and end of a line,
glVertex2f(lines[i].x1, lines[i].y1); // so you can give OpenGL multiple pairs in each block
}
}
glEnd();

glEnable(GL_LINE_STIPPLE);
// Do the glBegin()/glEnd() block + for loop again but testing for stipple flag
glDisable(GL_LINE_STIPPLE);

Of course, this way requires two semi-redundant passes, but since you can't enable stipple from inside a glBegin()/glEnd() block, it's pretty much the only immediate mode approach (assuming I guessed your structure correctly).

However, a better way to do it would require restructuring your data. Separate the stippled lines from the regular lines, and make a primitive (probably float) array for each where (assuming lines from 0 to 1, 2 to 3, etc):


{x0, y0, x1, y1, x2, y2, x3, y3, ...}

Then draw it with vertex arrays:


// Given float arrays "stippled" and "not_stippled" with lengths "length_s" and "length_n" respectively
glEnableClientState(GL_VERTEX_ARRAY);

glVertexPointer(2, GL_FLOAT, 0, not_stippled); // Where 2 is number of floats per vertex, GL_FLOAT is the type, and 0 is the "stride" (how many to skip between vertices)
glDrawArrays(GL_LINES, 0, length_n / 2); // Where GL_LINES is draw mode, 0 is start index, and length_s / 2 is how many vertices to draw

glEnable(GL_LINE_STIPPLE);
glVertexPointer(2, GL_FLOAT, 0, stippled);
glDrawArrays(GL_LINES, 0, length_s / 2);
glDisable(GL_LINE_STIPPLE);


You could take a step further and use VBOs, but I've gone on long enough... I'll leave that to you to figure out, I suppose ;)