From 9634525a2e112501938d7cc5c48ce75f8b975a38 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Fri, 16 Mar 2012 00:40:15 +0000 Subject: [PATCH] initial start at rewrite of fg_geometry functions, using glDrawArrays. Tetrahedon done as example (seems to work well, but further comments pending) Done restructuring of the file as well git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@1143 7f0cb862-5218-0410-a997-914c9d46530a --- src/fg_geometry.c | 269 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 175 insertions(+), 94 deletions(-) diff --git a/src/fg_geometry.c b/src/fg_geometry.c index de1cbad..3a19a3b 100644 --- a/src/fg_geometry.c +++ b/src/fg_geometry.c @@ -31,6 +31,8 @@ /* * TODO BEFORE THE STABLE RELEASE: * + * See fghTetrahedron + * * Following functions have been contributed by Andreas Umbach. * * glutWireCube() -- looks OK @@ -59,58 +61,106 @@ */ -/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ - /* - * Draws a wireframed cube. Code contributed by Andreas Umbach + * General function for drawing geometry. As for all geometry we have no + * redundancy (or hardly any in the case of cones and cylinders) in terms + * of the vertex/normal combinations, we just use glDrawArrays. + * useWireMode controls the drawing of solids (false) or wire frame + * versions (TRUE) of the geometry you pass */ -void FGAPIENTRY glutWireCube( GLdouble dSize ) +static void fghDrawGeometry(GLenum vertexMode, double* vertices, double* normals, GLsizei numVertices, GLboolean useWireMode) { - double size = dSize * 0.5; + if (useWireMode) + { + glPushAttrib(GL_POLYGON_BIT); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireCube" ); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); -# define V(a,b,c) glVertex3d( a size, b size, c size ); -# define N(a,b,c) glNormal3d( a, b, c ); + glVertexPointer(3, GL_DOUBLE, 0, vertices); + glNormalPointer(GL_DOUBLE, 0, normals); + glDrawArrays(vertexMode,0,numVertices); - /* PWO: I dared to convert the code to use macros... */ - glBegin( GL_LINE_LOOP ); N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+); glEnd(); - glBegin( GL_LINE_LOOP ); N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+); glEnd(); - glBegin( GL_LINE_LOOP ); N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+); glEnd(); - glBegin( GL_LINE_LOOP ); N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-); glEnd(); - glBegin( GL_LINE_LOOP ); N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+); glEnd(); - glBegin( GL_LINE_LOOP ); N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-); glEnd(); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); -# undef V -# undef N + if (useWireMode) + { + glPopAttrib(); + } } -/* - * Draws a solid cube. Code contributed by Andreas Umbach - */ -void FGAPIENTRY glutSolidCube( GLdouble dSize ) -{ - double size = dSize * 0.5; - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidCube" ); +/* -- INTERNAL SETUP OF GEOMETRY --------------------------------------- */ +/* -- first the cachable ones -- */ -# define V(a,b,c) glVertex3d( a size, b size, c size ); -# define N(a,b,c) glNormal3d( a, b, c ); +/* Magic Numbers: r0 = ( 1, 0, 0 ) + * r1 = ( -1/3, 2 sqrt(2) / 3, 0 ) + * r2 = ( -1/3, - sqrt(2) / 3, sqrt(6) / 3 ) + * r3 = ( -1/3, - sqrt(2) / 3, -sqrt(6) / 3 ) + * |r0| = |r1| = |r2| = |r3| = 1 + * Distance between any two points is 2 sqrt(6) / 3 + * + * Normals: The unit normals are simply the negative of the coordinates of the point not on the surface. +*/ - /* PWO: Again, I dared to convert the code to use macros... */ - glBegin( GL_QUADS ); - N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+); - N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+); - N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+); - N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-); - N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+); - N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-); - glEnd(); +/* -- TetraHedron -- */ +#define TETR_NUM_FACES 4 +#define TETR_NUM_VERT_PER_FACE 3 -# undef V -# undef N +/* Vertex Coordinates */ +static GLdouble tet_r[TETR_NUM_FACES][TETR_NUM_VERT_PER_FACE] = +{ + { 1.0, 0.0, 0.0 }, + { -0.333333333333, 0.942809041582, 0.0 }, + { -0.333333333333, -0.471404520791, 0.816496580928 }, + { -0.333333333333, -0.471404520791, -0.816496580928 } +}; + +/* Vertex indices */ +static GLubyte tet_i[TETR_NUM_FACES][TETR_NUM_VERT_PER_FACE] = +{ + { 1, 3, 2 }, { 0, 2, 3 }, { 0, 3, 1 }, { 0, 1, 2 } +}; +/* Normal indices */ +static GLubyte tet_n[TETR_NUM_FACES] = +{ + 0, 1, 2, 3 +}; + +/* Cache of input to glDrawArrays */ +static GLboolean tetrCached = FALSE; +static double tetr_verts[TETR_NUM_FACES * TETR_NUM_VERT_PER_FACE * 3]; +static double tetr_norms[TETR_NUM_FACES * TETR_NUM_VERT_PER_FACE * 3]; + +static void fghTetrahedronCache() +{ + int p,q; + /* + * Build array with vertices from vertex coordinates and vertex indices + * Do same for normals. + * Need to do this because of different normals at shared vertices + * (and because normals' coordinates need to be negated). + */ + for (p=0; p + */ +void FGAPIENTRY glutWireCube( GLdouble dSize ) +{ + double size = dSize * 0.5; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireCube" ); + +# define V(a,b,c) glVertex3d( a size, b size, c size ); +# define N(a,b,c) glNormal3d( a, b, c ); + + /* PWO: I dared to convert the code to use macros... */ + glBegin( GL_LINE_LOOP ); N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+); glEnd(); + glBegin( GL_LINE_LOOP ); N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+); glEnd(); + glBegin( GL_LINE_LOOP ); N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+); glEnd(); + glBegin( GL_LINE_LOOP ); N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-); glEnd(); + glBegin( GL_LINE_LOOP ); N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+); glEnd(); + glBegin( GL_LINE_LOOP ); N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-); glEnd(); + +# undef V +# undef N +} + +/* + * Draws a solid cube. Code contributed by Andreas Umbach + */ +void FGAPIENTRY glutSolidCube( GLdouble dSize ) +{ + double size = dSize * 0.5; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidCube" ); + +# define V(a,b,c) glVertex3d( a size, b size, c size ); +# define N(a,b,c) glNormal3d( a, b, c ); + + /* PWO: Again, I dared to convert the code to use macros... */ + glBegin( GL_QUADS ); + N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+); + N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+); + N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+); + N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-); + N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+); + N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-); + glEnd(); + +# undef V +# undef N +} + + /* * Draws a solid sphere */ @@ -905,58 +1019,6 @@ void FGAPIENTRY glutSolidOctahedron( void ) #undef RADIUS } -/* Magic Numbers: r0 = ( 1, 0, 0 ) - * r1 = ( -1/3, 2 sqrt(2) / 3, 0 ) - * r2 = ( -1/3, -sqrt(2) / 3, sqrt(6) / 3 ) - * r3 = ( -1/3, -sqrt(2) / 3, -sqrt(6) / 3 ) - * |r0| = |r1| = |r2| = |r3| = 1 - * Distance between any two points is 2 sqrt(6) / 3 - * - * Normals: The unit normals are simply the negative of the coordinates of the point not on the surface. - */ - -#define NUM_TETR_FACES 4 - -static GLdouble tet_r[4][3] = { { 1.0, 0.0, 0.0 }, - { -0.333333333333, 0.942809041582, 0.0 }, - { -0.333333333333, -0.471404520791, 0.816496580928 }, - { -0.333333333333, -0.471404520791, -0.816496580928 } } ; - -static GLint tet_i[4][3] = /* Vertex indices */ -{ - { 1, 3, 2 }, { 0, 2, 3 }, { 0, 3, 1 }, { 0, 1, 2 } -} ; - -/* - * - */ -void FGAPIENTRY glutWireTetrahedron( void ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireTetrahedron" ); - - glBegin( GL_LINE_LOOP ) ; - glNormal3d ( -tet_r[0][0], -tet_r[0][1], -tet_r[0][2] ) ; glVertex3dv ( tet_r[1] ) ; glVertex3dv ( tet_r[3] ) ; glVertex3dv ( tet_r[2] ) ; - glNormal3d ( -tet_r[1][0], -tet_r[1][1], -tet_r[1][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[2] ) ; glVertex3dv ( tet_r[3] ) ; - glNormal3d ( -tet_r[2][0], -tet_r[2][1], -tet_r[2][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[3] ) ; glVertex3dv ( tet_r[1] ) ; - glNormal3d ( -tet_r[3][0], -tet_r[3][1], -tet_r[3][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[1] ) ; glVertex3dv ( tet_r[2] ) ; - glEnd() ; -} - -/* - * - */ -void FGAPIENTRY glutSolidTetrahedron( void ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidTetrahedron" ); - - glBegin( GL_TRIANGLES ) ; - glNormal3d ( -tet_r[0][0], -tet_r[0][1], -tet_r[0][2] ) ; glVertex3dv ( tet_r[1] ) ; glVertex3dv ( tet_r[3] ) ; glVertex3dv ( tet_r[2] ) ; - glNormal3d ( -tet_r[1][0], -tet_r[1][1], -tet_r[1][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[2] ) ; glVertex3dv ( tet_r[3] ) ; - glNormal3d ( -tet_r[2][0], -tet_r[2][1], -tet_r[2][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[3] ) ; glVertex3dv ( tet_r[1] ) ; - glNormal3d ( -tet_r[3][0], -tet_r[3][1], -tet_r[3][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[1] ) ; glVertex3dv ( tet_r[2] ) ; - glEnd() ; -} - /* * */ @@ -1143,7 +1205,7 @@ void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, GLdouble offset[3], G if ( num_levels == 0 ) { - for ( i = 0 ; i < NUM_TETR_FACES ; i++ ) + for ( i = 0 ; i < TETR_NUM_FACES ; i++ ) { glBegin ( GL_LINE_LOOP ) ; glNormal3d ( -tet_r[i][0], -tet_r[i][1], -tet_r[i][2] ) ; @@ -1163,7 +1225,7 @@ void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, GLdouble offset[3], G GLdouble local_offset[3] ; /* Use a local variable to avoid buildup of roundoff errors */ num_levels -- ; scale /= 2.0 ; - for ( i = 0 ; i < NUM_TETR_FACES ; i++ ) + for ( i = 0 ; i < TETR_NUM_FACES ; i++ ) { local_offset[0] = offset[0] + scale * tet_r[i][0] ; local_offset[1] = offset[1] + scale * tet_r[i][1] ; @@ -1183,7 +1245,7 @@ void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, GLdouble offset[3], { glBegin ( GL_TRIANGLES ) ; - for ( i = 0 ; i < NUM_TETR_FACES ; i++ ) + for ( i = 0 ; i < TETR_NUM_FACES ; i++ ) { glNormal3d ( -tet_r[i][0], -tet_r[i][1], -tet_r[i][2] ) ; for ( j = 0; j < 3; j++ ) @@ -1202,7 +1264,7 @@ void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble local_offset[3] ; /* Use a local variable to avoid buildup of roundoff errors */ num_levels -- ; scale /= 2.0 ; - for ( i = 0 ; i < NUM_TETR_FACES ; i++ ) + for ( i = 0 ; i < TETR_NUM_FACES ; i++ ) { local_offset[0] = offset[0] + scale * tet_r[i][0] ; local_offset[1] = offset[1] + scale * tet_r[i][1] ; @@ -1212,4 +1274,23 @@ void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, GLdouble offset[3], } } + + +/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ + + +void FGAPIENTRY glutWireTetrahedron( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireTetrahedron" ); + + fghTetrahedron( TRUE ); +} +void FGAPIENTRY glutSolidTetrahedron( void ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidTetrahedron" ); + + fghTetrahedron( FALSE ); +} + + /*** END OF FILE ***/ -- 1.7.10.4