/** * $Id: cylicone.cc,v 1.2 1996/08/31 07:04:00 keithw Exp $ * * (c)1996 Hermetica. Written by Alligator Descartes * * Cylinder/cone tesselator * */ /* * Distributed under the Artistic Licence. This file is not a part of lib3d. * See the file LICENCE in this directory. */ #ifdef PTHREADS #include #endif #include #include #include #include #include // static const char *rcsId = "$Id: cylicone.cc,v 1.2 1996/08/31 07:04:00 keithw Exp $"; Model *_createCylinderTriangular( cylicone_cap_t type, float bottomRadius, float topRadius, float height, float granularity ); Model *_createCylinderPolygonal( cylicone_cap_t type, float bottomRadius, float topRadius, float height, float granularity ); Model * createCone( cylicone_cap_t capping, float radius, float height, float granularity ) { float facetAngle = 360 / granularity; int vertexLoop; int topCap = 0, bottomCap = 0; ModelBuilder mb; int numVertices = int(granularity) + 1; // Number of vertices + apex printf( "createCone: radius: %f\theight: %f\tgranularity: %f\n", radius, height, granularity ); printf( "\tAngle of subdivision: %f\n", facetAngle ); printf( "\tCalculating %f vertices of base\n", granularity ); if ( radius <= 0 || granularity <= 2 || height <= 0 ) { return NULL; } if ( ( capping & CAP_TOP ) || ( capping & CAP_BOTTOM ) || ( capping & CAP_BOTH ) ) { topCap = 1; bottomCap = 1; /** * Increase the number of vertices required by 1. * - This covers the centre vertex in the base. */ numVertices++; } mb.startModel(); mb.calculatePolygonNormals(); mb.calculateVertexNormals(); mb.setPolygonMaterial( 0 ); uint *modelVertices = new uint[numVertices]; // uint *reverseVertices = new uint[numVertices]; modelVertices[0] = mb.addVertex( 0, height, 0 ); for ( vertexLoop = 1 ; vertexLoop <= granularity ; vertexLoop++, facetAngle += ( 360 / granularity ) ) { float x = 0, y = 0, z = 0; double radAngle = ( ( facetAngle / 180 ) * PI ); x = cos( radAngle ) * radius; z = sin( radAngle ) * radius; printf( "\t\tVertex %i: ( %f, %f, %f )\n", vertexLoop, x, y, z ); modelVertices[vertexLoop] = mb.addVertex( x, y, z ); } /** Add the base centre vertex if we're capping */ if ( topCap || bottomCap ) { modelVertices[numVertices - 1] = mb.addVertex( 0, 0, 0 ); } for ( int polyLoop = 1 ; polyLoop <= granularity ; polyLoop++ ) { uint *polyVertices = new uint[3]; polyVertices[0] = modelVertices[0]; polyVertices[1] = modelVertices[polyLoop]; polyVertices[2] = modelVertices[( polyLoop+1 > granularity ) ? 1 : ( polyLoop+1)]; mb.addPolygon( 3, polyVertices ); // if ( topCap == 0 && bottomCap == 0 ) { uint *backVertices = new uint[3]; backVertices[2] = polyVertices[0]; backVertices[1] = polyVertices[1]; backVertices[0] = polyVertices[2]; mb.addPolygon( 3, backVertices ); // } } /** If we're capping, do the cap now */ if ( topCap || bottomCap ) { for ( int i = 1 ; i <= granularity ; i++ ) { uint *polyVertices = new uint[3]; polyVertices[0] = modelVertices[numVertices - 1]; polyVertices[1] = modelVertices[i]; polyVertices[2] = modelVertices[( i + 1 > granularity ) ? 1 : i + 1]; mb.addPolygon( 3, polyVertices ); } } return mb.endModel(); } /** Cylinder tesselator */ Model * createCylinder( tesselate_type_t ttype, cylicone_cap_t type, float radius, float height, float granularity ) { if ( ttype == TRIANGULAR ) return _createCylinderTriangular( type, radius, radius, height, granularity ); if ( ttype == POLYGONAL ) return _createCylinderPolygonal( type, radius, radius, height, granularity ); return NULL; } Model * createCylinder( tesselate_type_t ttype, cylicone_cap_t type, float bottomRadius, float topRadius, float height, float granularity ) { if ( ttype == TRIANGULAR ) return _createCylinderTriangular( type, bottomRadius, topRadius, height, granularity ); if ( ttype == POLYGONAL ) return _createCylinderPolygonal( type, bottomRadius, topRadius, height, granularity ); return NULL; } Model * _createCylinderTriangular( cylicone_cap_t capping, float bottomRadius, float topRadius, float height, float granularity ) { float facetAngle = 360 / granularity; int vertexLoop; int topCap = 0, bottomCap = 0; ModelBuilder mb; int numVertices = int(granularity) * 2 + 2; printf( "createCylinder: bottomRadius: %f\ttopRadius: %f\theight: %f\tgranularity: %f\n", bottomRadius, topRadius, height, granularity ); printf( "\tAngle of subdivision: %f\n", facetAngle ); printf( "\tCalculating %f vertices of base\n", granularity ); if ( bottomRadius <= 0 || topRadius <= 0 || granularity <= 2 || height <= 0 ) { return NULL; } if ( capping == CAP_BOTH ) { topCap = 1; bottomCap = 1; } else { if ( capping & CAP_TOP ) { topCap = 1; } else { if ( capping & CAP_BOTTOM ) { bottomCap = 1; } } } mb.startModel(); mb.calculatePolygonNormals(); mb.calculateVertexNormals(); mb.setPolygonMaterial( 0 ); uint *modelVertices = new uint[numVertices]; // uint *reverseVertices = new uint[numVertices]; for ( vertexLoop = 0 ; vertexLoop < granularity ; vertexLoop++, facetAngle += ( 360 / granularity ) ) { float x = 0, y = 0, z = 0; double radAngle = ( ( facetAngle / 180 ) * PI ); x = cos( radAngle ) * bottomRadius; z = sin( radAngle ) * bottomRadius; modelVertices[vertexLoop] = mb.addVertex( x, y, z ); x = cos( radAngle ) * topRadius; z = sin( radAngle ) * topRadius; modelVertices[(int)(vertexLoop + granularity)] = mb.addVertex( x, y + height, z ); } /** Draw the polygons from the bottom up */ for ( int polyLoop = 0 ; polyLoop < granularity ; polyLoop++ ) { uint *polyVertices = new uint[3]; polyVertices[0] = modelVertices[(int)(polyLoop + granularity)]; polyVertices[1] = modelVertices[polyLoop]; polyVertices[2] = modelVertices[( polyLoop + 1 >= granularity ) ? 0 : ( polyLoop+1)]; mb.addPolygon( 3, polyVertices ); uint *backVertices = new uint[3]; backVertices[2] = polyVertices[0]; backVertices[1] = polyVertices[1]; backVertices[0] = polyVertices[2]; mb.addPolygon( 3, backVertices ); } /** Draw the polygons from the top down */ for ( int polyLoop = int(granularity) ; polyLoop < ( granularity * 2 ) ; polyLoop++ ) { uint *polyVertices = new uint[3]; polyVertices[0] = modelVertices[( polyLoop - granularity + 1 ) == granularity ? (int)0 : (int)( polyLoop - granularity + 1 )]; polyVertices[1] = modelVertices[polyLoop]; polyVertices[2] = modelVertices[( polyLoop + 1 == ( granularity * 2 ) ? (int)granularity : polyLoop + 1 )]; mb.addPolygon( 3, polyVertices ); uint *backVertices = new uint[3]; backVertices[2] = polyVertices[0]; backVertices[1] = polyVertices[1]; backVertices[0] = polyVertices[2]; mb.addPolygon( 3, backVertices ); } /** Draw the bottom cap, if desired */ if ( bottomCap ) { modelVertices[numVertices - 2] = mb.addVertex( 0, 0, 0 ); for ( int i = 0 ; i < granularity ; i++ ) { uint *polyVertices = new uint[3]; polyVertices[0] = modelVertices[numVertices - 2]; polyVertices[1] = modelVertices[i]; polyVertices[2] = modelVertices[( i + 1 == granularity ) ? 0 : i + 1]; mb.addPolygon( 3, polyVertices ); uint *revVertices = new uint[3]; revVertices[0] = polyVertices[2]; revVertices[1] = polyVertices[1]; revVertices[2] = polyVertices[0]; mb.addPolygon( 3, revVertices ); } } /** Draw the top cap on the cylinder */ if ( topCap ) { modelVertices[numVertices - 1] = mb.addVertex( 0, height, 0 ); for ( int i = int(granularity) ; i <= ( granularity * 2 ) ; i++ ) { uint *polyVertices = new uint[3]; polyVertices[0] = modelVertices[numVertices - 1]; polyVertices[1] = modelVertices[i]; polyVertices[2] = modelVertices[( i + 1 == ( granularity * 2 ) ) ? (int)granularity : i + 1]; mb.addPolygon( 3, polyVertices ); uint *revVertices = new uint[3]; revVertices[0] = polyVertices[2]; revVertices[1] = polyVertices[1]; revVertices[2] = polyVertices[0]; mb.addPolygon( 3, revVertices ); } } return mb.endModel(); } Model * _createCylinderPolygonal( cylicone_cap_t capping, float bottomRadius, float topRadius, float height, float granularity ) { float facetAngle = 360 / granularity; int vertexLoop; int topCap = 0, bottomCap = 0; ModelBuilder mb; int numVertices = int(granularity * 2) + 2; printf( "createCylinder ( polygonal ): bottomRadius: %f\ttopRadius: %f\theight: %f\tgranularity: %f\n", bottomRadius, topRadius, height, granularity ); printf( "\tAngle of subdivision: %f\n", facetAngle ); printf( "\tCalculating %f vertices of base\n", granularity ); if ( bottomRadius <= 0 || topRadius <= 0 || granularity <= 2 || height <= 0 ) { return NULL; } if ( capping == CAP_BOTH ) { topCap = 1; bottomCap = 1; } else { if ( capping & CAP_TOP ) { topCap = 1; } else { if ( capping & CAP_BOTTOM ) { bottomCap = 1; } } } mb.startModel(); mb.calculatePolygonNormals(); mb.calculateVertexNormals(); mb.setPolygonMaterial( 0 ); uint *modelVertices = new uint[numVertices]; // uint *reverseVertices = new uint[numVertices]; for ( vertexLoop = 0 ; vertexLoop < granularity ; vertexLoop++, facetAngle += ( 360 / granularity ) ) { float x = 0, y = 0, z = 0; double radAngle = ( ( facetAngle / 180 ) * PI ); x = cos( radAngle ) * bottomRadius; z = sin( radAngle ) * bottomRadius; modelVertices[vertexLoop] = mb.addVertex( x, y, z ); x = cos( radAngle ) * topRadius; z = sin( radAngle ) * topRadius; modelVertices[(int)(vertexLoop + granularity)] = mb.addVertex( x, y + height, z ); } /** Draw the polygons from the bottom up */ for ( int polyLoop = 0 ; polyLoop < granularity ; polyLoop++ ) { uint *polyVertices = new uint[4]; printf( "Creating polygon between vertices %d, %d, %d and %d\n", (int)(polyLoop + granularity), (int)(polyLoop + 1 + granularity ) >= ( granularity * 2 ) ? (int)granularity : (int)( polyLoop + 1 + granularity ), (int)( polyLoop + 1 >= granularity ) ? 0 : ( polyLoop+1), (int)polyLoop ); polyVertices[0] = modelVertices[(int)(polyLoop + granularity)]; polyVertices[1] = modelVertices[(int)(polyLoop + 1 + granularity ) >= ( granularity * 2 ) ? (int)granularity : (int)( polyLoop + 1 + granularity )]; polyVertices[2] = modelVertices[( polyLoop + 1 >= granularity ) ? 0 : ( polyLoop+1)]; polyVertices[3] = modelVertices[polyLoop]; mb.addPolygon( 4, polyVertices ); uint *backVertices = new uint[4]; backVertices[3] = polyVertices[0]; backVertices[2] = polyVertices[1]; backVertices[1] = polyVertices[2]; backVertices[0] = polyVertices[3]; mb.addPolygon( 4, backVertices ); } /** Draw the bottom cap, if desired */ if ( bottomCap ) { modelVertices[numVertices - 2] = mb.addVertex( 0, 0, 0 ); for ( int i = 0 ; i < granularity ; i++ ) { uint *polyVertices = new uint[3]; polyVertices[0] = modelVertices[numVertices - 2]; polyVertices[1] = modelVertices[i]; polyVertices[2] = modelVertices[( i + 1 == granularity ) ? 0 : i + 1]; mb.addPolygon( 3, polyVertices ); uint *revVertices = new uint[3]; revVertices[0] = polyVertices[2]; revVertices[1] = polyVertices[1]; revVertices[2] = polyVertices[0]; mb.addPolygon( 3, revVertices ); } } /** Draw the top cap on the cylinder */ if ( topCap ) { modelVertices[numVertices - 1] = mb.addVertex( 0, height, 0 ); for ( int i = int(granularity) ; i <= ( granularity * 2 ) ; i++ ) { uint *polyVertices = new uint[3]; polyVertices[0] = modelVertices[numVertices - 1]; polyVertices[1] = modelVertices[i]; polyVertices[2] = modelVertices[( i + 1 == ( granularity * 2 ) ) ? (int)granularity : i + 1]; mb.addPolygon( 3, polyVertices ); uint *revVertices = new uint[3]; revVertices[0] = polyVertices[2]; revVertices[1] = polyVertices[1]; revVertices[2] = polyVertices[0]; mb.addPolygon( 3, revVertices ); } } return mb.endModel(); }