#include <maya/MIOStream.h>
#include <math.h>
#include <maya/MPxCommand.h>
#include <maya/MString.h>
#include <maya/MArgList.h>
#include <maya/MGlobal.h>
#include <maya/MPoint.h>
#include <maya/MIntArray.h>
#include <maya/MDoubleArray.h>
#include <maya/MFloatPoint.h>
#include <maya/MFloatPointArray.h>
#include <maya/MDagPath.h>
#include <maya/MFnPlugin.h>
#include <maya/MFnMesh.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define checkErr(stat,msg) \
if ( MS::kSuccess != stat ) { \
displayError(msg); \
return stat; \
}
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 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();
int shapeFlag;
int num_verts;
int num_faces;
int num_edges;
int edges_per_face;
int num_face_connects;
int *p_gons;
MFloatPointArray iarr;
MFloatPointArray pa;
MIntArray faceCounts;
MIntArray faceConnects;
MObject newTransform;
MDGModifier dgModifier;
};
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 );
}
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()
{
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();
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;
xf = (x1+x2+x3)/3.0;
yf = (y1+y2+y3)/3.0;
zf = (z1+z2+z3)/3.0;
len = sqrt( xf*xf + yf*yf + zf*zf );
xf /= len; yf /= len; zf /= len;
FILL( xf, yf, zf );
}
}
void polyPrimitive::create_tetrahedron( )
{
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( )
{
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;
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;
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++;
}
}
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;
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;
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++;
}
y -= hSize;
}
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 )
{
v0 = sides - 1 + sides * i;
v3 = sides - 1 + sides * (i+1);
}
else
{
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 );
}
}
num_face_connects = faceConnects.length();
num_edges = num_face_connects/2;
}
MStatus polyPrimitive::doIt( const MArgList& args )
{
shapeFlag = 1;
if ( args.length() > 0 )
shapeFlag = args.asInt(0);
return redoIt();
}
MStatus polyPrimitive::redoIt()
{
MStatus stat;
MFnMesh fnPoly;
iarr.clear();
faceCounts.clear();
faceConnects.clear();
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;
}
pa.clear();
int i;
for ( i=0; i<num_verts; i++ )
pa.append( iarr[i] );
if ( NULL != p_gons ) {
num_face_connects = num_faces * edges_per_face;
num_edges = num_face_connects/2;
for ( i=0; i<num_faces; i++ )
faceCounts.append( edges_per_face );
for ( i=0; i<(num_faces*edges_per_face); i++ )
faceConnects.append( p_gons[i]-1 );
}
newTransform = fnPoly.create( num_verts, num_faces, pa,
faceCounts, faceConnects, MObject::kNullObj, &stat );
checkErr( stat, "Could not create MFnMesh" );
fnPoly.updateSurface();
dgModifier.renameNode( newTransform, "pPrimitive1" );
dgModifier.doIt();
MString cmd ("sets -e -fe initialShadingGroup ");
cmd += fnPoly.name();
dgModifier.commandToExecute( cmd );
MFnDagNode fnDagNode( newTransform, &stat );
if ( MS::kSuccess == stat )
{
cmd = "select ";
cmd += fnDagNode.name();
dgModifier.commandToExecute( cmd );
}
dgModifier.doIt();
return MS::kSuccess;
}
MStatus polyPrimitive::undoIt()
{
MStatus status;
MDGModifier dgModifier;
MFnDagNode dagNode( newTransform, &status );
checkErr( status, "Could not get dagNode for transform" );
MObject mesh = dagNode.child( 0, &status );
checkErr( status, "Could not get dagNode's child" );
MFnDependencyNode meshNode( mesh );
status = dgModifier.deleteNode( mesh );
checkErr( status, "Could not delete mesh" );
dgModifier.deleteNode( newTransform );
checkErr( status, "Could not delete transform" );
return dgModifier.doIt();
}
MStatus initializePlugin( MObject obj )
{
MStatus status;
MFnPlugin plugin( obj, PLUGIN_COMPANY, "3.0", "Any");
status = plugin.registerCommand( "polyPrimitiveTest", polyPrimitive::creator );
if (!status) {
status.perror("registerCommand");
return status;
}
status = plugin.registerUI("polyPrimitiveCreateUI", "polyPrimitiveDeleteUI");
if (!status) {
status.perror("registerUI");
return status;
}
return status;
}
MStatus uninitializePlugin( MObject obj)
{
MStatus status;
MFnPlugin plugin( obj );
status = plugin.deregisterCommand( "polyPrimitiveTest" );
if (!status) {
status.perror("deregisterCommand");
return status;
}
return status;
}