#include <math.h>
#include <maya/MIOStream.h>
#include "apiMeshCreator.h"
#include "apiMeshData.h"
#include <api_macros.h>
#include <maya/MFnMesh.h>
#include <maya/MFnPluginData.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MFnEnumAttribute.h>
#include <maya/MFnNumericAttribute.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif
MObject apiMeshCreator::outputSurface;
MTypeId apiMeshCreator::id( 0x80089 );
apiMeshCreator::apiMeshCreator() {}
apiMeshCreator::~apiMeshCreator() {}
{
if ( plug == outputSurface ) {
fnDataCreator.
create( tmpid, &stat );
MCHECKERROR( stat, "compute : error creating apiMeshData")
apiMeshData * newData = (apiMeshData*)fnDataCreator.data( &stat );
MCHECKERROR( stat, "compute : error gettin at proxy apiMeshData object")
apiMeshGeom * geomPtr = newData->fGeometry;
bool hasHistory = computeInputMesh( plug, datablock,
geomPtr->vertices,
geomPtr->face_counts,
geomPtr->face_connects,
geomPtr->normals,
geomPtr->uvcoords
);
if ( !hasHistory ) {
double shape_size = sizeHandle.
asDouble();
MDataHandle typeHandle = datablock.inputValue( shapeType );
short shape_type = typeHandle.
asShort();
switch( shape_type )
{
case 0 :
buildCube( shape_size,
geomPtr->vertices,
geomPtr->face_counts,
geomPtr->face_connects,
geomPtr->normals,
geomPtr->uvcoords
);
break;
case 1 :
buildSphere( shape_size,
32,
geomPtr->vertices,
geomPtr->face_counts,
geomPtr->face_connects,
geomPtr->normals,
geomPtr->uvcoords
);
break;
}
}
geomPtr->faceCount = geomPtr->face_counts.length();
MDataHandle outHandle = datablock.outputValue( outputSurface );
outHandle.
set( newData );
datablock.setClean( plug );
}
else {
}
}
void apiMeshCreator::buildCube(
double cube_size,
apiMeshGeomUV& uvs
)
{
const int num_faces = 6;
const int num_face_connects = 24;
const double normal_value = 0.5775;
const int uv_count = 14;
uvs.reset();
normals.
append(
MVector( -normal_value, -normal_value, -normal_value ) );
normals.
append(
MVector( normal_value, -normal_value, -normal_value ) );
normals.
append(
MVector( normal_value, -normal_value, normal_value ) );
normals.
append(
MVector( -normal_value, -normal_value, normal_value ) );
normals.
append(
MVector( -normal_value, normal_value, -normal_value ) );
normals.
append(
MVector( -normal_value, normal_value, normal_value ) );
normals.
append(
MVector( normal_value, normal_value, normal_value ) );
normals.
append(
MVector( normal_value, normal_value, -normal_value ) );
float uv_pts[uv_count * 2] = { 0.375, 0.0,
0.625, 0.0,
0.625, 0.25,
0.375, 0.25,
0.625, 0.5,
0.375, 0.5,
0.625, 0.75,
0.375, 0.75,
0.625, 1.0,
0.375, 1.0,
0.875, 0.0,
0.875, 0.25,
0.125, 0.0,
0.125, 0.25
};
int uv_fvid [ num_face_connects ] = { 0, 1, 2, 3,
3, 2, 4, 5,
5, 4, 6, 7,
7, 6, 8, 9,
1, 10, 11, 2,
12, 0, 3, 13 };
int i;
for ( i = 0; i < uv_count; i ++ ) {
uvs.append_uv( uv_pts[i*2], uv_pts[i*2 + 1] );
}
for ( i = 0; i < num_face_connects; i ++ ) {
uvs.faceVertexIndex.append( uv_fvid[i] );
}
int face_counts[num_faces] = { 4, 4, 4, 4, 4, 4 };
for ( i=0; i<num_faces; i++ )
{
faceCounts.
append( face_counts[i] );
}
int face_connects[ num_face_connects ] = { 0, 1, 2, 3,
4, 5, 6, 7,
3, 2, 6, 5,
0, 3, 5, 4,
0, 4, 7, 1,
1, 7, 6, 2 };
for ( i=0; i<num_face_connects; i++ )
{
faceConnects.
append( face_connects[i] );
}
}
void apiMeshCreator::buildSphere(
double rad,
int div,
apiMeshGeomUV & uvs
)
{
double u = -M_PI_2;
double v = -M_PI;
double u_delta = M_PI / ((double)div);
double v_delta = 2 * M_PI / ((double)div);
MPoint topPole( 0.0, rad, 0.0 );
MPoint botPole( 0.0, -rad, 0.0 );
int i;
for ( i=0; i<(div-1); i++ )
{
u += u_delta;
v = -M_PI;
for ( int j=0; j<div; j++ )
{
double x = rad * cos(u) * cos(v);
double y = rad * sin(u);
double z = rad * cos(u) * sin(v) ;
v += v_delta;
}
}
int vid = 1;
int numV = 0;
for ( i=0; i<div; i++ )
{
for ( int j=0; j<div; j++ )
{
if ( i==0 ) {
connects.
append( (j==(div-1)) ? vid : j+vid+1 );
}
else if ( i==(div-1) ) {
connects.
append( j+vid+1-div );
connects.
append( j==(div-1) ? vid+1-div : j+vid+2-div );
}
else {
connects.
append( j + vid+1-div );
connects.
append( j == (div-1) ? vid+1 : j+vid+2 );
connects.
append( j == (div-1) ? vid+1-div : j+vid+2-div );
}
numV++;
}
vid = numV;
}
}
MStatus apiMeshCreator::computeInputMesh(
apiMeshGeomUV& uvs
)
{
MCHECKERROR( stat, "compute get inputMesh")
MPlug surfPlug( thisObj, inputMesh );
if ( !surfPlug.isConnected() ) {
MCHECKERROR( stat, "compute setClean" )
}
MCHECKERROR( stat, "compute -
MFnMesh error" );
stat = surfFn.getPoints( vertices,
MSpace::kObject );
MCHECKERROR( stat, "compute getPoints");
bool hasUVs = surfFn.numUVs() > 0;
surfFn.getUVs( uvs.ucoord, uvs.vcoord );
for ( int i=0; i<surfFn.numPolygons(); i++ )
{
surfFn.getPolygonVertices( i, polyVerts );
int uvId;
for ( int v=0; v<pvc; v++ ) {
if ( hasUVs ) {
surfFn.getPolygonUVid( i, v, uvId );
uvs.faceVertexIndex.append( uvId );
}
connects.
append( polyVerts[v] );
}
}
for ( int n=0; n<(int)vertices.length(); n++ )
{
surfFn.getVertexNormal( n, normal );
}
}
void* apiMeshCreator::creator()
{
return new apiMeshCreator();
}
MStatus apiMeshCreator::initialize()
{
MAKE_NUMERIC_ATTR( size, "size", "sz",
false, false, true );
shapeType = enumAttr.
create(
"shapeType",
"st", 0, &stat );
MCHECKERROR( stat, "create shapeType attribute" );
MCHECKERROR( stat, "add enum type cube" );
stat = enumAttr.
addField(
"sphere", 1 );
MCHECKERROR( stat, "add enum type sphere" );
ADD_ATTRIBUTE( shapeType );
MAKE_TYPED_ATTR( inputMesh,
"inputMesh",
"im",
MFnData::kMesh, NULL );
outputSurface = typedAttr.
create(
"outputSurface",
"os",
apiMeshData::id,
MCHECKERROR( stat, "create outputSurface attribute" )
typedAttr.setWritable( false );
ADD_ATTRIBUTE( outputSurface );
ATTRIBUTE_AFFECTS( inputMesh, outputSurface );
ATTRIBUTE_AFFECTS( size, outputSurface );
ATTRIBUTE_AFFECTS( shapeType, outputSurface );
}