X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffg_geometry.c;h=12d1035e93311f5cd3d59273cf5dbbac61f0d408;hb=6bb70a51b03902c66ab3891f159c99485b6c8ca9;hp=066a0d35478d4a93ddb810937c0b59a6f8719f69;hpb=ea5dc8a10beb55cd972c34d6b531158101b6773f;p=freeglut diff --git a/src/fg_geometry.c b/src/fg_geometry.c index 066a0d3..12d1035 100644 --- a/src/fg_geometry.c +++ b/src/fg_geometry.c @@ -30,6 +30,18 @@ #include "fg_gl2.h" #include +/* + * A note: We do not use the GLuint data type for vertex index arrays + * in this code as Open GL ES1 only supports GLushort. This affects the + * cylindrical objects only (Torus, Sphere, Cylinder and Cone) and limits + * their number of vertices to 65535 (2^16-1). Thats about 256*256 + * subdivisions, which is sufficient for just about any usage case, so + * I am not going to worry about it for now. + * One could do compile time detection of the gluint type through CMake, + * but it is likely that we'll eventually move to runtime selection + * of OpenGL or GLES1/2, which would make that strategy useless... + */ + /* declare for drawing using the different OpenGL versions here so we can have a nice code order below */ #ifndef GL_ES_VERSION_2_0 @@ -51,7 +63,10 @@ static void fghDrawGeometrySolid20(GLfloat *vertices, GLfloat *normals, GLsizei /* declare function for generating visualization of normals */ static void fghGenerateNormalVisualization(GLfloat *vertices, GLfloat *normals, GLsizei numVertices, GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart); -static void fghDrawNormalVisualization(); +#ifndef GL_ES_VERSION_2_0 +static void fghDrawNormalVisualization11(); +#endif +static void fghDrawNormalVisualization20(GLint attribute_v_coord); /* Drawing geometry: * Explanation of the functions has to be separate for the polyhedra and @@ -173,11 +188,22 @@ static void fghDrawGeometrySolid(GLfloat *vertices, GLfloat *normals, GLsizei nu GLint attribute_v_coord = fgStructure.CurrentWindow->Window.attribute_v_coord; GLint attribute_v_normal = fgStructure.CurrentWindow->Window.attribute_v_normal; + if (fgStructure.CurrentWindow->State.VisualizeNormals) + /* generate normals for each vertex to be drawn as well */ + fghGenerateNormalVisualization(vertices, normals, numVertices, + vertIdxs, numParts, numVertIdxsPerPart); + if (fgState.HasOpenGL20 && (attribute_v_coord != -1 || attribute_v_normal != -1)) + { /* User requested a 2.0 draw */ fghDrawGeometrySolid20(vertices, normals, numVertices, vertIdxs, numParts, numVertIdxsPerPart, attribute_v_coord, attribute_v_normal); + + if (fgStructure.CurrentWindow->State.VisualizeNormals) + /* draw normals for each vertex as well */ + fghDrawNormalVisualization20(attribute_v_coord); + } #ifndef GL_ES_VERSION_2_0 else { @@ -185,13 +211,8 @@ static void fghDrawGeometrySolid(GLfloat *vertices, GLfloat *normals, GLsizei nu vertIdxs, numParts, numVertIdxsPerPart); if (fgStructure.CurrentWindow->State.VisualizeNormals) - { - /* generate normals for each vertex to be drawn as well */ - fghGenerateNormalVisualization(vertices, normals, numVertices, - vertIdxs, numParts, numVertIdxsPerPart); /* draw normals for each vertex as well */ - fghDrawNormalVisualization(); - } + fghDrawNormalVisualization11(); } #endif } @@ -469,8 +490,8 @@ static void fghGenerateNormalVisualization(GLfloat *vertices, GLfloat *normals, GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart) { GLushort i,j; - /* calc number of vertices to generate, allocate. TODO: FREE again after draw! - * two for each vertex in the input shape + /* calc number of vertices to generate, allocate. Must be freed by caller + * We do the free at the end of fghDrawNormalVisualization11/fghDrawNormalVisualization20 */ if (!vertIdxs) numNormalVertices = numVertices * 2; @@ -506,7 +527,9 @@ static void fghGenerateNormalVisualization(GLfloat *vertices, GLfloat *normals, } } -static void fghDrawNormalVisualization() +/* Version for OpenGL (ES) 1.1 */ +#ifndef GL_ES_VERSION_2_0 +static void fghDrawNormalVisualization11() { GLfloat currentColor[4]; /* Setup draw color: (1,1,1)-shape's color */ @@ -524,6 +547,46 @@ static void fghDrawNormalVisualization() free(verticesForNormalVisualization); glColor4fv(currentColor); } +#endif + +/* Version for OpenGL (ES) >= 2.0 */ +static void fghDrawNormalVisualization20(GLint attribute_v_coord) +{ + GLuint vbo_coords = 0; + + if (attribute_v_coord != -1) { + fghGenBuffers(1, &vbo_coords); + fghBindBuffer(FGH_ARRAY_BUFFER, vbo_coords); + fghBufferData(FGH_ARRAY_BUFFER, numNormalVertices * 3 * sizeof(verticesForNormalVisualization[0]), + verticesForNormalVisualization, FGH_STATIC_DRAW); + } + + + if (vbo_coords) { + fghEnableVertexAttribArray(attribute_v_coord); + fghBindBuffer(FGH_ARRAY_BUFFER, vbo_coords); + fghVertexAttribPointer( + attribute_v_coord, /* attribute */ + 3, /* number of elements per vertex, here (x,y,z) */ + GL_FLOAT, /* the type of each element */ + GL_FALSE, /* take our values as-is */ + 0, /* no extra data between each position */ + 0 /* offset of first element */ + ); + fghBindBuffer(FGH_ARRAY_BUFFER, 0); + } + + glDrawArrays(GL_LINES, 0, numNormalVertices); + + if (vbo_coords != 0) + fghDisableVertexAttribArray(attribute_v_coord); + + if (vbo_coords != 0) + fghDeleteBuffers(1, &vbo_coords); + + /* Done, free memory */ + free(verticesForNormalVisualization); +} /** * Generate all combinations of vertices and normals needed to draw object. @@ -600,7 +663,7 @@ static void fghGenerateGeometry(int numFaces, int numEdgePerFace, GLfloat *verti * vertices and normals are unique. */ #define DECLARE_SHAPE_CACHE(name,nameICaps,nameCaps)\ - static GLboolean name##Cached = FALSE;\ + static GLboolean name##Cached = GL_FALSE;\ static GLfloat name##_verts[nameCaps##_VERT_ELEM_PER_OBJ];\ static GLfloat name##_norms[nameCaps##_VERT_ELEM_PER_OBJ];\ static void fgh##nameICaps##Generate()\ @@ -610,7 +673,7 @@ static void fghGenerateGeometry(int numFaces, int numEdgePerFace, GLfloat *verti name##_verts, name##_norms);\ } #define DECLARE_SHAPE_CACHE_DECOMPOSE_TO_TRIANGLE(name,nameICaps,nameCaps)\ - static GLboolean name##Cached = FALSE;\ + static GLboolean name##Cached = GL_FALSE;\ static GLfloat name##_verts[nameCaps##_VERT_ELEM_PER_OBJ];\ static GLfloat name##_norms[nameCaps##_VERT_ELEM_PER_OBJ];\ static GLushort name##_vertIdxs[nameCaps##_VERT_PER_OBJ_TRI];\ @@ -1104,15 +1167,13 @@ static void fghGenerateSphere(GLfloat radius, GLint slices, GLint stacks, GLfloa *nVert = slices*(stacks-1)+2; if ((*nVert) > 65535) /* - * limit of glushort, thats 256*256 subdivisions, should be enough in practice. - * But still: - * TODO: must have a better solution than this low limit, at least for architectures where gluint is available + * limit of glushort, thats 256*256 subdivisions, should be enough in practice. See note above */ fgWarning("fghGenerateSphere: too many slices or stacks requested, indices will wrap"); /* precompute values on unit circle */ - fghCircleTable(&sint1,&cost1,-slices,FALSE); - fghCircleTable(&sint2,&cost2, stacks,TRUE); + fghCircleTable(&sint1,&cost1,-slices,GL_FALSE); + fghCircleTable(&sint2,&cost2, stacks,GL_TRUE); /* Allocate vertex and normal buffers, bail out if memory allocation fails */ *vertices = malloc((*nVert)*3*sizeof(GLfloat)); @@ -1201,14 +1262,12 @@ void fghGenerateCone( if ((*nVert) > 65535) /* - * limit of glushort, thats 256*256 subdivisions, should be enough in practice. - * But still: - * TODO: must have a better solution than this low limit, at least for architectures where gluint is available + * limit of glushort, thats 256*256 subdivisions, should be enough in practice. See note above */ fgWarning("fghGenerateCone: too many slices or stacks requested, indices will wrap"); /* Pre-computed circle */ - fghCircleTable(&sint,&cost,-slices,FALSE); + fghCircleTable(&sint,&cost,-slices,GL_FALSE); /* Allocate vertex and normal buffers, bail out if memory allocation fails */ *vertices = malloc((*nVert)*3*sizeof(GLfloat)); @@ -1247,9 +1306,9 @@ void fghGenerateCone( (*vertices)[idx ] = cost[j]*r; (*vertices)[idx+1] = sint[j]*r; (*vertices)[idx+2] = z; - (*normals )[idx ] = cost[j]*sinn; - (*normals )[idx+1] = sint[j]*sinn; - (*normals )[idx+2] = cosn; + (*normals )[idx ] = cost[j]*cosn; + (*normals )[idx+1] = sint[j]*cosn; + (*normals )[idx+2] = sinn; } z += zStep; @@ -1288,14 +1347,12 @@ void fghGenerateCylinder( if ((*nVert) > 65535) /* - * limit of glushort, thats 256*256 subdivisions, should be enough in practice. - * But still: - * TODO: must have a better solution than this low limit, at least for architectures where gluint is available + * limit of glushort, thats 256*256 subdivisions, should be enough in practice. See note above */ fgWarning("fghGenerateCylinder: too many slices or stacks requested, indices will wrap"); /* Pre-computed circle */ - fghCircleTable(&sint,&cost,-slices,FALSE); + fghCircleTable(&sint,&cost,-slices,GL_FALSE); /* Allocate vertex and normal buffers, bail out if memory allocation fails */ *vertices = malloc((*nVert)*3*sizeof(GLfloat)); @@ -1392,15 +1449,13 @@ void fghGenerateTorus( if ((*nVert) > 65535) /* - * limit of glushort, thats 256*256 subdivisions, should be enough in practice. - * But still: - * TODO: must have a better solution than this low limit, at least for architectures where gluint is available + * limit of glushort, thats 256*256 subdivisions, should be enough in practice. See note above */ fgWarning("fghGenerateTorus: too many slices or stacks requested, indices will wrap"); /* precompute values on unit circle */ - fghCircleTable(&spsi,&cpsi, nRings,FALSE); - fghCircleTable(&sphi,&cphi,-nSides,FALSE); + fghCircleTable(&spsi,&cpsi, nRings,GL_FALSE); + fghCircleTable(&sphi,&cphi,-nSides,GL_FALSE); /* Allocate vertex and normal buffers, bail out if memory allocation fails */ *vertices = malloc((*nVert)*3*sizeof(GLfloat)); @@ -2007,7 +2062,7 @@ static void fghTorus( GLfloat dInnerRadius, GLfloat dOuterRadius, GLint nSides, void FGAPIENTRY glutSolidSphere(double radius, GLint slices, GLint stacks) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidSphere" ); - fghSphere((GLfloat)radius, slices, stacks, FALSE ); + fghSphere((GLfloat)radius, slices, stacks, GL_FALSE ); } /* @@ -2016,7 +2071,7 @@ void FGAPIENTRY glutSolidSphere(double radius, GLint slices, GLint stacks) void FGAPIENTRY glutWireSphere(double radius, GLint slices, GLint stacks) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireSphere" ); - fghSphere((GLfloat)radius, slices, stacks, TRUE ); + fghSphere((GLfloat)radius, slices, stacks, GL_TRUE ); } @@ -2026,7 +2081,7 @@ void FGAPIENTRY glutWireSphere(double radius, GLint slices, GLint stacks) void FGAPIENTRY glutSolidCone( double base, double height, GLint slices, GLint stacks ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidCone" ); - fghCone((GLfloat)base, (GLfloat)height, slices, stacks, FALSE ); + fghCone((GLfloat)base, (GLfloat)height, slices, stacks, GL_FALSE ); } /* @@ -2035,7 +2090,7 @@ void FGAPIENTRY glutSolidCone( double base, double height, GLint slices, GLint s void FGAPIENTRY glutWireCone( double base, double height, GLint slices, GLint stacks) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireCone" ); - fghCone((GLfloat)base, (GLfloat)height, slices, stacks, TRUE ); + fghCone((GLfloat)base, (GLfloat)height, slices, stacks, GL_TRUE ); } @@ -2045,7 +2100,7 @@ void FGAPIENTRY glutWireCone( double base, double height, GLint slices, GLint st void FGAPIENTRY glutSolidCylinder(double radius, double height, GLint slices, GLint stacks) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidCylinder" ); - fghCylinder((GLfloat)radius, (GLfloat)height, slices, stacks, FALSE ); + fghCylinder((GLfloat)radius, (GLfloat)height, slices, stacks, GL_FALSE ); } /* @@ -2054,7 +2109,7 @@ void FGAPIENTRY glutSolidCylinder(double radius, double height, GLint slices, GL void FGAPIENTRY glutWireCylinder(double radius, double height, GLint slices, GLint stacks) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireCylinder" ); - fghCylinder((GLfloat)radius, (GLfloat)height, slices, stacks, TRUE ); + fghCylinder((GLfloat)radius, (GLfloat)height, slices, stacks, GL_TRUE ); } /* @@ -2063,7 +2118,7 @@ void FGAPIENTRY glutWireCylinder(double radius, double height, GLint slices, GLi void FGAPIENTRY glutWireTorus( double dInnerRadius, double dOuterRadius, GLint nSides, GLint nRings ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireTorus" ); - fghTorus((GLfloat)dInnerRadius, (GLfloat)dOuterRadius, nSides, nRings, TRUE); + fghTorus((GLfloat)dInnerRadius, (GLfloat)dOuterRadius, nSides, nRings, GL_TRUE); } /* @@ -2072,7 +2127,7 @@ void FGAPIENTRY glutWireTorus( double dInnerRadius, double dOuterRadius, GLint n void FGAPIENTRY glutSolidTorus( double dInnerRadius, double dOuterRadius, GLint nSides, GLint nRings ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidTorus" ); - fghTorus((GLfloat)dInnerRadius, (GLfloat)dOuterRadius, nSides, nRings, FALSE); + fghTorus((GLfloat)dInnerRadius, (GLfloat)dOuterRadius, nSides, nRings, GL_FALSE); } @@ -2083,23 +2138,23 @@ void FGAPIENTRY glutSolidTorus( double dInnerRadius, double dOuterRadius, GLint void FGAPIENTRY glutWire##nameICaps( void )\ {\ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWire"#nameICaps );\ - fgh##nameICaps( TRUE );\ + fgh##nameICaps( GL_TRUE );\ }\ void FGAPIENTRY glutSolid##nameICaps( void )\ {\ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolid"#nameICaps );\ - fgh##nameICaps( FALSE );\ + fgh##nameICaps( GL_FALSE );\ } void FGAPIENTRY glutWireCube( double dSize ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireCube" ); - fghCube( (GLfloat)dSize, TRUE ); + fghCube( (GLfloat)dSize, GL_TRUE ); } void FGAPIENTRY glutSolidCube( double dSize ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidCube" ); - fghCube( (GLfloat)dSize, FALSE ); + fghCube( (GLfloat)dSize, GL_FALSE ); } DECLARE_SHAPE_INTERFACE(Dodecahedron) @@ -2110,12 +2165,12 @@ DECLARE_SHAPE_INTERFACE(RhombicDodecahedron) void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, double offset[3], double scale ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireSierpinskiSponge" ); - fghSierpinskiSponge ( num_levels, offset, (GLfloat)scale, TRUE ); + fghSierpinskiSponge ( num_levels, offset, (GLfloat)scale, GL_TRUE ); } void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, double offset[3], double scale ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidSierpinskiSponge" ); - fghSierpinskiSponge ( num_levels, offset, (GLfloat)scale, FALSE ); + fghSierpinskiSponge ( num_levels, offset, (GLfloat)scale, GL_FALSE ); } DECLARE_SHAPE_INTERFACE(Tetrahedron)