//- // ========================================================================== // Copyright (C) 1995 - 2005 Alias Systems Corp. and/or its licensors. All // rights reserved. // // The coded instructions, statements, computer programs, and/or related // material (collectively the "Data") in these files are provided by Alias // Systems Corp. ("Alias") and/or its licensors for the exclusive use of the // Customer (as defined in the Alias Software License Agreement that // accompanies this Alias software). Such Customer has the right to use, // modify, and incorporate the Data into other products and to distribute such // products for use by end-users. // // THE DATA IS PROVIDED "AS IS". ALIAS HEREBY DISCLAIMS ALL WARRANTIES // RELATING TO THE DATA, INCLUDING, WITHOUT LIMITATION, ANY AND ALL EXPRESS OR // IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. IN NO EVENT SHALL ALIAS BE LIABLE FOR ANY DAMAGES // WHATSOEVER, WHETHER DIRECT, INDIRECT, SPECIAL, OR PUNITIVE, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, OR IN EQUITY, // ARISING OUT OF ACCESS TO, USE OF, OR RELIANCE UPON THE DATA. // ========================================================================== //+ //////////////////////////////////////////////////////////////////////// // // Description: // This plugin creates the following types of polygon primitives // at the origin: // 1) Icosahedron // 2) Dodecahedron // 3) Tetrahedron // 4) Cube // 5) Octahedron // 6) Plane // 7) Cylinder // 8) Truncated Icosahedron (soccer ball) // // Usage: // polyPrimitive // // // Options: ******NOT IMPLEMENTED YET****** // Plane: // Cube: // X Sections: number of horizontal sections // Y Sections: number of vertical sections // Size: width and height of the square // // Cylinder: // Radius: radius of the cylinder // Sides: number of polygons around the cylinder // Height: height of the cylinder // Sections: number of vertical sections // // // Related files: // polyPrimitiveCmd.mel // // // Limitations: // Newly created primitives are always placed at origin // // Note: // Original implementation for OpenAlias in the // jptPolyPrimitives plugin // //////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 /* pi */ #endif // Macro for error checking #define checkErr(stat,msg) \ if ( MS::kSuccess != stat ) { \ displayError(msg); \ return stat; \ } ///////////////////////////////// // Primitive face connect data // ///////////////////////////////// static int tetra_gons[12] = { 1,2,3, 2,4,3, 1,3,4, 1,4,2 }; static int cube_gons[24] = { 1,4,3,2, 8,5,6,7, 3,7,6,2, 1,5,8,4, 3,4,8,7, 2,6,5,1 }; static int octa_gons[24] = { 2,3,1, 3,4,1, 4,5,1, 1,5,2, 6,3,2, 6,4,3, 6,5,4, 6,2,5 }; static int dodeca_gons[60] = { 1,5,3,4,2, 8,6,7,1,2, 1,7,17,20,5, 6,11,12,17,7, 17,12,9,16,20, 5,20,16,14,3, 3,14,15,19,4, 2,4,19,18,8, 8,18,13,11,6, 9,12,11,13,10, 10,13,18,19,15, 10,15,14,16,9 }; static int icosa_gons[60] = { 2,10,1, 1,11,2, 1,8,7, 1,7,11, 1,10,8, 5,2,6, 10,2,5, 2,11,6, 4,9,3, 3,12,4, 5,6,3, 3,9,5, 6,12,3, 7,8,4, 4,12,7, 4,8,9, 5,9,10, 6,11,12, 7,12,11, 8,10,9 }; static double trunc_icosa_vtxArray[][3] = { { 0.00000000, 0.00000000, 1.00000000 }, { 0.39524780, 0.00000000, 0.91857395 }, { -0.22278550, 0.32647698, 0.91857395 }, { -0.14409696, -0.36804505, 0.91857395 }, { 0.56771009, 0.32647698, 0.75572282 }, { 0.49542801, -0.36804505, 0.78682468 }, { -0.58966797, 0.28490989, 0.75572282 }, { -0.05032380, 0.65295495, 0.75572282 }, { 0.16209500, -0.59550930, 0.78682468 }, { -0.51097943, -0.40961312, 0.75572282 }, { 0.84035260, 0.28490989, 0.46112243 }, { 0.34492458, 0.65295495, 0.67429775 }, { 0.76807052, -0.40961312, 0.49222429 }, { -0.64395201, 0.58569638, 0.49222429 }, { -0.73376494, -0.08313546, 0.67429775 }, { -0.31061900, 0.81316063, 0.49222429 }, { 0.10140353, -0.86454163, 0.49222429 }, { -0.57166993, -0.67864447, 0.46112243 }, { 0.78606856, 0.58569638, 0.19762390 }, { 0.94053281, -0.08313546, 0.32937316 }, { 0.47987757, 0.81316063, 0.32937316 }, { 0.70737904, -0.67864447, 0.19762390 }, { -0.84233203, 0.51843879, 0.14730069 }, { -0.93214496, -0.15039373, 0.32937316 }, { -0.17566601, 0.97336729, 0.14730069 }, { 0.37404603, -0.90610970, 0.19762390 }, { -0.26547894, -0.90610970, 0.32937316 }, { -0.83196474, -0.51843879, 0.19762390 }, { 0.83196474, 0.51843879, -0.19762390 }, { 0.98642507, -0.15039373, -0.06587463 }, { 0.21958178, 0.97336729, 0.06587463 }, { 0.84233203, -0.51843879, -0.14730069 }, { -0.70737904, 0.67864447, -0.19762390 }, { -0.98642507, 0.15039373, 0.06587463 }, { -0.37404603, 0.90610970, -0.19762390 }, { 0.17566601, -0.97336729, -0.14730069 }, { -0.21958178, -0.97336729, -0.06587463 }, { -0.78606856, -0.58569638, -0.19762390 }, { 0.57166993, 0.67864447, -0.46112243 }, { 0.93214496, 0.15039373, -0.32937316 }, { 0.26547894, 0.90610970, -0.32937316 }, { 0.64395201, -0.58569638, -0.49222429 }, { -0.76807052, 0.40961312, -0.49222429 }, { -0.94053281, 0.08313546, -0.32937316 }, { -0.10140353, 0.86454163, -0.49222429 }, { 0.31061900, -0.81316063, -0.49222429 }, { -0.47987757, -0.81316063, -0.32937316 }, { -0.84035260, -0.28490989, -0.46112243 }, { 0.51097943, 0.40961312, -0.75572282 }, { 0.73376494, 0.08313546, -0.67429775 }, { 0.58966797, -0.28490989, -0.75572282 }, { -0.49542801, 0.36804505, -0.78682468 }, { -0.16209500, 0.59550930, -0.78682468 }, { 0.05032380, -0.65295495, -0.75572282 }, { -0.34492458, -0.65295495, -0.67429775 }, { -0.56771009, -0.32647698, -0.75572282 }, { 0.14409696, 0.36804505, -0.91857395 }, { 0.22278550, -0.32647698, -0.91857395 }, { -0.39524780, 0.00000000, -0.91857395 }, { 0.00000000, 0.00000000, -1.00000000 } }; static int trunc_icosa_faceCountArray[] = { 6, 6, 5, 6, 5, 6, 5, 6, 6, 6, 5, 6, 5, 6, 5, 6, 6, 6, 5, 6, 5, 5, 6, 6, 6, 5, 6, 5, 6, 6, 5, 6 }; static int trunc_icosa_faceConnectArray[] = { 0,1,4,11,7,2, 0,2,6,14,9,3, 3,8,5,1,0, 5,12,19,10,4,1, 7,15,13,6,2, 9,17,26,16,8,3, 4,10,18,20,11, 5,8,16,25,21,12, 6,13,22,33,23,14, 7,11,20,30,24,15, 9,14,23,27,17, 19,29,39,28,18,10, 21,31,29,19,12, 13,15,24,34,32,22, 26,36,35,25,16, 27,37,46,36,26,17, 28,38,40,30,20,18, 21,25,35,45,41,31, 22,32,42,43,33, 33,43,47,37,27,23, 24,30,40,44,34, 39,49,48,38,28, 29,31,41,50,49,39, 32,34,44,52,51,42, 35,36,46,54,53,45, 47,55,54,46,37, 48,56,52,44,40,38, 41,45,53,57,50, 51,58,55,47,43,42, 48,49,50,57,59,56, 51,52,56,59,58, 53,54,55,58,59,57 }; ////////////////////// // Class definition // ////////////////////// class polyPrimitive : public MPxCommand { public: polyPrimitive() {}; virtual ~polyPrimitive(); MStatus doIt( const MArgList& args ); MStatus redoIt(); MStatus undoIt(); inline bool isUndoable() const { return true; }; static void* creator(); public: inline void FILL( double x, double y, double z ); void create_icosa_points(); void create_dodecahedron(); void create_tetrahedron(); void create_cube(); void create_octahedron(); void create_truncated_icosahedron(); void createPlane(); void createCylinder(); // What sort of shape we're making int shapeFlag; // Misc. primitive data // int num_verts; // Number of vertices of polygon int num_faces; // Number of faces on polygon int num_edges; // Number of edges on polygon int edges_per_face; // Number of edges (or verticies) per face int num_face_connects; // Number of elements in face connect array int *p_gons; // Pointer to static array of face connects MFloatPointArray iarr; MFloatPointArray pa; MIntArray faceCounts; MIntArray faceConnects; MObject newTransform; MDGModifier dgModifier; }; ////////////////////////// // Class implementation // ////////////////////////// polyPrimitive::~polyPrimitive() {} void* polyPrimitive::creator() { return new polyPrimitive(); } void polyPrimitive::FILL( double x, double y, double z ) { MFloatPoint pnt( (float)x, (float)y, (float)z ); iarr.append( pnt ); } //////////////////////////////// // Primitive creation methods // //////////////////////////////// void polyPrimitive::create_icosa_points() { double a = sqrt( ( 1.0 - sqrt( .2 ) ) / 2.0 ); double b = sqrt( ( 1.0 + sqrt( .2 ) ) / 2.0 ); double z = 0.0; FILL(b,a,z); FILL(b,-a,z); FILL(-b,-a,z); FILL(-b,a,z); FILL(0,-b,-a); FILL(0,-b,a); FILL(0,b,a); FILL(0,b,-a); FILL(-a,0,-b); FILL(a,0,-b); FILL(a,0,b); FILL(-a,0,b); } void polyPrimitive::create_dodecahedron() { // Generated from icosahedron points. create_icosa_points(); MFloatPoint my_info[12]; int idx; for( idx = 0; idx < 12; idx++ ) { my_info[idx].x=iarr[idx].x; my_info[idx].y=iarr[idx].y; my_info[idx].z=iarr[idx].z; } iarr.clear(); // now generate the dodecahedron points: double x1,y1,z1,x2,y2,z2,x3,y3,z3; double xf, yf, zf; double len; for( idx = 0; idx < 20; idx++ ) { x1 = my_info[ icosa_gons[3*idx]-1 ].x; y1 = my_info[ icosa_gons[3*idx]-1 ].y; z1 = my_info[ icosa_gons[3*idx]-1 ].z; x2 = my_info[ icosa_gons[3*idx + 1]-1 ].x; y2 = my_info[ icosa_gons[3*idx + 1]-1 ].y; z2 = my_info[ icosa_gons[3*idx + 1]-1 ].z; x3 = my_info[ icosa_gons[3*idx + 2]-1 ].x; y3 = my_info[ icosa_gons[3*idx + 2]-1 ].y; z3 = my_info[ icosa_gons[3*idx + 2]-1 ].z; // the docecahedron vertex is the average of these points. xf = (x1+x2+x3)/3.0; yf = (y1+y2+y3)/3.0; zf = (z1+z2+z3)/3.0; // One more transformation: scale this point so it lies on the // unit sphere... len = sqrt( xf*xf + yf*yf + zf*zf ); xf /= len; yf /= len; zf /= len; FILL( xf, yf, zf ); } } void polyPrimitive::create_tetrahedron( ) { // First, create the points: double sq = sqrt(3.0); FILL(0.0,0.0,1.0); FILL(sq/2.0,0.0,-.5); FILL(-sq/4.0,.75,-.5); FILL(-sq/4.0,-.75,-.5); } void polyPrimitive::create_cube( ) { // First, create the points: double a = sqrt( 1.0/3.0 ); FILL(a,a,a); FILL(a,-a,a); FILL(-a,-a,a); FILL(-a,a,a); FILL(a,a,-a); FILL(a,-a,-a); FILL(-a,-a,-a); FILL(-a,a,-a); } void polyPrimitive::create_octahedron( ) { FILL(0.0,0.0,1.0); FILL(1.0,0.0,0.0); FILL(0.0,1.0,0.0); FILL(-1.0,0.0,0.0); FILL(0.0,-1.0,0.0); FILL(0.0,0.0,-1.0); } void polyPrimitive::create_truncated_icosahedron( ) { num_verts = 60; int idx; for ( idx = 0; idx < num_verts; idx++ ) { FILL(trunc_icosa_vtxArray[idx][0], trunc_icosa_vtxArray[idx][1], trunc_icosa_vtxArray[idx][2]); } num_faces = 32; for ( idx = 0; idx < num_faces; idx++ ) { faceCounts.append( trunc_icosa_faceCountArray[idx] ); } for ( idx = 0; idx < 180; idx++ ) { faceConnects.append( trunc_icosa_faceConnectArray[idx] ); } } void polyPrimitive::createPlane( ) { int w = 2; int h = 2; double size = 2.0; double hSize, wSize; // Initialize class data // num_verts = 0; num_faces = 0; edges_per_face = 4; if ( w < 1 ) w = 1; if ( h < 1 ) h = 1; if ( size < 0.0001 ) size = 1.0; wSize = size / w; hSize = size / h; // create vertices // double x, z; for ( z = -size/2.0; z <= size / 2.0; z += hSize ) { for ( x = -size/2.0; x <= size/2.0; x += wSize ) { FILL( x, 0, z ); num_verts++; } } // create polys // int v0, v1, v2, v3; for ( int i = 0; i < h; i++ ) { for ( int j = 0; j < w; j++ ) { v0 = j + (w+1) * i; v1 = j + 1 + (w+1) * i; v2 = j + 1 + (w+1) * (i+1); v3 = j + (w+1) * (i+1); faceConnects.append( v0 ); faceConnects.append( v3 ); faceConnects.append( v2 ); faceConnects.append( v1 ); num_faces++; faceCounts.append( edges_per_face ); } } num_face_connects = num_faces * edges_per_face; num_edges = num_face_connects/2; } void polyPrimitive::createCylinder() { double r = 1.0; double height = 2.0; int sides = 8; int sections = 2; // Initialize class data // num_verts = 0; num_faces = 0; edges_per_face = 0; if ( sides < 3 ) sides = 3; if ( sections < 1 ) sections = 1; if ( height <= 0 ) height = 1.0; if ( r <= 0 ) r = 1.0; // create verts // double angle, deg = 360.0 / (double) sides; double hSize = height / (double) sections; double x, z, y = height / 2.0; int i,j; for ( i = 0; i <= sections; i++ ) { for ( j = sides - 1; j >= 0; j-- ) { angle = deg * j / 180.0 * M_PI; x = cos( angle ); z = sin( angle ); FILL( x, y, z ); num_verts++; } // for j y -= hSize; } // for i // create polys // for ( i = 0; i < sides; i++ ) { faceConnects.append( i ); edges_per_face++; } num_faces++; faceCounts.append( edges_per_face ); edges_per_face = 0; for ( i = sides-1; i >= 0; i-- ) { faceConnects.append( i + sides * sections ); edges_per_face++; } num_faces++; faceCounts.append( edges_per_face ); edges_per_face = 0; int v0, v1, v2, v3; for ( i = 0; i < sections; i++ ) { for ( j = 0; j < sides; j++ ) { if ( j == 0 ) // use last vtx on this section { v0 = sides - 1 + sides * i; v3 = sides - 1 + sides * (i+1); } else // use prev vtx { v0 = j - 1 + sides * i; v3 = j - 1 + sides * (i+1); } v1 = j + sides * i; v2 = j + sides * (i+1); faceConnects.append( v0 ); faceConnects.append( v3 ); faceConnects.append( v2 ); faceConnects.append( v1 ); num_faces++; faceCounts.append( 4 ); } // for j } // for i num_face_connects = faceConnects.length(); num_edges = num_face_connects/2; } MStatus polyPrimitive::doIt( const MArgList& args ) { // Command line argument specifies type of primitive to create // shapeFlag = 1; if ( args.length() > 0 ) shapeFlag = args.asInt(0); return redoIt(); } MStatus polyPrimitive::redoIt() { MStatus stat; // create a poly function set // MFnMesh fnPoly; iarr.clear(); faceCounts.clear(); faceConnects.clear(); // Decide which type of primitive to create // switch( shapeFlag ) { case 1: default: create_icosa_points(); num_verts = 12; num_faces = 20; edges_per_face = 3; p_gons = icosa_gons; break; case 2: create_dodecahedron(); num_verts = 20; num_faces = 12; edges_per_face = 5; p_gons = dodeca_gons; break; case 3: create_tetrahedron(); num_verts = 4; num_faces = 4; edges_per_face = 3; p_gons = tetra_gons; break; case 4: create_cube(); num_verts = 8; num_faces = 6; edges_per_face = 4; p_gons = cube_gons; break; case 5: create_octahedron(); num_verts = 6; num_faces = 8; edges_per_face = 3; p_gons = octa_gons; break; case 6: createPlane(); p_gons = NULL; break; case 7: createCylinder(); p_gons = NULL; break; case 8: create_truncated_icosahedron(); p_gons = NULL; break; } // Construct the point array // pa.clear(); int i; for ( i=0; i