1 | /*
|
---|
2 | ============================================================================
|
---|
3 | This source file is part of the Ogre-Maya Tools.
|
---|
4 | Distributed as part of Ogre (Object-oriented Graphics Rendering Engine).
|
---|
5 | Copyright (C) 2003 Fifty1 Software Inc., Bytelords
|
---|
6 |
|
---|
7 | This program is free software; you can redistribute it and/or
|
---|
8 | modify it under the terms of the GNU General Public License
|
---|
9 | as published by the Free Software Foundation; either version 2
|
---|
10 | of the License, or (at your option) any later version.
|
---|
11 |
|
---|
12 | This program is distributed in the hope that it will be useful,
|
---|
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
15 | GNU General Public License for more details.
|
---|
16 |
|
---|
17 | You should have received a copy of the GNU General Public License
|
---|
18 | along with this program; if not, write to the Free Software
|
---|
19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
---|
20 | or go to http://www.gnu.org/licenses/gpl.txt
|
---|
21 | ============================================================================
|
---|
22 | */
|
---|
23 | #include "OgreMayaMesh.h"
|
---|
24 | #include "OgreMayaOptions.h"
|
---|
25 |
|
---|
26 | #include <maya/MItGeometry.h>
|
---|
27 | #include <maya/MFnMesh.h>
|
---|
28 | #include <maya/MDagPath.h>
|
---|
29 | #include <maya/MDagPathArray.h>
|
---|
30 | #include <maya/MSelectionList.h>
|
---|
31 | #include <maya/MGlobal.h>
|
---|
32 | #include <maya/MPlug.h>
|
---|
33 | #include <maya/MFnLambertShader.h>
|
---|
34 | #include <maya/MFnBlinnShader.h>
|
---|
35 | #include <maya/MFnPhongShader.h>
|
---|
36 | #include <maya/MFnReflectShader.h>
|
---|
37 | #include <maya/MFnSet.h>
|
---|
38 | #include <maya/MPlugArray.h>
|
---|
39 | #include <maya/MItDependencyGraph.h>
|
---|
40 | #include <maya/MItDag.h>
|
---|
41 |
|
---|
42 | #include <maya/MItDependencyNodes.h>
|
---|
43 | #include <maya/MFnSkinCluster.h>
|
---|
44 |
|
---|
45 | #include <iostream>
|
---|
46 | #include <string>
|
---|
47 |
|
---|
48 | #include <math.h>
|
---|
49 |
|
---|
50 | namespace OgreMaya {
|
---|
51 |
|
---|
52 | using namespace std;
|
---|
53 |
|
---|
54 | // --------------------------------------------------------------------------
|
---|
55 | /** Standard constructor. Creates Ogre Mesh and defines known options.
|
---|
56 | */
|
---|
57 | // --------------------------------------------------------------------------
|
---|
58 | MeshGenerator::MeshGenerator() {
|
---|
59 | }
|
---|
60 |
|
---|
61 |
|
---|
62 | // --------------------------------------------------------------------------
|
---|
63 | /** Destructor.
|
---|
64 | */
|
---|
65 | // --------------------------------------------------------------------------
|
---|
66 | MeshGenerator::~MeshGenerator()
|
---|
67 | {
|
---|
68 | }
|
---|
69 |
|
---|
70 |
|
---|
71 | // --------------------------------------------------------------------------
|
---|
72 | /** Finds and exports all polygonal meshes in the DAG. Each polygonal mesh
|
---|
73 | corresponds to a single Ogre SubMesh.
|
---|
74 |
|
---|
75 | \return True if exported ok, false otherwise
|
---|
76 | */
|
---|
77 | // --------------------------------------------------------------------------
|
---|
78 | bool MeshGenerator::exportAll()
|
---|
79 | {
|
---|
80 | MStatus status;
|
---|
81 | bool bStatus = true;
|
---|
82 |
|
---|
83 | // ===== Iterate over mesh components of DAG
|
---|
84 |
|
---|
85 | // --- Setup iterator
|
---|
86 | MItDag iterDag(MItDag::kDepthFirst, MFn::kMesh, &status);
|
---|
87 | if (status == MStatus::kFailure) {
|
---|
88 | MGlobal::displayError("MItDag::MItDag");
|
---|
89 | return false;
|
---|
90 | }
|
---|
91 |
|
---|
92 |
|
---|
93 | {
|
---|
94 | ofstream out(OPTIONS.outMeshFile.c_str());
|
---|
95 |
|
---|
96 | out.precision(5);
|
---|
97 | out.setf(ios::fixed);
|
---|
98 |
|
---|
99 | out << "<mesh>\n";
|
---|
100 | out << "\t<submeshes>\n";
|
---|
101 |
|
---|
102 | MSelectionList list;
|
---|
103 | MGlobal::getActiveSelectionList(list);
|
---|
104 |
|
---|
105 | // --- Iterate
|
---|
106 | for(; !iterDag.isDone(); iterDag.next()) {
|
---|
107 |
|
---|
108 | // Get DAG path
|
---|
109 | MDagPath dagPath;
|
---|
110 | status = iterDag.getPath(dagPath);
|
---|
111 | if (status == MStatus::kFailure) {
|
---|
112 | MGlobal::displayError("MDagPath::getPath");
|
---|
113 | bStatus = false;
|
---|
114 | break;
|
---|
115 | }
|
---|
116 |
|
---|
117 | // Process this node?
|
---|
118 | //if(OPTIONS.exportSelected && !list.hasItem(dagPath.node())) continue;
|
---|
119 |
|
---|
120 | if( dagPath.hasFn(MFn::kTransform)) continue;
|
---|
121 | if(!dagPath.hasFn(MFn::kMesh)) continue;
|
---|
122 |
|
---|
123 | MFnDagNode dagNode(dagPath);
|
---|
124 | if(dagNode.isIntermediateObject()) continue;
|
---|
125 |
|
---|
126 | // Process node if visible
|
---|
127 | bool bVisible;
|
---|
128 | bVisible = _isVisible(dagNode, status);
|
---|
129 | if (bVisible && (status == MStatus::kSuccess)) {
|
---|
130 | status = _processPolyMesh(out, dagPath);
|
---|
131 | if (status != MStatus::kSuccess) {
|
---|
132 | break;
|
---|
133 | }
|
---|
134 | }
|
---|
135 | }
|
---|
136 |
|
---|
137 | out << "\t</submeshes>\n";
|
---|
138 |
|
---|
139 | if(OPTIONS.exportSkeleton || OPTIONS.exportVBA) {
|
---|
140 | string skeletonName =
|
---|
141 | OPTIONS.outSkelFile.substr(
|
---|
142 | 0, OPTIONS.outSkelFile.find_last_of('.')
|
---|
143 | );
|
---|
144 | out << "\t<skeletonlink name=\""<<skeletonName<<"\"/>\n";
|
---|
145 | }
|
---|
146 |
|
---|
147 | out << "</mesh>\n";
|
---|
148 | }
|
---|
149 |
|
---|
150 | // reactivate IK Solver
|
---|
151 | MGlobal::executeCommand("ikSystem -e -sol 1;");
|
---|
152 |
|
---|
153 | // ===== Done
|
---|
154 | return (status == MStatus::kSuccess);
|
---|
155 | }
|
---|
156 |
|
---|
157 |
|
---|
158 | // --------------------------------------------------------------------------
|
---|
159 | /** Process a Maya polyMesh to generate an Ogre SubMesh.
|
---|
160 |
|
---|
161 | \param dagPath
|
---|
162 | Path to the Maya polyMesh to be processed
|
---|
163 |
|
---|
164 | \return MStatus::kSuccess if processed successfuly,
|
---|
165 | different MStatus otherwise
|
---|
166 |
|
---|
167 | \todo Vertex optimization
|
---|
168 | \todo Submesh optimization (merge submeshes that share materials)
|
---|
169 | */
|
---|
170 | // --------------------------------------------------------------------------
|
---|
171 | MStatus MeshGenerator::_processPolyMesh(ofstream& out, const MDagPath dagPath) {
|
---|
172 |
|
---|
173 | cout << "\nMeshGenerator::_processPolyMesh\n";
|
---|
174 | cout << "\tdagPath = \"" << dagPath.fullPathName().asChar() << "\"\n";
|
---|
175 |
|
---|
176 | MStatus status = MStatus::kSuccess;
|
---|
177 | MeshMayaGeometry MayaGeometry;
|
---|
178 |
|
---|
179 | //*******************************************************************
|
---|
180 |
|
---|
181 | // ===== Calculate the influence of SkinCluter if any
|
---|
182 | bool hasSkinCluster = false;
|
---|
183 |
|
---|
184 | //search the skin cluster affecting this geometry
|
---|
185 | MItDependencyNodes kDepNodeIt( MFn::kSkinClusterFilter );
|
---|
186 |
|
---|
187 | MFnMesh fnMesh(dagPath, &status);
|
---|
188 |
|
---|
189 | for( ;!kDepNodeIt.isDone() && !hasSkinCluster; kDepNodeIt.next()) {
|
---|
190 |
|
---|
191 | MObject kInputObject, kOutputObject;
|
---|
192 | MObject kObject = kDepNodeIt.item();
|
---|
193 |
|
---|
194 | MFnSkinCluster kSkinClusterFn(kObject, &status);
|
---|
195 |
|
---|
196 | cout << "\tskin cluster name: " << kSkinClusterFn.name().asChar() << '\n';
|
---|
197 |
|
---|
198 |
|
---|
199 | unsigned int uiNumGeometries = kSkinClusterFn.numOutputConnections();
|
---|
200 |
|
---|
201 | cout << "\tfound " << uiNumGeometries << " geometry object(s) in skin cluster\n";
|
---|
202 |
|
---|
203 | for(unsigned int uiGeometry = 0; uiGeometry < uiNumGeometries; ++uiGeometry ) {
|
---|
204 | unsigned int uiIndex = kSkinClusterFn.indexForOutputConnection( uiGeometry, &status );
|
---|
205 |
|
---|
206 |
|
---|
207 | kInputObject = kSkinClusterFn.inputShapeAtIndex( uiIndex, &status );
|
---|
208 | kOutputObject = kSkinClusterFn.outputShapeAtIndex( uiIndex, &status );
|
---|
209 |
|
---|
210 | if(kOutputObject == fnMesh.object()) {
|
---|
211 | cout << "\tgeometry located in skin cluster\n";
|
---|
212 | hasSkinCluster = true;
|
---|
213 |
|
---|
214 | /*
|
---|
215 | MDagPathArray jointPaths;
|
---|
216 | kSkinClusterFn.influenceObjects(jointPaths, &status);
|
---|
217 | int dummy;
|
---|
218 | string rootName = jointPaths[0].partialPathName(&status).asChar();
|
---|
219 |
|
---|
220 | MGlobal::executeCommand("ikSystem -e -sol 0;");
|
---|
221 | MGlobal::selectByName(rootName.c_str());
|
---|
222 | MGlobal::executeCommand("dagPose -r -g -bp");
|
---|
223 | */
|
---|
224 |
|
---|
225 | // get weights
|
---|
226 | MItGeometry kGeometryIt(kInputObject);
|
---|
227 | for(int uiVertex = 0; !kGeometryIt.isDone(); kGeometryIt.next(), ++uiVertex ) {
|
---|
228 | MObject kComponent = kGeometryIt.component( 0 );
|
---|
229 |
|
---|
230 | MFloatArray kWeightArray;
|
---|
231 | unsigned int uiNumInfluences;
|
---|
232 |
|
---|
233 | kSkinClusterFn.getWeights(dagPath, kComponent, kWeightArray, uiNumInfluences);
|
---|
234 |
|
---|
235 | MayaGeometry.Weights.push_back(kWeightArray);
|
---|
236 | }
|
---|
237 | }
|
---|
238 | }
|
---|
239 |
|
---|
240 | }
|
---|
241 |
|
---|
242 |
|
---|
243 | // ===== Get Maya geometry
|
---|
244 | status = _queryMayaGeometry(fnMesh, MayaGeometry);
|
---|
245 | if (status == MStatus::kFailure) {
|
---|
246 | return status;
|
---|
247 | }
|
---|
248 |
|
---|
249 | /*
|
---|
250 | if(hasSkinCluster) {
|
---|
251 | MGlobal::executeCommand("ikSystem -e -sol 1;");
|
---|
252 | }
|
---|
253 | */
|
---|
254 |
|
---|
255 | // ===== Parse into MeshGenerator format
|
---|
256 | MeshFaceVertexVector FaceVertices;
|
---|
257 | MeshTriFaceList TriFaces;
|
---|
258 | status = _parseMayaGeometry(fnMesh, MayaGeometry, FaceVertices, TriFaces);
|
---|
259 | if (status == MStatus::kFailure) {
|
---|
260 | return status;
|
---|
261 | }
|
---|
262 |
|
---|
263 |
|
---|
264 | ////////////////////////////////////////////////////////////////////////////////
|
---|
265 |
|
---|
266 | // export as XML
|
---|
267 | out << "\t\t<submesh material=\"" << OPTIONS.matPrefix << MayaGeometry.MaterialName.asChar() << "\" usesharedvertices=\"false\" use32bitindexes=\"false\">\n";
|
---|
268 |
|
---|
269 |
|
---|
270 | // ===== Create Ogre face list
|
---|
271 | // --- Basic info
|
---|
272 | unsigned int nTriFaces = (unsigned int)TriFaces.size();
|
---|
273 | // --- Store face indices
|
---|
274 | MeshTriFaceList::iterator faceIt, faceEnd;
|
---|
275 | faceEnd = TriFaces.end();
|
---|
276 |
|
---|
277 | out << "\t\t\t<faces count=\"" << nTriFaces << "\">\n";
|
---|
278 | for(faceIt=TriFaces.begin(); faceIt!=faceEnd; ++faceIt) {
|
---|
279 | out << "\t\t\t\t<face ";
|
---|
280 | out << "v1=\"" << faceIt->index0 << "\" ";
|
---|
281 | out << "v2=\"" << faceIt->index1 << "\" ";
|
---|
282 | out << "v3=\"" << faceIt->index2 << "\"/>\n";
|
---|
283 | }
|
---|
284 | out << "\t\t\t</faces>\n";
|
---|
285 |
|
---|
286 |
|
---|
287 |
|
---|
288 | out << "\t\t\t<geometry vertexcount=\"" << FaceVertices.size() << "\">\n";
|
---|
289 |
|
---|
290 |
|
---|
291 | MeshFaceVertexVector::iterator vertexIt, vertexEnd;
|
---|
292 | vertexEnd = FaceVertices.end();
|
---|
293 |
|
---|
294 | //
|
---|
295 | // POSITIONS
|
---|
296 | //
|
---|
297 | out << "\t\t\t\t<vertexbuffer ";
|
---|
298 | out << "positions=\"true\"";
|
---|
299 | if(OPTIONS.exportNormals)
|
---|
300 | out << " normals=\"true\"";
|
---|
301 | if(OPTIONS.exportColours)
|
---|
302 | out << " colours_diffuse=\"true\"";
|
---|
303 | if(MayaGeometry.UVSets.size() > 0 && OPTIONS.exportUVs)
|
---|
304 | out << " texture_coords=\"" << MayaGeometry.UVSets.size() << "\"";
|
---|
305 | out << ">\n";
|
---|
306 |
|
---|
307 |
|
---|
308 | for(vertexIt=FaceVertices.begin(); vertexIt!=vertexEnd; ++vertexIt) {
|
---|
309 | out << "\t\t\t\t\t<vertex>\n";
|
---|
310 |
|
---|
311 | out << "\t\t\t\t\t\t<position ";
|
---|
312 | out << "x=\"" << vertexIt->vecPosition.x << "\" ";
|
---|
313 | out << "y=\"" << vertexIt->vecPosition.y << "\" ";
|
---|
314 | out << "z=\"" << vertexIt->vecPosition.z << "\"/>\n";
|
---|
315 |
|
---|
316 | if(OPTIONS.exportNormals) {
|
---|
317 | out << "\t\t\t\t\t\t<normal ";
|
---|
318 | out << "x=\"" << vertexIt->vecNormal.x << "\" ";
|
---|
319 | out << "y=\"" << vertexIt->vecNormal.y << "\" ";
|
---|
320 | out << "z=\"" << vertexIt->vecNormal.z << "\"/>\n";
|
---|
321 | }
|
---|
322 |
|
---|
323 |
|
---|
324 | if(OPTIONS.exportColours) {
|
---|
325 | out << "\t\t\t\t\t\t<colour_diffuse value=\"";
|
---|
326 | out << vertexIt->colour.r << " ";
|
---|
327 | out << vertexIt->colour.g << " ";
|
---|
328 | out << vertexIt->colour.b << " ";
|
---|
329 | out << vertexIt->colour.a << "\"/>\n";
|
---|
330 | }
|
---|
331 |
|
---|
332 | if(MayaGeometry.UVSets.size() > 0 && OPTIONS.exportUVs) {
|
---|
333 | MeshVertexUVList::iterator uvIt, uvEnd;
|
---|
334 | uvEnd = vertexIt->listUV.end();
|
---|
335 | for (uvIt = vertexIt->listUV.begin(); uvIt!=uvEnd; ++uvIt) {
|
---|
336 |
|
---|
337 | float u,v;
|
---|
338 | u = uvIt->u;
|
---|
339 | //v = 1.0f - uvIt->v;
|
---|
340 | v = uvIt->v;
|
---|
341 |
|
---|
342 | out << "\t\t\t\t\t\t<texcoord ";
|
---|
343 | out << "u=\"" << u << "\" ";
|
---|
344 | out << "v=\"" << v << "\"/>\n";
|
---|
345 | }
|
---|
346 | }
|
---|
347 |
|
---|
348 | out << "\t\t\t\t\t</vertex>\n";
|
---|
349 | }
|
---|
350 |
|
---|
351 | out << "\t\t\t\t</vertexbuffer>\n";
|
---|
352 |
|
---|
353 | out << "\t\t\t</geometry>\n";
|
---|
354 |
|
---|
355 |
|
---|
356 | // BONE ASSIGMENTS
|
---|
357 | if(OPTIONS.exportVBA || OPTIONS.exportSkeleton) {
|
---|
358 | out << "\t\t\t<boneassignments>\n";
|
---|
359 |
|
---|
360 | int i;
|
---|
361 | for(i=0, vertexIt=FaceVertices.begin(); vertexIt!=vertexEnd; ++vertexIt, i++) {
|
---|
362 | VertexBoneAssigmentList::iterator boneIt, boneEnd;
|
---|
363 | boneEnd = vertexIt->boneAssigments.end();
|
---|
364 | for (boneIt=vertexIt->boneAssigments.begin(); boneIt!=boneEnd; ++boneIt) {
|
---|
365 | VertexBoneAssigment& assigment = *boneIt;
|
---|
366 |
|
---|
367 | if(assigment.weight<0.01)
|
---|
368 | continue;
|
---|
369 |
|
---|
370 | out << "\t\t\t\t<vertexboneassignment ";
|
---|
371 | out << "vertexindex=\""<<i<<"\" ";
|
---|
372 | out << "boneindex=\""<<assigment.boneId<<"\" ";
|
---|
373 | out << "weight=\""<<assigment.weight<<"\"/>\n";
|
---|
374 | }
|
---|
375 | }
|
---|
376 |
|
---|
377 |
|
---|
378 | out << "\t\t\t</boneassignments>\n";
|
---|
379 | }
|
---|
380 |
|
---|
381 |
|
---|
382 | out << "\t\t</submesh>\n";
|
---|
383 |
|
---|
384 | ////////////////////////////////////////////////////////////////////////////////
|
---|
385 |
|
---|
386 |
|
---|
387 | // ===== Success!
|
---|
388 | return MStatus::kSuccess;
|
---|
389 | }
|
---|
390 |
|
---|
391 | MString MeshGenerator::getMaterialName(MFnMesh &fnMesh) {
|
---|
392 |
|
---|
393 | MStatus status = MStatus::kSuccess;
|
---|
394 | MString MaterialName = "";
|
---|
395 |
|
---|
396 |
|
---|
397 | // ===== Connected sets and members
|
---|
398 | // (Required to determine texturing of different faces)
|
---|
399 |
|
---|
400 | // Determine instance number
|
---|
401 | MDagPath meshPath = fnMesh.dagPath();
|
---|
402 | meshPath.extendToShape();
|
---|
403 | int iInstance = 0;
|
---|
404 | if (meshPath.isInstanced()) {
|
---|
405 | iInstance = meshPath.instanceNumber();
|
---|
406 | }
|
---|
407 |
|
---|
408 | // Get the connected sets and members
|
---|
409 | MObjectArray PolygonSets;
|
---|
410 | MObjectArray PolygonComponents;
|
---|
411 | status = fnMesh.getConnectedSetsAndMembers(iInstance,
|
---|
412 | PolygonSets,
|
---|
413 | PolygonComponents,
|
---|
414 | true);
|
---|
415 | if (!status) {
|
---|
416 | MGlobal::displayError("MFnMesh::getConnectedSetsAndMembers");
|
---|
417 | return MaterialName;
|
---|
418 | }
|
---|
419 |
|
---|
420 |
|
---|
421 | // ===== Materials
|
---|
422 | unsigned int iSet;
|
---|
423 | for (iSet = 0; iSet < PolygonSets.length(); ++iSet) {
|
---|
424 | MObject PolygonSet = PolygonSets[iSet];
|
---|
425 | MObject PolygonComponent = PolygonComponents[iSet];
|
---|
426 |
|
---|
427 | MFnDependencyNode dnSet(PolygonSet);
|
---|
428 | MObject ssAttr = dnSet.attribute(MString("surfaceShader"));
|
---|
429 | MPlug ssPlug(PolygonSet, ssAttr);
|
---|
430 |
|
---|
431 | MPlugArray srcPlugArray;
|
---|
432 | ssPlug.connectedTo(srcPlugArray, true, false);
|
---|
433 |
|
---|
434 | if (srcPlugArray.length() > 0) {
|
---|
435 | // This object contains a reference to a shader or material.
|
---|
436 | // Check for known material types and extract material name.
|
---|
437 | MObject srcNode = srcPlugArray[0].node();
|
---|
438 |
|
---|
439 | if (srcNode.hasFn(MFn::kPhong)) {
|
---|
440 | MFnPhongShader fnPhong(srcNode);
|
---|
441 | MaterialName = fnPhong.name();
|
---|
442 | }
|
---|
443 | else if (srcNode.hasFn(MFn::kLambert)) {
|
---|
444 | MFnLambertShader fnLambert(srcNode);
|
---|
445 | MaterialName = fnLambert.name();
|
---|
446 | }
|
---|
447 | else if (srcNode.hasFn(MFn::kBlinn)) {
|
---|
448 | MFnBlinnShader fnBlinn(srcNode);
|
---|
449 | MaterialName = fnBlinn.name();
|
---|
450 | }
|
---|
451 | else if (srcNode.hasFn(MFn::kReflect)) {
|
---|
452 | MFnReflectShader fnReflect(srcNode);
|
---|
453 | MaterialName = fnReflect.name();
|
---|
454 | }
|
---|
455 | }
|
---|
456 | }
|
---|
457 |
|
---|
458 |
|
---|
459 | // ===== Done
|
---|
460 | return MaterialName;
|
---|
461 |
|
---|
462 | }
|
---|
463 |
|
---|
464 | // --------------------------------------------------------------------------
|
---|
465 | /** Retrieve all Maya geometry for a single Maya mesh.
|
---|
466 | \todo Define materials if requested
|
---|
467 | \todo Fix normals
|
---|
468 | */
|
---|
469 | // --------------------------------------------------------------------------
|
---|
470 | MStatus MeshGenerator::_queryMayaGeometry(
|
---|
471 | MFnMesh &fnMesh,
|
---|
472 | MeshMayaGeometry &rGeom
|
---|
473 | ) {
|
---|
474 | cout << "\nMeshGenerator::_queryMayaGeometry\n";
|
---|
475 |
|
---|
476 | MStatus status = MStatus::kSuccess;
|
---|
477 |
|
---|
478 | // ===== Identification
|
---|
479 | rGeom.Name = fnMesh.partialPathName(); // shortest unique name
|
---|
480 | rGeom.MaterialName = getMaterialName(fnMesh);
|
---|
481 |
|
---|
482 |
|
---|
483 | // ===== Geometry
|
---|
484 |
|
---|
485 | // --- Vertices
|
---|
486 | status = fnMesh.getPoints(rGeom.Vertices, MSpace::kWorld);
|
---|
487 | if (status == MStatus::kFailure) {
|
---|
488 | cout << "\t[ERROR] MFnMesh::getPoints() failed\n";
|
---|
489 | return status;
|
---|
490 | }
|
---|
491 |
|
---|
492 | cout << "\tvertices count: " << rGeom.Vertices.length() << '\n';
|
---|
493 |
|
---|
494 | // --- Vertex normals
|
---|
495 | status = fnMesh.getNormals(rGeom.FaceVertexNormals);
|
---|
496 | if (status == MStatus::kFailure) {
|
---|
497 | cout << "\t[ERROR] MFnMesh::getNormals() failed\n";
|
---|
498 | return status;
|
---|
499 | }
|
---|
500 |
|
---|
501 | // --- Triangular faces
|
---|
502 | MDagPath dagPath;
|
---|
503 | fnMesh.getPath(dagPath);
|
---|
504 | MItMeshPolygon iterPoly(dagPath);
|
---|
505 |
|
---|
506 | int iPolygon, nPolygons;
|
---|
507 | nPolygons = fnMesh.numPolygons();
|
---|
508 | for (iPolygon=0; iPolygon < nPolygons; ++iPolygon)
|
---|
509 | {
|
---|
510 | MIntArray ThisPolyTriVertices;
|
---|
511 | MPointArray ThisPolyPointsUntweaked;
|
---|
512 | iterPoly.getTriangles(ThisPolyPointsUntweaked, ThisPolyTriVertices, MSpace::kWorld);
|
---|
513 |
|
---|
514 | _convertObjectToFace(iterPoly, ThisPolyTriVertices, rGeom.TriangleVertexIds);
|
---|
515 |
|
---|
516 | int iTriangle, nTriangles;
|
---|
517 | iterPoly.numTriangles(nTriangles);
|
---|
518 | for (iTriangle=0; iTriangle < nTriangles; ++iTriangle) {
|
---|
519 | rGeom.TrianglePolygonIds.append(iPolygon);
|
---|
520 | }
|
---|
521 |
|
---|
522 | iterPoly.next();
|
---|
523 | }
|
---|
524 |
|
---|
525 |
|
---|
526 | // ===== Colours and UVs
|
---|
527 |
|
---|
528 | // --- Face vertex colours
|
---|
529 | status = fnMesh.getFaceVertexColors(rGeom.FaceVertexColours);
|
---|
530 | if (status == MStatus::kFailure) {
|
---|
531 | cout << "\t[ERROR] MFnMesh::getFaceVertexColors() failed\n";
|
---|
532 | return status;
|
---|
533 | }
|
---|
534 | // Override non-existent colours with semi-transparent white
|
---|
535 | unsigned int iFaceVertex;
|
---|
536 | MColor mayaColour;
|
---|
537 | for (iFaceVertex=0; iFaceVertex < rGeom.FaceVertexColours.length(); ++iFaceVertex) {
|
---|
538 | mayaColour = rGeom.FaceVertexColours[iFaceVertex];
|
---|
539 | if ((mayaColour.r) == -1) mayaColour.r = 1;
|
---|
540 | if ((mayaColour.g) == -1) mayaColour.g = 1;
|
---|
541 | if ((mayaColour.b) == -1) mayaColour.b = 1;
|
---|
542 | if ((mayaColour.a) == -1) mayaColour.a = 0.2;
|
---|
543 | rGeom.FaceVertexColours[iFaceVertex] = mayaColour;
|
---|
544 | }
|
---|
545 |
|
---|
546 | // --- UV set names
|
---|
547 | MStringArray UVSetNames;
|
---|
548 | status = fnMesh.getUVSetNames(UVSetNames);
|
---|
549 | if (status == MStatus::kFailure) {
|
---|
550 | cout << "\t[ERROR] MFnMesh::getUVSetNames() failed\n";
|
---|
551 | return status;
|
---|
552 | }
|
---|
553 |
|
---|
554 | // --- Linked list of UV sets
|
---|
555 | unsigned int nUVSets = UVSetNames.length();
|
---|
556 | unsigned int iUVSet;
|
---|
557 |
|
---|
558 | // Loop over all UV sets
|
---|
559 | MeshMayaUVSet UVSet;
|
---|
560 | for (iUVSet = 0; iUVSet < nUVSets; ++iUVSet) {
|
---|
561 |
|
---|
562 | // Store UV name
|
---|
563 | UVSet.sName = UVSetNames[iUVSet];
|
---|
564 |
|
---|
565 | // Retrieve UV coordinates
|
---|
566 | status = fnMesh.getUVs(UVSet.uArray, UVSet.vArray, &(UVSet.sName));
|
---|
567 | if (status == MStatus::kFailure) {
|
---|
568 | return status;
|
---|
569 | }
|
---|
570 |
|
---|
571 | // Store UV set
|
---|
572 | rGeom.UVSets.push_back(UVSet);
|
---|
573 | }
|
---|
574 |
|
---|
575 |
|
---|
576 | // ===== Done
|
---|
577 | return status;
|
---|
578 |
|
---|
579 | }
|
---|
580 |
|
---|
581 |
|
---|
582 | // --------------------------------------------------------------------------
|
---|
583 | /** Parse Maya geometry into MeshGenerator format for further processing.
|
---|
584 | */
|
---|
585 | // --------------------------------------------------------------------------
|
---|
586 | MStatus MeshGenerator::_parseMayaGeometry(
|
---|
587 | MFnMesh &fnMesh,
|
---|
588 | MeshMayaGeometry &MayaGeometry,
|
---|
589 | MeshFaceVertexVector &FaceVertices,
|
---|
590 | MeshTriFaceList &TriFaces
|
---|
591 | ) {
|
---|
592 | cout << "\nMeshGenerator::_parseMayaGeometry\n";
|
---|
593 |
|
---|
594 | MStatus status;
|
---|
595 |
|
---|
596 | // --- Determine number of triangles
|
---|
597 | unsigned int nTris = MayaGeometry.TrianglePolygonIds.length();
|
---|
598 | if (nTris == 0) {
|
---|
599 | return MStatus::kFailure;
|
---|
600 | }
|
---|
601 |
|
---|
602 | // --- Confirm number of triangle vertices
|
---|
603 | unsigned int nTriVertices = MayaGeometry.TriangleVertexIds.length();
|
---|
604 | if (nTriVertices != 3*nTris) {
|
---|
605 | cout << "\t[ERROR] "<<nTris<<" triangles require "<<(3*nTris)<<" vertices but "<<nTriVertices<<" vertices present!\n";
|
---|
606 | return MStatus::kFailure;
|
---|
607 | }
|
---|
608 |
|
---|
609 | // --- Loop over all triangles
|
---|
610 | unsigned int iTri;
|
---|
611 | cout << "\texporting "<<fnMesh.numPolygons()<<" faces as "<<nTris<<" triangles from "<<MayaGeometry.Name.asChar()<<" (material "<<MayaGeometry.MaterialName.asChar()<<")...\n";
|
---|
612 |
|
---|
613 | for (iTri = 0; iTri < nTris; ++iTri) {
|
---|
614 |
|
---|
615 | // --- Get polygon index
|
---|
616 | unsigned int iPoly;
|
---|
617 | iPoly = MayaGeometry.TrianglePolygonIds[iTri];
|
---|
618 |
|
---|
619 | // --- Get indices of face-vertices
|
---|
620 | MIntArray VertexIds;
|
---|
621 | status = fnMesh.getPolygonVertices(iPoly, VertexIds);
|
---|
622 | if (status == MStatus::kFailure) {
|
---|
623 | MGlobal::displayError("MFnMesh::getPolygonVertices()");
|
---|
624 | return status;
|
---|
625 | }
|
---|
626 |
|
---|
627 | // --- Get indices of face-vertex normals
|
---|
628 | MIntArray NormalIds;
|
---|
629 | /*if (OPTIONS.exportNormals)*/ {
|
---|
630 | fnMesh.getFaceNormalIds(iPoly, NormalIds);
|
---|
631 | if (status == MStatus::kFailure) {
|
---|
632 | MGlobal::displayError("MFnMesh::getFaceNormalIds()");
|
---|
633 | return status;
|
---|
634 | }
|
---|
635 | }
|
---|
636 |
|
---|
637 | // --- Loop over all face-vertices
|
---|
638 | unsigned int iTriVertex;
|
---|
639 | MeshFaceVertex faceVertices[3];
|
---|
640 | for (iTriVertex = 0; iTriVertex < 3; ++iTriVertex) {
|
---|
641 |
|
---|
642 | MeshFaceVertex& FaceVertex = faceVertices[iTriVertex];
|
---|
643 |
|
---|
644 | // Get polygon vertex id
|
---|
645 | unsigned int iPolyVertex;
|
---|
646 | iPolyVertex = MayaGeometry.TriangleVertexIds[3*iTri + iTriVertex];
|
---|
647 |
|
---|
648 | // Lookup and store face-vertex position
|
---|
649 | MPoint mayaPoint;
|
---|
650 | int iVertex = VertexIds[iPolyVertex];
|
---|
651 | mayaPoint = MayaGeometry.Vertices[iVertex];
|
---|
652 |
|
---|
653 | MFloatArray* weights = 0;
|
---|
654 |
|
---|
655 | if(iVertex < MayaGeometry.Weights.size()) {
|
---|
656 | weights = &MayaGeometry.Weights[iVertex];
|
---|
657 | }
|
---|
658 |
|
---|
659 | FaceVertex.vecPosition.x = mayaPoint.x;
|
---|
660 | FaceVertex.vecPosition.y = mayaPoint.y;
|
---|
661 | FaceVertex.vecPosition.z = mayaPoint.z;
|
---|
662 |
|
---|
663 | // Lookup and store face-vertex normal
|
---|
664 | /*if (OPTIONS.exportNormals)*/ {
|
---|
665 | MVector mayaNormal;
|
---|
666 | int iNormal = NormalIds[iPolyVertex];
|
---|
667 | mayaNormal = MayaGeometry.FaceVertexNormals[iNormal];
|
---|
668 | FaceVertex.vecNormal.x = mayaNormal.x;
|
---|
669 | FaceVertex.vecNormal.y = mayaNormal.y;
|
---|
670 | FaceVertex.vecNormal.z = mayaNormal.z;
|
---|
671 | }
|
---|
672 |
|
---|
673 | // Lookup and store face-vertex colour
|
---|
674 | /*if (OPTIONS.exportColours)*/ {
|
---|
675 | int iColour;
|
---|
676 | MColor mayaColour;
|
---|
677 | status = fnMesh.getFaceVertexColorIndex(iPoly, iPolyVertex, iColour);
|
---|
678 | mayaColour = MayaGeometry.FaceVertexColours[iColour];
|
---|
679 | FaceVertex.colour.r = mayaColour.r;
|
---|
680 | FaceVertex.colour.g = mayaColour.g;
|
---|
681 | FaceVertex.colour.b = mayaColour.b;
|
---|
682 | FaceVertex.colour.a = mayaColour.a;
|
---|
683 | }
|
---|
684 |
|
---|
685 | // Loop over UV sets
|
---|
686 | /*if (OPTIONS.exportUVs)*/ {
|
---|
687 | MeshMayaUVSetList::iterator iterUVSet;
|
---|
688 | iterUVSet = MayaGeometry.UVSets.begin();
|
---|
689 | while (iterUVSet != MayaGeometry.UVSets.end()) {
|
---|
690 | int iUV;
|
---|
691 | MStatus stat = fnMesh.getPolygonUVid(iPoly, iPolyVertex, iUV, &(iterUVSet->sName));
|
---|
692 |
|
---|
693 | MeshVertexUV VertexUV;
|
---|
694 | if(!stat.error()) {
|
---|
695 | VertexUV.u = iterUVSet->uArray[iUV];
|
---|
696 | VertexUV.v = 1.0f - iterUVSet->vArray[iUV]; // CJV 2004-01-05: Required for Ogre 0.13
|
---|
697 | }
|
---|
698 | else {
|
---|
699 | VertexUV.u = 0;
|
---|
700 | VertexUV.v = 0;
|
---|
701 | }
|
---|
702 |
|
---|
703 | FaceVertex.listUV.push_back(VertexUV);
|
---|
704 |
|
---|
705 | ++iterUVSet;
|
---|
706 | }
|
---|
707 | }
|
---|
708 |
|
---|
709 | // assign weights
|
---|
710 | if(weights) {
|
---|
711 | const float eps = 0.001f;
|
---|
712 | float acc;
|
---|
713 |
|
---|
714 | for(int i=weights->length()-1; i>=0; i--) {
|
---|
715 | acc = 0;
|
---|
716 | if((*weights)[i] < eps) {
|
---|
717 | acc += (*weights)[i];
|
---|
718 | }
|
---|
719 | else {
|
---|
720 | VertexBoneAssigment vba;
|
---|
721 |
|
---|
722 | vba.boneId = i;
|
---|
723 | vba.weight = (*weights)[i];// + (acc/(float)i);
|
---|
724 |
|
---|
725 | FaceVertex.boneAssigments.push_front(vba);
|
---|
726 | }
|
---|
727 | }
|
---|
728 | }
|
---|
729 | }
|
---|
730 |
|
---|
731 |
|
---|
732 |
|
---|
733 | // OPTIMIZIATION CODE: BEGIN
|
---|
734 | // Search in the current vertex vector for occurance
|
---|
735 | int index[3];
|
---|
736 | for(int i=0; i<3; i++) {
|
---|
737 |
|
---|
738 | vector<MeshFaceVertex>::iterator it;
|
---|
739 | vector<MeshFaceVertex>::iterator end = FaceVertices.end();
|
---|
740 |
|
---|
741 | int j;
|
---|
742 | for(j=0, it=FaceVertices.begin(); it!=end; ++it, j++) {
|
---|
743 | if(faceVertices[i] == *it) {
|
---|
744 | // this vertex is already in vector -> reuse
|
---|
745 | index[i] = j;
|
---|
746 | break;
|
---|
747 | }
|
---|
748 | }
|
---|
749 |
|
---|
750 | // if can not be found in vector, insert
|
---|
751 | if(it==end) {
|
---|
752 | index[i] = FaceVertices.size();
|
---|
753 | FaceVertices.push_back(faceVertices[i]);
|
---|
754 | }
|
---|
755 | }
|
---|
756 | // OPTIMIZIATION CODE: END
|
---|
757 |
|
---|
758 |
|
---|
759 | // --- Define face (three face-vertices)
|
---|
760 | MeshTriFace TriFace;
|
---|
761 | TriFace.index0 = (unsigned long)index[0];
|
---|
762 | TriFace.index1 = (unsigned long)index[1];
|
---|
763 | TriFace.index2 = (unsigned long)index[2];
|
---|
764 |
|
---|
765 | TriFaces.push_back(TriFace);
|
---|
766 | }
|
---|
767 |
|
---|
768 | return MStatus::kSuccess;
|
---|
769 | }
|
---|
770 |
|
---|
771 |
|
---|
772 | // --------------------------------------------------------------------------
|
---|
773 | /** Determines if a given DAG node is currently visible.
|
---|
774 | \param fnDag
|
---|
775 | DAG node to check
|
---|
776 | \param status
|
---|
777 | Status code from Maya API
|
---|
778 |
|
---|
779 | \return True if node is visible, False if node is not visible or if
|
---|
780 | unable to determine visibility
|
---|
781 | */
|
---|
782 | // --------------------------------------------------------------------------
|
---|
783 | bool MeshGenerator::_isVisible(MFnDagNode &fnDag, MStatus &status) {
|
---|
784 |
|
---|
785 | if(fnDag.isIntermediateObject()) {
|
---|
786 | return false;
|
---|
787 | }
|
---|
788 |
|
---|
789 | bool bVisible = false;
|
---|
790 | MPlug visPlug = fnDag.findPlug("visibility", &status);
|
---|
791 | if (MStatus::kFailure == status) {
|
---|
792 | cout << "[WARNING] can not find \"visibility\" plug, returning false\n";
|
---|
793 | } else {
|
---|
794 | status = visPlug.getValue(bVisible);
|
---|
795 | if (MStatus::kFailure == status) {
|
---|
796 | bVisible = false;
|
---|
797 | cout << "[WARNING] can not query \"visibility\" plug, returning false\n";
|
---|
798 | }
|
---|
799 | }
|
---|
800 |
|
---|
801 | return bVisible;
|
---|
802 | }
|
---|
803 |
|
---|
804 |
|
---|
805 | // --------------------------------------------------------------------------
|
---|
806 | /** Convert an array of object-relative vertex indices into an array of face-
|
---|
807 | relative vertex indices. Required because MItMeshPolygon::getTriangle()
|
---|
808 | returns object-relative vertex indices, whereas many other methods require
|
---|
809 | face-relative vertex indices.
|
---|
810 |
|
---|
811 | Adapted from "How do I write a polygon mesh exporter?" at URL
|
---|
812 | http://www.ewertb.com/maya/api/api_a18.html.
|
---|
813 |
|
---|
814 | \param iterPoly
|
---|
815 | Reference to a polygon iterator that is currently at the
|
---|
816 | polygon of interest
|
---|
817 | \param objIndices
|
---|
818 | Reference to array of object-relative indices
|
---|
819 | \param faceIndices
|
---|
820 | Reference to array of face-relative indices (output). Indices
|
---|
821 | are appended to the end of this array. A value of -1 will be
|
---|
822 | appended if there is no corresponding vertex.
|
---|
823 | */
|
---|
824 | // --------------------------------------------------------------------------
|
---|
825 | void MeshGenerator::_convertObjectToFace(
|
---|
826 | MItMeshPolygon &iterPoly,
|
---|
827 | MIntArray &objIndices,
|
---|
828 | MIntArray &faceIndices
|
---|
829 | ) {
|
---|
830 | MIntArray polyIndices;
|
---|
831 | iterPoly.getVertices(polyIndices);
|
---|
832 |
|
---|
833 | bool bMatched;
|
---|
834 | unsigned int iPoly, iObj;
|
---|
835 | for (iObj=0; iObj < objIndices.length(); ++iObj)
|
---|
836 | {
|
---|
837 | bMatched = false;
|
---|
838 |
|
---|
839 | // iPoly is face-relative vertex index
|
---|
840 | for (iPoly=0; iPoly < polyIndices.length(); ++iPoly)
|
---|
841 | {
|
---|
842 | if (objIndices[iObj] == polyIndices[iPoly]) {
|
---|
843 | faceIndices.append(iPoly);
|
---|
844 | bMatched = true;
|
---|
845 | break;
|
---|
846 | }
|
---|
847 |
|
---|
848 | }
|
---|
849 |
|
---|
850 | // default if no match found
|
---|
851 | if (!bMatched) {
|
---|
852 | faceIndices.append(-1);
|
---|
853 | }
|
---|
854 |
|
---|
855 | }
|
---|
856 | }
|
---|
857 |
|
---|
858 |
|
---|
859 | } // namespace OgreMaya
|
---|