Generate a plane with triangle strips
Thanks you all. I've coded this. Is it correct? Or is the generated strip somehow wrong?
int width;
int height;
float* vertices = 0;
int* indices = 0;
int getVerticesCount( int width, int height ) {
return width * height * 3;
}
int getIndicesCount( int width, int height ) {
return (width*height) + (width-1)*(height-2);
}
float* getVertices( int width, int height ) {
if ( vertices ) return vertices;
vertices = new float[ getVerticesCount( width, height ) ];
int i = 0;
for ( int row=0; row<height; row++ ) {
for ( int col=0; col<width; col++ ) {
vertices[i++] = (float) col;
vertices[i++] = 0.0f;
vertices[i++] = (float) row;
}
}
return vertices;
}
int* getIndices( int width, int height ) {
if ( indices ) return indices;
indices = new int[ iSize ];
int i = 0;
for ( int row=0; row<height-1; row++ ) {
if ( (row&1)==0 ) { // even rows
for ( int col=0; col<width; col++ ) {
indices[i++] = col + row * width;
indices[i++] = col + (row+1) * width;
}
} else { // odd rows
for ( int col=width-1; col>0; col-- ) {
indices[i++] = col + (row+1) * width;
indices[i++] = col - 1 + + row * width;
}
}
}
if ( (mHeight&1) && mHeight>2 ) {
mpIndices[i++] = (mHeight-1) * mWidth;
}
return indices;
}
void render() {
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, GL_FLOAT, 0, getVertices(width,height) );
glDrawElements( GL_TRIANGLE_STRIP, getIndicesCount(width,height), GL_UNSIGNED_INT, getIndices(width,height) );
glDisableClientState( GL_VERTEX_ARRAY );
}
With width=4 and height=4 this is what I got:
And here I'm modifying some vertex height:
Creating plane with triangular strips
For me, this looks like the triangles, that are produced by the triangle-strip to "jump back" to the left side. This happens whenever you start a new row. Basically, they consist of the last-vertices of the previous row and the first vertices of the next row. Backface culling seems to work, but the large triangles are visible from the back because their winding order is exactly opposite to the one of the small triangles.
If you don't want to have them, you either have to reset the triangle-strip at the end of each row, or use another structure (GL_TRIANGLES).
Convert triangle strips to Octagonal?
Use the polygon rasterization mode GL_LINE
to render a wire frame:
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
float xPos = 0.0f;
float yPos = 0.0f;
float radius = 0.5f;
int steps = 8;
float prevX = xPos;
float prevY = yPos - radius;
glBegin(GL_TRIANGLES);
glColor3f(0.0f, 0.5f, 0.0f);
for (int i=0; i <= step; ++i)
{
float angle = 3.1415926f * 2.0f * i / step;
float newX = radius * sin(angle);
float newY = - radius * cos(angle);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(prevX, prevY, 0.0f);
glVertex3f(newX, newY, 0.0f);
prevX = newX;
prevY = newY;
}
glEnd();
Use a GL_TRIANGLE_FAN
Triangle primitive to simplify your code:
glBegin(GL_TRIANGLE_FAN);
glColor3f(0.0f, 0.5f, 0.0f);
for (int i=0; i <= step; ++i)
{
float angle = 3.1415926f * 2.0f * i / step;
float newX = radius * sin(angle);
float newY = - radius * cos(angle);
glVertex3f(newX, newY, 0.0f);
}
glEnd();
If you want to use a triangle GL_TRIANGLE_STRIP
, you must change the order of the vertices:
glBegin(GL_TRIANGLE_STRIP);
glColor3f(0.0f, 0.5f, 0.0f);
for (int i=0; i <= step; ++i)
{
int strip_i = i % 2 == 0 ? i/2 : step - i/2;
float angle = 3.1415926f * 2.0f * strip_i / step;
float newX = radius * sin(angle);
float newY = - radius * cos(angle);
glVertex3f(newX, newY, 0.0f);
}
glEnd();
If you want to render the wire frame on top of the polygon, you need to enable the depth test and render the polygon first. Note the default depth test function is GL_LESS
:
for (int pass = 0; pass < 2; ++pass)
{
if (pass == 0)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glColor3f(1.0f, 1.0f, 1.0f);
}
else
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glColor3f(0.0f, 0.5f, 0.0f);
}
glBegin(GL_TRIANGLE_STRIP);
for (int i=0; i <= step; ++i)
{
int strip_i = i % 2 == 0 ? i/2 : step - i/2;
float angle = 3.1415926f * 2.0f * strip_i / step;
float newX = radius * sin(angle);
float newY = - radius * cos(angle);
glVertex3f(newX, newY, 0.0f);
}
glEnd();
}
Issues with making an OpenGL plane out of triangles
I realised that vertices were being created from bottom to top and indices were ordered to create triangles from top to bottom. So I changed the vertex creation for loop.
int index = 0;
for (int y = height; y >= 0; y--)
{
for (int x = 0; x <= width; x++)
{
vertices[index] = ((float)x/4)-0.5;
vertices[index +1] = ((float)y/4)-0.5;
vertices[index + 2] = 0.0f;
index += 3;
}
}
It creates the vertices from top left to right bottom. Loop for the indices stayed the same:
int i = 0;
++width;
GLuint indices2[170] = { 0 };
for (int y = 0; y < height; y++)
{
int base = y * width;
for (int x = 0; x < width; x++)
{
indices[i++] = base + x;
indices[i++] = base + width + x;
}
if (y < height - 1)
{
indices[i++] = ((y + 1) * width + (width - 1));
indices[i++] = ((y + 1) * width);
}
}
Related Topics
The Fastest Way to Retrieve 16K Key-Value Pairs
Line by Line C - C++ Code Debugging in Linux Ubuntu
String-Interning at Compiletime for Profiling
Error Lnk2019 Unresolved External Symbol
How to Check If Std::Map Contains a Key Without Doing Insert
Knight's Tour Backtrack Implementation Choosing the Step Array
Why Emplace_Back Is Faster Than Push_Back
What Are Consequences of Forcing Qobject as a Parent of Qwidget
Dereferencing One Past the End Pointer to Array Type
Avoiding If Statement Inside a for Loop
How to Treat a Specific Warning as an Error
Explicitly Initialize Dword to 1, But Debugger Shows Wildly Out of Range Value
When to Use Template VS Inheritance
Why How to Define Structures and Classes Within a Function in C++