I'm currently using opengl to draw a several thousand polygons and it's running very slow. It takes apx 100 ms to draw 8000 polygons.
Here is some info about my set-up:
I'm currently drawing as follows:
for(allPlanes){
glBegin(GL_POLYGON);
for(allPointsInThePlane){
glVertex(pointX,pointY,pointZ);
}
glEnd();
}
This is much slower than I expected and I have looked into using glDrawElements() instead and breaking the polygon planes into triangles and using trianglefans or strips to draw them.
Im just looking for some advice on the most efficient way to do this, or any criticism on the way I'm approaching the drawing.
Triangulate everything and toss the triangles into a big VA/VBO.
EDIT: GLUtesselator wrapper:
struct TessContext
{
~TessContext()
{
for( size_t i = 0; i < combined.size(); ++i )
{
delete[] combined[i];
}
}
vector< Eigen::Vector2d > pts;
vector< GLdouble* > combined;
};
#define APIENTRY __stdcall
void APIENTRY tess_begin( GLenum type ) {}
void APIENTRY tess_edgeFlag( GLboolean flag ) {}
void APIENTRY tess_end() {}
void APIENTRY tess_vertex( void *data, TessContext* ctx )
{
GLdouble* coord = (GLdouble*)data;
ctx->pts.push_back( Eigen::Vector2d( coord[0], coord[1] ) );
}
void APIENTRY tess_combine( GLdouble coords[3], void *vertex_data[4], GLfloat weight[4], void **outData, TessContext* ctx )
{
GLdouble* newVert = new GLdouble[3];
ctx->combined.push_back( newVert );
newVert[0] = coords[0];
newVert[1] = coords[1];
newVert[2] = coords[2];
*outData = newVert;
}
template< typename Vec >
vector< Vec > Triangulate
(
const vector< Vec >& aSimplePolygon
)
{
vector< GLdouble > coords;
for( size_t i = 0; i < aSimplePolygon.size(); ++i )
{
coords.push_back( aSimplePolygon[i].x() );
coords.push_back( aSimplePolygon[i].y() );
coords.push_back( 0 );
}
GLUtesselator* tess = gluNewTess();
//gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD );
//gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO );
gluTessCallback( tess, GLU_TESS_BEGIN, (GLvoid (APIENTRY *)()) tess_begin );
gluTessCallback( tess, GLU_TESS_EDGE_FLAG, (GLvoid (APIENTRY *)()) tess_edgeFlag );
gluTessCallback( tess, GLU_TESS_VERTEX_DATA, (GLvoid (APIENTRY *)()) tess_vertex );
gluTessCallback( tess, GLU_TESS_END, (GLvoid (APIENTRY *)()) tess_end );
gluTessCallback( tess, GLU_TESS_COMBINE_DATA, (GLvoid (APIENTRY *)()) tess_combine );
gluTessNormal( tess, 0.0, 0.0, 1.0 );
TessContext ctx;
gluTessBeginPolygon( tess, &ctx );
gluTessBeginContour( tess );
for( size_t i = 0; i < aSimplePolygon.size(); ++i )
{
gluTessVertex( tess, &coords[i*3], &coords[i*3] );
}
gluTessEndContour( tess );
gluTessEndPolygon( tess );
gluDeleteTess(tess);
vector< Vec > ret( ctx.pts.size() );
for( size_t i = 0; i < ret.size(); ++i )
{
ret[i].x() = ctx.pts[i].x();
ret[i].y() = ctx.pts[i].y();
}
return ret;
}
Uses Eigen but not for anything interesting.
glDrawArrays() or glDrawElements() (or glDrawRangeElements()) are the preferred way, and also the only non-deprecated one. Immediate mode (your example) is the slowest and the least preferred method, useful mostly for OpenGL tutorials and (in my own experience) debugging. There are also display lists
, "macros" for OpenGL that are only one step above using the immediate mode for drawing, and vertex buffer objects (VBOs)
.
Any, except the immediate mode, should be sufficiently fast for your needs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With