📄 ogremayamesh.cpp
字号:
/*
============================================================================
This source file is part of the Ogre-Maya Tools.
Distributed as part of Ogre (Object-oriented Graphics Rendering Engine).
Copyright (C) 2003 Fifty1 Software Inc., Bytelords
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
or go to http://www.gnu.org/licenses/gpl.txt
============================================================================
*/
#include "OgreMayaMesh.h"
#include "OgreMayaOptions.h"
#include <maya/MItGeometry.h>
#include <maya/MFnMesh.h>
#include <maya/MDagPath.h>
#include <maya/MDagPathArray.h>
#include <maya/MSelectionList.h>
#include <maya/MGlobal.h>
#include <maya/MPlug.h>
#include <maya/MFnLambertShader.h>
#include <maya/MFnBlinnShader.h>
#include <maya/MFnPhongShader.h>
#include <maya/MFnReflectShader.h>
#include <maya/MFnSet.h>
#include <maya/MPlugArray.h>
#include <maya/MItDependencyGraph.h>
#include <maya/MItDag.h>
#include <maya/MItDependencyNodes.h>
#include <maya/MFnSkinCluster.h>
#include <iostream>
#include <string>
#include <math.h>
namespace OgreMaya {
using namespace std;
// --------------------------------------------------------------------------
/** Standard constructor. Creates Ogre Mesh and defines known options.
*/
// --------------------------------------------------------------------------
MeshGenerator::MeshGenerator() {
}
// --------------------------------------------------------------------------
/** Destructor.
*/
// --------------------------------------------------------------------------
MeshGenerator::~MeshGenerator()
{
}
// --------------------------------------------------------------------------
/** Finds and exports all polygonal meshes in the DAG. Each polygonal mesh
corresponds to a single Ogre SubMesh.
\return True if exported ok, false otherwise
*/
// --------------------------------------------------------------------------
bool MeshGenerator::exportAll()
{
MStatus status;
bool bStatus = true;
// ===== Iterate over mesh components of DAG
// --- Setup iterator
MItDag iterDag(MItDag::kDepthFirst, MFn::kMesh, &status);
if (status == MStatus::kFailure) {
MGlobal::displayError("MItDag::MItDag");
return false;
}
{
ofstream out(OPTIONS.outMeshFile.c_str());
out.precision(5);
out.setf(ios::fixed);
out << "<mesh>\n";
out << "\t<submeshes>\n";
MSelectionList list;
MGlobal::getActiveSelectionList(list);
// --- Iterate
for(; !iterDag.isDone(); iterDag.next()) {
// Get DAG path
MDagPath dagPath;
status = iterDag.getPath(dagPath);
if (status == MStatus::kFailure) {
MGlobal::displayError("MDagPath::getPath");
bStatus = false;
break;
}
// Process this node?
//if(OPTIONS.exportSelected && !list.hasItem(dagPath.node())) continue;
if( dagPath.hasFn(MFn::kTransform)) continue;
if(!dagPath.hasFn(MFn::kMesh)) continue;
MFnDagNode dagNode(dagPath);
if(dagNode.isIntermediateObject()) continue;
// Process node if visible
bool bVisible;
bVisible = _isVisible(dagNode, status);
if (bVisible && (status == MStatus::kSuccess)) {
status = _processPolyMesh(out, dagPath);
if (status != MStatus::kSuccess) {
break;
}
}
}
out << "\t</submeshes>\n";
if(OPTIONS.exportSkeleton || OPTIONS.exportVBA) {
string skeletonName =
OPTIONS.outSkelFile.substr(
0, OPTIONS.outSkelFile.find_last_of('.')
);
out << "\t<skeletonlink name=\""<<skeletonName<<"\"/>\n";
}
out << "</mesh>\n";
}
// reactivate IK Solver
MGlobal::executeCommand("ikSystem -e -sol 1;");
// ===== Done
return (status == MStatus::kSuccess);
}
// --------------------------------------------------------------------------
/** Process a Maya polyMesh to generate an Ogre SubMesh.
\param dagPath
Path to the Maya polyMesh to be processed
\return MStatus::kSuccess if processed successfuly,
different MStatus otherwise
\todo Vertex optimization
\todo Submesh optimization (merge submeshes that share materials)
*/
// --------------------------------------------------------------------------
MStatus MeshGenerator::_processPolyMesh(ofstream& out, const MDagPath dagPath) {
cout << "\nMeshGenerator::_processPolyMesh\n";
cout << "\tdagPath = \"" << dagPath.fullPathName().asChar() << "\"\n";
MStatus status = MStatus::kSuccess;
MeshMayaGeometry MayaGeometry;
//*******************************************************************
// ===== Calculate the influence of SkinCluter if any
bool hasSkinCluster = false;
//search the skin cluster affecting this geometry
MItDependencyNodes kDepNodeIt( MFn::kSkinClusterFilter );
MFnMesh fnMesh(dagPath, &status);
for( ;!kDepNodeIt.isDone() && !hasSkinCluster; kDepNodeIt.next()) {
MObject kInputObject, kOutputObject;
MObject kObject = kDepNodeIt.item();
MFnSkinCluster kSkinClusterFn(kObject, &status);
cout << "\tskin cluster name: " << kSkinClusterFn.name().asChar() << '\n';
unsigned int uiNumGeometries = kSkinClusterFn.numOutputConnections();
cout << "\tfound " << uiNumGeometries << " geometry object(s) in skin cluster\n";
for(unsigned int uiGeometry = 0; uiGeometry < uiNumGeometries; ++uiGeometry ) {
unsigned int uiIndex = kSkinClusterFn.indexForOutputConnection( uiGeometry, &status );
kInputObject = kSkinClusterFn.inputShapeAtIndex( uiIndex, &status );
kOutputObject = kSkinClusterFn.outputShapeAtIndex( uiIndex, &status );
if(kOutputObject == fnMesh.object()) {
cout << "\tgeometry located in skin cluster\n";
hasSkinCluster = true;
/*
MDagPathArray jointPaths;
kSkinClusterFn.influenceObjects(jointPaths, &status);
int dummy;
string rootName = jointPaths[0].partialPathName(&status).asChar();
MGlobal::executeCommand("ikSystem -e -sol 0;");
MGlobal::selectByName(rootName.c_str());
MGlobal::executeCommand("dagPose -r -g -bp");
*/
// get weights
MItGeometry kGeometryIt(kInputObject);
for(int uiVertex = 0; !kGeometryIt.isDone(); kGeometryIt.next(), ++uiVertex ) {
MObject kComponent = kGeometryIt.component( 0 );
MFloatArray kWeightArray;
unsigned int uiNumInfluences;
kSkinClusterFn.getWeights(dagPath, kComponent, kWeightArray, uiNumInfluences);
MayaGeometry.Weights.push_back(kWeightArray);
}
}
}
}
// ===== Get Maya geometry
status = _queryMayaGeometry(fnMesh, MayaGeometry);
if (status == MStatus::kFailure) {
return status;
}
/*
if(hasSkinCluster) {
MGlobal::executeCommand("ikSystem -e -sol 1;");
}
*/
// ===== Parse into MeshGenerator format
MeshFaceVertexVector FaceVertices;
MeshTriFaceList TriFaces;
status = _parseMayaGeometry(fnMesh, MayaGeometry, FaceVertices, TriFaces);
if (status == MStatus::kFailure) {
return status;
}
////////////////////////////////////////////////////////////////////////////////
// export as XML
out << "\t\t<submesh material=\"" << OPTIONS.matPrefix << MayaGeometry.MaterialName.asChar() << "\" usesharedvertices=\"false\" use32bitindexes=\"false\">\n";
// ===== Create Ogre face list
// --- Basic info
unsigned int nTriFaces = (unsigned int)TriFaces.size();
// --- Store face indices
MeshTriFaceList::iterator faceIt, faceEnd;
faceEnd = TriFaces.end();
out << "\t\t\t<faces count=\"" << nTriFaces << "\">\n";
for(faceIt=TriFaces.begin(); faceIt!=faceEnd; ++faceIt) {
out << "\t\t\t\t<face ";
out << "v1=\"" << faceIt->index0 << "\" ";
out << "v2=\"" << faceIt->index1 << "\" ";
out << "v3=\"" << faceIt->index2 << "\"/>\n";
}
out << "\t\t\t</faces>\n";
out << "\t\t\t<geometry vertexcount=\"" << FaceVertices.size() << "\">\n";
MeshFaceVertexVector::iterator vertexIt, vertexEnd;
vertexEnd = FaceVertices.end();
//
// POSITIONS
//
out << "\t\t\t\t<vertexbuffer ";
out << "positions=\"true\"";
if(OPTIONS.exportNormals)
out << " normals=\"true\"";
if(OPTIONS.exportColours)
out << " colours_diffuse=\"true\"";
if(MayaGeometry.UVSets.size() > 0 && OPTIONS.exportUVs)
out << " texture_coords=\"" << MayaGeometry.UVSets.size() << "\"";
out << ">\n";
for(vertexIt=FaceVertices.begin(); vertexIt!=vertexEnd; ++vertexIt) {
out << "\t\t\t\t\t<vertex>\n";
out << "\t\t\t\t\t\t<position ";
out << "x=\"" << vertexIt->vecPosition.x << "\" ";
out << "y=\"" << vertexIt->vecPosition.y << "\" ";
out << "z=\"" << vertexIt->vecPosition.z << "\"/>\n";
if(OPTIONS.exportNormals) {
out << "\t\t\t\t\t\t<normal ";
out << "x=\"" << vertexIt->vecNormal.x << "\" ";
out << "y=\"" << vertexIt->vecNormal.y << "\" ";
out << "z=\"" << vertexIt->vecNormal.z << "\"/>\n";
}
if(OPTIONS.exportColours) {
out << "\t\t\t\t\t\t<colour_diffuse value=\"";
out << vertexIt->colour.r << " ";
out << vertexIt->colour.g << " ";
out << vertexIt->colour.b << " ";
out << vertexIt->colour.a << "\"/>\n";
}
if(MayaGeometry.UVSets.size() > 0 && OPTIONS.exportUVs) {
MeshVertexUVList::iterator uvIt, uvEnd;
uvEnd = vertexIt->listUV.end();
for (uvIt = vertexIt->listUV.begin(); uvIt!=uvEnd; ++uvIt) {
float u,v;
u = uvIt->u;
//v = 1.0f - uvIt->v;
v = uvIt->v;
out << "\t\t\t\t\t\t<texcoord ";
out << "u=\"" << u << "\" ";
out << "v=\"" << v << "\"/>\n";
}
}
out << "\t\t\t\t\t</vertex>\n";
}
out << "\t\t\t\t</vertexbuffer>\n";
out << "\t\t\t</geometry>\n";
// BONE ASSIGMENTS
if(OPTIONS.exportVBA || OPTIONS.exportSkeleton) {
out << "\t\t\t<boneassignments>\n";
int i;
for(i=0, vertexIt=FaceVertices.begin(); vertexIt!=vertexEnd; ++vertexIt, i++) {
VertexBoneAssigmentList::iterator boneIt, boneEnd;
boneEnd = vertexIt->boneAssigments.end();
for (boneIt=vertexIt->boneAssigments.begin(); boneIt!=boneEnd; ++boneIt) {
VertexBoneAssigment& assigment = *boneIt;
if(assigment.weight<0.01)
continue;
out << "\t\t\t\t<vertexboneassignment ";
out << "vertexindex=\""<<i<<"\" ";
out << "boneindex=\""<<assigment.boneId<<"\" ";
out << "weight=\""<<assigment.weight<<"\"/>\n";
}
}
out << "\t\t\t</boneassignments>\n";
}
out << "\t\t</submesh>\n";
////////////////////////////////////////////////////////////////////////////////
// ===== Success!
return MStatus::kSuccess;
}
MString MeshGenerator::getMaterialName(MFnMesh &fnMesh) {
MStatus status = MStatus::kSuccess;
MString MaterialName = "";
// ===== Connected sets and members
// (Required to determine texturing of different faces)
// Determine instance number
MDagPath meshPath = fnMesh.dagPath();
meshPath.extendToShape();
int iInstance = 0;
if (meshPath.isInstanced()) {
iInstance = meshPath.instanceNumber();
}
// Get the connected sets and members
MObjectArray PolygonSets;
MObjectArray PolygonComponents;
status = fnMesh.getConnectedSetsAndMembers(iInstance,
PolygonSets,
PolygonComponents,
true);
if (!status) {
MGlobal::displayError("MFnMesh::getConnectedSetsAndMembers");
return MaterialName;
}
// ===== Materials
unsigned int iSet;
for (iSet = 0; iSet < PolygonSets.length(); ++iSet) {
MObject PolygonSet = PolygonSets[iSet];
MObject PolygonComponent = PolygonComponents[iSet];
MFnDependencyNode dnSet(PolygonSet);
MObject ssAttr = dnSet.attribute(MString("surfaceShader"));
MPlug ssPlug(PolygonSet, ssAttr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -