meshOpFtyAction.cpp
#include "meshOpFty.h"
#include <maya/MGlobal.h>
#include <maya/MIOStream.h>
#include <maya/MFloatPointArray.h>
#include <maya/MFnMesh.h>
#include <maya/MItMeshPolygon.h>
#include <maya/MItMeshEdge.h>
#define CHECK_STATUS(st) if ((st) != MS::kSuccess) { break; }
MStatus meshOpFty::doIt()
{
MStatus status;
unsigned int i, j;
MFnMesh meshFn(fMesh);
int divisionCount = 2;
MFloatVector translation;
if (fOperationType == kExtrudeEdges
|| fOperationType == kExtrudeFaces
|| fOperationType == kDuplicateFaces
|| fOperationType == kExtractFaces)
{
MFn::Type componentType = getExpectedComponentType(fOperationType);
MIntArray adjacentVertexList;
switch (componentType)
{
case MFn::kMeshEdgeComponent:
for (i = 0; i < fComponentIDs.length(); ++i)
{
int2 vertices;
meshFn.getEdgeVertices(fComponentIDs[i], vertices);
adjacentVertexList.append(vertices[0]);
adjacentVertexList.append(vertices[1]);
}
break;
case MFn::kMeshPolygonComponent:
for (i = 0; i < fComponentIDs.length(); ++i)
{
MIntArray vertices;
meshFn.getPolygonVertices(fComponentIDs[i], vertices);
for (j = 0; j < vertices.length(); ++j)
adjacentVertexList.append(vertices[j]);
}
break;
default:
break;
}
MVector averageNormal(0, 0, 0);
for (i = 0; i < adjacentVertexList.length(); ++i)
{
MVector vertexNormal;
meshFn.getVertexNormal(adjacentVertexList[i], vertexNormal,
MSpace::kWorld);
averageNormal += vertexNormal;
}
if (averageNormal.length() < 0.001)
averageNormal = MVector(0.0, 1.0, 0.0);
else averageNormal.normalize();
translation = averageNormal;
}
bool extrudeTogether = true;
switch (fOperationType)
{
case kSubdivideEdges: {
status = meshFn.subdivideEdges(fComponentIDs, divisionCount);
CHECK_STATUS(status);
break; }
case kSubdivideFaces: {
status = meshFn.subdivideFaces(fComponentIDs, divisionCount);
CHECK_STATUS(status);
break; }
case kExtrudeEdges: {
status = meshFn.extrudeEdges(fComponentIDs, divisionCount,
&translation, extrudeTogether);
CHECK_STATUS(status);
break; }
case kExtrudeFaces: {
status = meshFn.extrudeFaces(fComponentIDs, divisionCount,
&translation, extrudeTogether);
CHECK_STATUS(status);
break; }
case kCollapseEdges: {
status = meshFn.collapseEdges(fComponentIDs);
CHECK_STATUS(status);
break; }
case kCollapseFaces: {
status = meshFn.collapseFaces(fComponentIDs);
CHECK_STATUS(status);
break; }
case kDuplicateFaces: {
status = meshFn.duplicateFaces(fComponentIDs, &translation);
CHECK_STATUS(status);
break; }
case kExtractFaces: {
status = meshFn.extractFaces(fComponentIDs, &translation);
CHECK_STATUS(status);
break; }
case kSplitLightning: {
status = doLightningSplit(meshFn);
CHECK_STATUS(status);
break; }
default:
status = MS::kFailure;
break;
}
return status;
}
MStatus meshOpFty::doLightningSplit(MFnMesh& meshFn)
{
unsigned int i, j;
MIntArray placements;
MIntArray edgeIDs;
MFloatArray edgeFactors;
MFloatPointArray internalPoints;
bool* faceTouched = new bool[fComponentIDs.length()];
for (i = 0; i < fComponentIDs.length(); ++i)
faceTouched[i] = false;
MItMeshPolygon itPoly(fMesh);
for (; !itPoly.isDone(); itPoly.next())
{
if (fComponentIDs[0] == (int)itPoly.index()) break;
}
if (itPoly.isDone())
{
delete [] faceTouched;
return MS::kFailure;
}
int edge0, edge1;
MPoint innerVert0, innerVert1;
int nextFaceIndex = 0;
MIntArray edgeList;
itPoly.getEdges(edgeList);
edge0 = edgeList[0];
bool done = false;
while (!done)
{
faceTouched[nextFaceIndex] = true;
MPoint faceCenter = itPoly.center();
MIntArray faceList;
itPoly.getConnectedFaces(faceList);
nextFaceIndex = -1;
for (i = 0; i < fComponentIDs.length(); ++i)
{
for (j = 0; j < faceList.length(); ++j)
{
if (fComponentIDs[i] == faceList[j] && !faceTouched[i])
{
nextFaceIndex = i;
break;
}
}
if (nextFaceIndex != -1) break;
}
if (nextFaceIndex == -1)
{
done = true;
edge1 = -1;
for (i = 0; i < edgeList.length(); ++i)
{
if (edgeList[i] != edge0)
{
edge1 = edgeList[i];
break;
}
}
if (edge1 == -1)
{
delete [] faceTouched;
return MS::kFailure;
}
}
else
{
itPoly.reset();
for (; !itPoly.isDone(); itPoly.next())
{
if (fComponentIDs[nextFaceIndex] == (int)itPoly.index()) break;
}
if (itPoly.isDone())
{
delete [] faceTouched;
return MS::kFailure;
}
MIntArray nextFaceEdgeList;
itPoly.getEdges(nextFaceEdgeList);
edge1 = -1;
for (i = 0; i < edgeList.length(); ++i)
{
for (j = 0; j < nextFaceEdgeList.length(); ++j)
{
if (edgeList[i] == nextFaceEdgeList[j])
{
edge1 = edgeList[i];
break;
}
}
if (edge1 != -1) break;
}
if (edge1 == -1)
{
delete [] faceTouched;
return MS::kFailure;
}
edgeList = nextFaceEdgeList;
}
MPoint edge0vert0, edge0vert1, edge1vert0, edge1vert1;
MItMeshEdge itEdge(fMesh, MObject::kNullObj );
for (; !itEdge.isDone(); itEdge.next())
{
if (itEdge.index() == edge0)
{
edge0vert0 = itEdge.point(0);
edge0vert1 = itEdge.point(1);
}
if (itEdge.index() == edge1)
{
edge1vert0 = itEdge.point(0);
edge1vert1 = itEdge.point(1);
}
}
double distMax = edge0vert0.distanceTo(edge1vert0);
MPoint max0, max1;
max0 = edge0vert0;
max1 = edge1vert0;
double newDist = edge0vert1.distanceTo(edge1vert0);
if (newDist > distMax)
{
max0 = edge0vert1;
max1 = edge1vert0;
distMax = newDist;
}
newDist = edge0vert0.distanceTo(edge1vert1);
if (newDist > distMax)
{
max0 = edge0vert0;
max1 = edge1vert1;
distMax = newDist;
}
newDist = edge0vert1.distanceTo(edge1vert1);
if (newDist > distMax)
{
max0 = edge0vert1;
max1 = edge1vert1;
}
innerVert0 = (faceCenter + max0) / 2.0;
innerVert1 = (faceCenter + max1) / 2.0;
placements.append((int) MFnMesh::kOnEdge);
placements.append((int) MFnMesh::kInternalPoint);
placements.append((int) MFnMesh::kInternalPoint);
if (done) placements.append((int) MFnMesh::kOnEdge);
edgeIDs.append(edge0);
if (done) edgeIDs.append(edge1);
edgeFactors.append(0.5f);
if (done) edgeFactors.append(0.5f);
MFloatPoint point1((float)innerVert0[0], (float)innerVert0[1],
(float)innerVert0[2], (float)innerVert0[3]);
MFloatPoint point2((float)innerVert1[0], (float)innerVert1[1],
(float)innerVert1[2], (float)innerVert1[3]);
internalPoints.append(point1);
internalPoints.append(point2);
edge0 = edge1;
}
delete [] faceTouched;
return meshFn.split(placements, edgeIDs, edgeFactors, internalPoints);
}