749 lines
24 KiB
C++
Executable File
749 lines
24 KiB
C++
Executable File
//-----------------------------/------------------------------------------------
|
|
// Torque Game Engine
|
|
// Copyright (C) GarageGames.com, Inc.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning(disable : 4786)
|
|
#endif
|
|
|
|
#include "mayaAppMesh.h"
|
|
#include "mayaAppNode.h"
|
|
#include "appConfig.h"
|
|
#include "appIfl.h"
|
|
#include <maya/MFnDependencyNode.h>
|
|
#include <maya/MFnDagNode.h>
|
|
#include <maya/MGlobal.h>
|
|
#include <maya/MTime.h>
|
|
#include <maya/MDistance.h>
|
|
#include <maya/MMatrix.h>
|
|
#include <maya/MPlug.h>
|
|
#include <maya/MDGContext.h>
|
|
#include <maya/MAnimUtil.h>
|
|
#include <maya/MFnMesh.h>
|
|
#include <maya/MFnSet.h>
|
|
#include <maya/MItMeshPolygon.h>
|
|
#include <maya/MItMeshVertex.h>
|
|
#include <maya/MItDependencyGraph.h>
|
|
#include <maya/MItGeometry.h>
|
|
#include <maya/MFnSkinCluster.h>
|
|
#include <maya/MDagPathArray.h>
|
|
#include <maya/MFnReflectShader.h>
|
|
|
|
namespace DTS
|
|
{
|
|
|
|
bool getMeshAndSkin(MDagPath & path, MFnSkinCluster & skinCluster)
|
|
{
|
|
MStatus status;
|
|
|
|
// The following is the "correct" way to get the
|
|
// mesh and skinCluster in case the mesh is a skin,
|
|
// according to (and adapted from):
|
|
// http://www.greggman.com/pages/mayastuff.htm
|
|
// But we don't get the MeshFn from the input plug of the
|
|
// skinCluster as he does. Two reasons for this:
|
|
// 1) couldn't get it to work properly, not a valid MeshFn.
|
|
// 2) we want the final mesh, not the intermediate product.
|
|
|
|
// the deformed mesh comes into the visible mesh
|
|
// through its "inmesh" plug
|
|
MPlug inMeshPlug = MFnDagNode(path).findPlug("inMesh", &status);
|
|
if (status != MS::kSuccess || !inMeshPlug.isConnected())
|
|
return false; // no skin found
|
|
|
|
// walk the tree of stuff upstream from this plug
|
|
MItDependencyGraph dgIt(inMeshPlug,MFn::kInvalid,
|
|
MItDependencyGraph::kUpstream,
|
|
MItDependencyGraph::kDepthFirst,
|
|
MItDependencyGraph::kPlugLevel,
|
|
&status);
|
|
|
|
if (MS::kSuccess == status)
|
|
{
|
|
S32 count = 0;
|
|
dgIt.disablePruningOnFilter();
|
|
|
|
for ( ; ! dgIt.isDone(); dgIt.next() )
|
|
{
|
|
MObject thisNode = dgIt.thisNode();
|
|
|
|
// go until we find a skinCluster
|
|
|
|
if (thisNode.apiType() == MFn::kSkinClusterFilter)
|
|
{
|
|
skinCluster.setObject(thisNode);
|
|
return true; // found a skin
|
|
}
|
|
}
|
|
}
|
|
return false; // no skin found
|
|
}
|
|
|
|
MayaAppMesh::MayaAppMesh(MDagPath & nodePath, MDagPath & path)
|
|
{
|
|
mPath = path;
|
|
mNodePath = nodePath;
|
|
mName = NULL;
|
|
}
|
|
|
|
MayaAppMesh::~MayaAppMesh()
|
|
{
|
|
}
|
|
|
|
void MayaAppMesh::getSkinData()
|
|
{
|
|
MFnSkinCluster skinCluster;
|
|
if (!getMeshAndSkin(mPath,skinCluster))
|
|
return; // no skin, no sweat
|
|
|
|
MStatus status;
|
|
S32 i;
|
|
|
|
// get bones/influence array
|
|
MDagPathArray bones;
|
|
S32 numBones = skinCluster.influenceObjects(bones, &status);
|
|
if (!CheckMayaStatus(status))
|
|
return;
|
|
|
|
S32 bone;
|
|
for (bone=0; bone<numBones; bone++)
|
|
{
|
|
AppConfig::PrintDump(PDObjectStateDetails,avar("Adding bone %s\r\n",bones[bone].partialPathName().asChar()));
|
|
mBones.push_back(new MayaAppNode(bones[bone]));
|
|
mWeights.push_back(new std::vector<F32>);
|
|
}
|
|
|
|
MItGeometry gitr(mPath,&status);
|
|
if (!CheckMayaStatus(status))
|
|
return;
|
|
|
|
AppConfig::PrintDump(PDObjectStateDetails,avar("SkinPath: %s, # verts: %i, # bones: %i",
|
|
mPath.partialPathName().asChar(),gitr.count(),numBones));
|
|
|
|
for (; !gitr.isDone(); gitr.next())
|
|
{
|
|
while ( numBones && mWeights[0]->size() <= gitr.index())
|
|
for (i=0; i<numBones; i++)
|
|
mWeights[i]->push_back(0.0f);
|
|
|
|
MObject comp = gitr.component(&status);
|
|
if (!CheckMayaStatus(status))
|
|
return;
|
|
|
|
MFloatArray wts;
|
|
U32 weightCount;
|
|
status = skinCluster.getWeights(mPath,comp,wts,weightCount);
|
|
if (!CheckMayaStatus(status))
|
|
return;
|
|
if (weightCount != numBones)
|
|
{
|
|
AppConfig::SetExportError("Assertion failed on skinned mesh");
|
|
return;
|
|
}
|
|
for (i=0; i<numBones; i++)
|
|
(*mWeights[i])[gitr.index()] = wts[i];
|
|
}
|
|
|
|
// make sure we have weights for all bones and verts
|
|
S32 numVerts = MFnMesh(mPath,&status).numVertices();
|
|
if (!CheckMayaStatus(status))
|
|
return;
|
|
while ( numBones && mWeights[0]->size() < numVerts)
|
|
for (i=0; i<numBones; i++)
|
|
mWeights[i]->push_back(0.0f);
|
|
}
|
|
|
|
const char * MayaAppMesh::getName()
|
|
{
|
|
MStatus status;
|
|
if (!mName)
|
|
{
|
|
MFnDagNode fnNode(mNodePath,&status);
|
|
CheckMayaStatus(status);
|
|
const char * newname = fnNode.name(&status).asChar();
|
|
CheckMayaStatus(status);
|
|
if (newname)
|
|
{
|
|
mName = strnew(newname);
|
|
HandleMayaNegative(mName);
|
|
}
|
|
}
|
|
CheckMayaStatus(status);
|
|
return mName;
|
|
}
|
|
|
|
Matrix<4,4,F32> MayaAppMesh::getMeshTransform(const AppTime & time)
|
|
{
|
|
MStatus status;
|
|
MayaSetTime(time);
|
|
MMatrix mayaMat = mPath.inclusiveMatrix(&status);
|
|
CheckMayaStatus(status);
|
|
return MayaToDtsTransform(mayaMat);
|
|
}
|
|
|
|
F32 MayaAppMesh::getVisValue(const AppTime & time)
|
|
{
|
|
// Need to check for "visibility" plug, which is built into
|
|
// maya and is a bool, and "vis" plug, which is custom and
|
|
// assumed to be a float. We added the "vis" plug to allow
|
|
// non-bool vis values. The "vis" plug takes precedence.
|
|
MayaSetTime(time);
|
|
|
|
F32 val = 1.0f;
|
|
if (getFloat("vis",val))
|
|
return val;
|
|
bool ret = true;
|
|
getBool("visibility",ret);
|
|
return ret ? 1.0f : 0.0f;
|
|
}
|
|
|
|
bool MayaAppMesh::getFloat(const char * propName, F32 & defaultVal)
|
|
{
|
|
MStatus status;
|
|
|
|
MFnDagNode fnNode(mNodePath,&status);
|
|
CheckMayaStatus(status);
|
|
|
|
MPlug plug = fnNode.findPlug(MString(propName),&status);
|
|
if (status!=MStatus::kSuccess)
|
|
return false;
|
|
|
|
F32 val;
|
|
status = plug.getValue(val);
|
|
if (status == MStatus::kSuccess)
|
|
defaultVal = val;
|
|
return status==MStatus::kSuccess;
|
|
}
|
|
|
|
bool MayaAppMesh::getInt(const char * propName, S32 & defaultVal)
|
|
{
|
|
MStatus status;
|
|
|
|
MFnDagNode fnNode(mNodePath,&status);
|
|
CheckMayaStatus(status);
|
|
|
|
MPlug plug = fnNode.findPlug(MString(propName),&status);
|
|
if (status!=MStatus::kSuccess)
|
|
return false;
|
|
|
|
S32 val;
|
|
status = plug.getValue(val);
|
|
if (status == MStatus::kSuccess)
|
|
defaultVal = val;
|
|
return status==MStatus::kSuccess;
|
|
}
|
|
|
|
bool MayaAppMesh::getBool(const char * propName, bool & defaultVal)
|
|
{
|
|
MStatus status;
|
|
|
|
MFnDagNode fnNode(mNodePath,&status);
|
|
CheckMayaStatus(status);
|
|
|
|
MPlug plug = fnNode.findPlug(MString(propName),&status);
|
|
if (status!=MStatus::kSuccess)
|
|
return false;
|
|
|
|
bool val;
|
|
status = plug.getValue(val);
|
|
if (status == MStatus::kSuccess)
|
|
defaultVal = val;
|
|
return status==MStatus::kSuccess;
|
|
}
|
|
|
|
bool MayaAppMesh::getMaterial(S32 matIdx, Material & mat)
|
|
{
|
|
if (matIdx>=0 && matIdx<mMaterials.size())
|
|
{
|
|
mat = mMaterials[matIdx];
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool MayaAppMesh::animatesVis(const AppSequenceData & seqData)
|
|
{
|
|
MStatus status;
|
|
|
|
// Need to check to see if either "visibility" or "vis" is animated.
|
|
// "visibility" is the built-in visibility mechanism, but it is
|
|
// only a bool. So we also look for custom "vis" which is assumed
|
|
// to be a float.
|
|
|
|
MFnDagNode fnNode(mNodePath,&status);
|
|
CheckMayaStatus(status);
|
|
|
|
MPlug plug = fnNode.findPlug(MString("visibility"),&status);
|
|
CheckMayaStatus(status);
|
|
if (status!=MStatus::kSuccess)
|
|
return false;
|
|
|
|
if (MAnimUtil::isAnimated(plug,false,&status))
|
|
return Parent::animatesVis(seqData);
|
|
CheckMayaStatus(status);
|
|
|
|
// don't animate "visibility", what about "vis"
|
|
MPlug plug2 = fnNode.findPlug(MString("vis"),&status);
|
|
if (status!=MStatus::kSuccess)
|
|
return false;
|
|
if (MAnimUtil::isAnimated(plug2,false,&status))
|
|
return Parent::animatesVis(seqData);
|
|
|
|
return false;
|
|
}
|
|
|
|
AppMeshLock MayaAppMesh::lockMesh(const AppTime & time, const Matrix<4,4,F32> & objectOffset)
|
|
{
|
|
S32 i;
|
|
MayaSetTime(time);
|
|
|
|
MStatus status;
|
|
MObject component = MObject::kNullObj; // not really sure what this is for...
|
|
|
|
MFnMesh fnMesh(mPath,&status);
|
|
if (!CheckMayaStatus(status))
|
|
return (AppMeshLock&)Parent::lockMesh(time,objectOffset);
|
|
|
|
MItMeshPolygon polyIter(mPath,component,&status);
|
|
if (!CheckMayaStatus(status))
|
|
return (AppMeshLock&)Parent::lockMesh(time,objectOffset);
|
|
S32 polyVertexCount = polyIter.polygonVertexCount();
|
|
if (polyVertexCount != 3)
|
|
{
|
|
AppConfig::SetExportError("Non-triangle mesh not supported");
|
|
return (AppMeshLock&)Parent::lockMesh(time,objectOffset);
|
|
}
|
|
|
|
MItMeshVertex vtxIter(mPath,component,&status);
|
|
if (!CheckMayaStatus(status))
|
|
return (AppMeshLock&)Parent::lockMesh(time,objectOffset);
|
|
|
|
// Create transform based on objectOffset for transforming normals
|
|
Matrix<4,4,F32> normOffset = objectOffset;
|
|
normOffset[0][3] = 0.0f;
|
|
normOffset[1][3] = 0.0f;
|
|
normOffset[2][3] = 0.0f;
|
|
normOffset[3][0] = 0.0f;
|
|
normOffset[3][1] = 0.0f;
|
|
normOffset[3][2] = 0.0f;
|
|
normOffset[3][3] = 1.0f;
|
|
F32 normScale = 0.0f;
|
|
for (i=0; i<9; i++)
|
|
{
|
|
S32 j = i % 3;
|
|
normScale += normOffset[(i-j)/3][j];
|
|
}
|
|
normScale /= 3.0f;
|
|
normScale = 1.0f/normScale;
|
|
|
|
// Write out the vertex table
|
|
//
|
|
|
|
std::vector<Point3D> verts;
|
|
std::vector<Point2D> tverts;
|
|
for ( ; !vtxIter.isDone(); vtxIter.next() )
|
|
{
|
|
MPoint p = vtxIter.position( MSpace::kObject );
|
|
// convert from maya point to dts point...
|
|
// ...also, convert from internal units
|
|
// to the current ui units
|
|
Point3D pos;
|
|
MDistance dist; // starts as internal units
|
|
|
|
dist.setValue(p.x);
|
|
pos[0] = dist.asMeters();
|
|
dist.setValue(p.y);
|
|
pos[1] = dist.asMeters();
|
|
dist.setValue(p.z);
|
|
pos[2] = dist.asMeters();
|
|
verts.push_back(objectOffset * pos);
|
|
}
|
|
|
|
MFloatArray uArray, vArray;
|
|
fnMesh.getUVs( uArray, vArray );
|
|
S32 uvLength = uArray.length();
|
|
for (i=0; i<uvLength; i++ )
|
|
{
|
|
Point2D tvert(uArray[i],1.0f-vArray[i]);
|
|
tverts.push_back(tvert);
|
|
}
|
|
|
|
for ( ; !polyIter.isDone(); polyIter.next() )
|
|
{
|
|
Primitive face;
|
|
face.firstElement = mIndices.size();
|
|
face.numElements = 3;
|
|
face.type = Primitive::Triangles|Primitive::Indexed|Primitive::NoMaterial;
|
|
|
|
for (S32 vtx=polyVertexCount-1; vtx>=0; vtx-- )
|
|
{
|
|
U16 vertId = polyIter.vertexIndex(vtx);
|
|
Point3D vert = verts[vertId];
|
|
|
|
// compute normal (TODO: handle non-uniform scale properly)
|
|
MVector mayaNorm;
|
|
status = polyIter.getNormal(vtx,mayaNorm,MSpace::kObject);
|
|
if (!CheckMayaStatus(status))
|
|
return (AppMeshLock&)Parent::lockMesh(time,objectOffset);
|
|
Point3D norm(mayaNorm[0],mayaNorm[1],mayaNorm[2]);
|
|
norm = normOffset * norm;
|
|
norm *= normScale;
|
|
if (norm.length()>0.001f)
|
|
norm.normalize();
|
|
else
|
|
norm = Point3D(0,0,1);
|
|
|
|
// grab tvert
|
|
Point2D tvert(0,0);
|
|
if (fnMesh.numUVs() > 0)
|
|
{
|
|
if (polyIter.hasUVs())
|
|
{
|
|
S32 uvIndex;
|
|
if (polyIter.getUVIndex(vtx,uvIndex))
|
|
tvert = tverts[uvIndex];
|
|
}
|
|
}
|
|
|
|
mIndices.push_back(addVertex(vert,norm,tvert,vertId));
|
|
}
|
|
mFaces.push_back(face);
|
|
}
|
|
|
|
getMaterials();
|
|
|
|
// are we 2-sided?
|
|
bool twoSided = false;
|
|
getBool("twoSided",twoSided);
|
|
if (twoSided)
|
|
{
|
|
S32 numFaces = mFaces.size();
|
|
for (i=0; i<numFaces; i++)
|
|
{
|
|
S32 first = mFaces[i].firstElement;
|
|
|
|
Primitive face;
|
|
face.firstElement = mIndices.size();
|
|
face.numElements = 3;
|
|
face.type = mFaces[i].type;
|
|
|
|
Point3D vert = mVerts[mIndices[first + 0]];
|
|
Point2D tvert = mTVerts[mIndices[first + 0]];
|
|
Point3D norm = -mNormals[mIndices[first + 0]];
|
|
S32 vertId = mVertId[mIndices[first + 0]];
|
|
mIndices.push_back(addVertex(vert,norm,tvert,vertId));
|
|
|
|
vert = mVerts[mIndices[first + 2]];
|
|
tvert = mTVerts[mIndices[first + 2]];
|
|
norm = -mNormals[mIndices[first + 2]];
|
|
vertId = mVertId[mIndices[first + 2]];
|
|
mIndices.push_back(addVertex(vert,norm,tvert,vertId));
|
|
|
|
vert = mVerts[mIndices[first + 1]];
|
|
tvert = mTVerts[mIndices[first + 1]];
|
|
norm = -mNormals[mIndices[first + 1]];
|
|
vertId = mVertId[mIndices[first + 1]];
|
|
mIndices.push_back(addVertex(vert,norm,tvert,vertId));
|
|
mFaces.push_back(face);
|
|
}
|
|
}
|
|
|
|
return (AppMeshLock&)Parent::lockMesh(time,objectOffset);
|
|
}
|
|
|
|
void MayaAppMesh::getMaterials()
|
|
{
|
|
// Maya material extraction code pulled from
|
|
// findTexturesPerPolyCmd.cpp from Maya sample plugins.
|
|
|
|
MStatus status;
|
|
|
|
S32 instanceNum = 0;
|
|
if (mPath.isInstanced())
|
|
instanceNum = mPath.instanceNumber();
|
|
|
|
// Get a list of all sets pertaining to the selected shape and the
|
|
// members of those sets.
|
|
MFnMesh fnMesh(mPath);
|
|
MObjectArray sets;
|
|
MObjectArray comps;
|
|
if (!fnMesh.getConnectedSetsAndMembers(instanceNum, sets, comps, true))
|
|
{
|
|
AppConfig::SetExportError("ERROR: getMaterials: MFnMesh::getConnectedSetsAndMembers\r\n");
|
|
return;
|
|
}
|
|
|
|
// This is a (hack) workaround. If we already have got at least one
|
|
// material, don't accept mesh iterators that include the whole mesh
|
|
// (would be an error anyway).
|
|
bool gotOne = false;
|
|
|
|
// Loop through all the sets. If the set is a polygonal set, find the
|
|
// shader attached to the and print out the texture file name for the
|
|
// set along with the polygons in the set.
|
|
//
|
|
for ( S32 i=0; i<sets.length(); i++ )
|
|
{
|
|
MObject set = sets[i];
|
|
MObject comp = comps[i];
|
|
|
|
MFnSet fnSet( set, &status );
|
|
if (MS::kFailure == status)
|
|
{
|
|
AppConfig::SetExportError("ERROR: getMaterials: MFnSet::MFnSet\r\n");
|
|
return;
|
|
}
|
|
|
|
// Special (hack) case in which we have an iterator over everything
|
|
// yet we already have got at least one material...
|
|
if (gotOne && (comp.apiType() == MFn::kInvalid))
|
|
continue;
|
|
|
|
// Make sure the set is a polygonal set. If not, continue.
|
|
MItMeshPolygon piter(mPath, comp, &status);
|
|
if (MS::kFailure == status)
|
|
continue;
|
|
|
|
// Find the texture that is applied to this set. First, get the
|
|
// shading node connected to the set. Then, if there is an input
|
|
// attribute called "color", search upstream from it for a texture
|
|
// file node.
|
|
MObject shaderNode = findShader(set);
|
|
if (shaderNode == MObject::kNullObj)
|
|
continue;
|
|
|
|
MPlug colorPlug = MFnDependencyNode(shaderNode).findPlug("color", &status);
|
|
if (status == MS::kFailure)
|
|
continue;
|
|
|
|
MItDependencyGraph dgIt(colorPlug, MFn::kFileTexture,
|
|
MItDependencyGraph::kUpstream,
|
|
MItDependencyGraph::kBreadthFirst,
|
|
MItDependencyGraph::kNodeLevel,
|
|
&status);
|
|
|
|
if (status == MS::kFailure)
|
|
continue;
|
|
|
|
dgIt.disablePruningOnFilter();
|
|
|
|
// If no texture file node was found, just continue.
|
|
if (dgIt.isDone())
|
|
continue;
|
|
|
|
// Print out the texture node name and texture file that it references.
|
|
//
|
|
MObject textureNode = dgIt.thisNode();
|
|
MPlug filenamePlug = MFnDependencyNode(textureNode).findPlug("fileTextureName");
|
|
MString textureName;
|
|
filenamePlug.getValue(textureName);
|
|
|
|
|
|
// look for filename plug on transparency channel -- if it has one, material is translucent
|
|
bool hasTransparency = false;
|
|
MPlug transPlug = MFnDependencyNode(shaderNode).findPlug("transparency", &status);
|
|
if (status == MS::kFailure)
|
|
continue;
|
|
|
|
dgIt.resetTo(transPlug, MFn::kFileTexture,
|
|
MItDependencyGraph::kUpstream,
|
|
MItDependencyGraph::kBreadthFirst,
|
|
MItDependencyGraph::kNodeLevel);
|
|
|
|
dgIt.disablePruningOnFilter();
|
|
|
|
// If no texture file node was found, just continue.
|
|
if (!dgIt.isDone())
|
|
{
|
|
// Print out the texture node name and texture file that it references.
|
|
//
|
|
MObject textureNode = dgIt.thisNode();
|
|
MPlug filenamePlug = MFnDependencyNode(textureNode).findPlug("fileTextureName");
|
|
MString textureName;
|
|
filenamePlug.getValue(textureName);
|
|
if (textureName.length() != 0)
|
|
hasTransparency = true;
|
|
}
|
|
|
|
for (; !piter.isDone(); piter.next())
|
|
{
|
|
S32 faceIdx = piter.index();
|
|
if (mFaces[faceIdx].type & Primitive::NoMaterial)
|
|
{
|
|
mFaces[faceIdx].type ^= Primitive::NoMaterial;
|
|
mFaces[faceIdx].type |= mMaterials.size();
|
|
|
|
// we have at least one material now
|
|
gotOne = true;
|
|
}
|
|
else
|
|
AppConfig::SetExportError("Mesh::getMaterials: face with multiple materials found");
|
|
}
|
|
|
|
Material mat;
|
|
mat.name = textureName.asChar();
|
|
mat.reflectance = -1;
|
|
mat.bump = -1;
|
|
mat.detail = -1;
|
|
mat.detailScale = 1.0f;
|
|
mat.reflection = 0.0f;
|
|
mat.flags = Material::SWrap|Material::TWrap|Material::NeverEnvMap;
|
|
|
|
MFnLambertShader lshader(shaderNode,&status);
|
|
if (status == MStatus::kSuccess)
|
|
{
|
|
F32 translucence = lshader.translucenceCoeff();
|
|
F32 selfIlluminating = lshader.glowIntensity();
|
|
if (translucence>0.1f || hasTransparency)
|
|
mat.flags |= Material::Translucent;
|
|
if (selfIlluminating>0.1f)
|
|
mat.flags |= Material::SelfIlluminating;
|
|
}
|
|
MFnReflectShader rshader(shaderNode,&status);
|
|
if (status == MStatus::kSuccess)
|
|
{
|
|
F32 reflectivity = rshader.reflectivity();
|
|
if (reflectivity>0.01f)
|
|
{
|
|
mat.reflection = reflectivity;
|
|
mat.flags ^= Material::NeverEnvMap;
|
|
}
|
|
|
|
}
|
|
|
|
// now get the texture placement node
|
|
status = dgIt.resetTo(colorPlug, MFn::kPlace2dTexture,
|
|
MItDependencyGraph::kUpstream,
|
|
MItDependencyGraph::kBreadthFirst,
|
|
MItDependencyGraph::kNodeLevel);
|
|
|
|
dgIt.disablePruningOnFilter();
|
|
if (status != MS::kFailure)
|
|
if (!dgIt.isDone())
|
|
{
|
|
MObject placeNode = dgIt.thisNode();
|
|
|
|
MStatus stat;
|
|
|
|
MFnDependencyNode fnNode(placeNode,&stat);
|
|
|
|
bool swrap = true;
|
|
bool twrap = true;
|
|
MPlug plug = fnNode.findPlug(MString("wrapU"),&stat);
|
|
plug.getValue(swrap);
|
|
plug = fnNode.findPlug(MString("wrapV"),&stat);
|
|
plug.getValue(swrap);
|
|
|
|
if (!swrap)
|
|
mat.flags ^= Material::SWrap;
|
|
if (!twrap)
|
|
mat.flags ^= Material::TWrap;
|
|
}
|
|
|
|
/*
|
|
Need to deal with these flags:
|
|
Additive = 0x00000008,
|
|
Subtractive = 0x00000010,
|
|
IFLMaterial = 0x08000000,
|
|
*/
|
|
|
|
//------------
|
|
// If this is an ifl, then create the ifl material if it doesn't exist and mark as ifl
|
|
const char * dot = strchr(textureName.asChar(),'.');
|
|
if (dot && !stricmp(dot+1,"ifl"))
|
|
{
|
|
mat.flags |= Material::IFLMaterial;
|
|
S32 matIdx = mMaterials.size();
|
|
while (mIfls.size()<=matIdx)
|
|
mIfls.push_back(NULL);
|
|
if (!mIfls[matIdx])
|
|
mIfls[matIdx] = new AppIfl(mat.name.c_str());
|
|
}
|
|
|
|
mMaterials.push_back(mat);
|
|
}
|
|
}
|
|
|
|
|
|
MObject MayaAppMesh::findShader( MObject& setNode )
|
|
{
|
|
// Description: Find the shading node for the given shading group set node.
|
|
MFnDependencyNode fnNode(setNode);
|
|
MPlug shaderPlug = fnNode.findPlug("surfaceShader");
|
|
|
|
if (!shaderPlug.isNull())
|
|
{
|
|
MPlugArray connectedPlugs;
|
|
bool asSrc = false;
|
|
bool asDst = true;
|
|
shaderPlug.connectedTo( connectedPlugs, asDst, asSrc );
|
|
|
|
if (connectedPlugs.length() != 1)
|
|
AppConfig::SetExportError("Error getting shader\r\n");
|
|
else
|
|
return connectedPlugs[0].node();
|
|
}
|
|
|
|
return MObject::kNullObj;
|
|
}
|
|
|
|
void MayaAppMesh::unlockMesh()
|
|
{
|
|
Parent::unlockMesh();
|
|
|
|
// no more cleanup...but if there were some to do, we'd do it here
|
|
}
|
|
|
|
void MayaSetTime(const AppTime & time)
|
|
{
|
|
MTime mayaTime(time.getF64(),MTime::kSeconds);
|
|
MGlobal::viewFrame(mayaTime);
|
|
}
|
|
|
|
Matrix<4,4,F32> MayaToDtsTransform(MMatrix & mayaMat)
|
|
{
|
|
Matrix<4,4,F32> mat;
|
|
for (S32 i=0; i<4; i++)
|
|
for (S32 j=0; j<4; j++)
|
|
mat[j][i] = mayaMat[i][j];
|
|
|
|
F64 scale;
|
|
MDistance dist; // starts as internal units
|
|
dist.setValue(1.0f);
|
|
scale = dist.asMeters();
|
|
|
|
mat[0][3] *= scale;
|
|
mat[1][3] *= scale;
|
|
mat[2][3] *= scale;
|
|
|
|
return mat;
|
|
}
|
|
|
|
bool CheckMayaStatus(MStatus & status)
|
|
{
|
|
if (!bool(status))
|
|
{
|
|
AppConfig::SetExportError(avar("Maya error: %s",status.errorString().asChar()));
|
|
status = MStatus::kSuccess;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void HandleMayaNegative(char * name)
|
|
{
|
|
S32 pos = strlen(name);
|
|
while (pos)
|
|
{
|
|
--pos;
|
|
if (isdigit(name[pos]))
|
|
continue;
|
|
if (name[pos]=='_')
|
|
name[pos]='-';
|
|
break;
|
|
}
|
|
}
|
|
|
|
}; // namespace DTS
|