1 /*
2 Copyright (c) 2015 Starbreeze
3
4 This file is part of COLLADAMaya.
5
6 Portions of the code are:
7 Copyright (c) 2005-2007 Feeling Software Inc.
8 Copyright (c) 2005-2007 Sony Computer Entertainment America
9 Copyright (c) 2004-2005 Alias Systems Corp.
10
11 Licensed under the MIT Open Source License,
12 for details please see LICENSE file or the website
13 http://www.opensource.org/licenses/mit-license.php
14 */
15
16 #include "COLLADAMayaStableHeaders.h"
17
18 #include "COLLADAMayaAttributeParser.h"
19 #include "COLLADAMayaDagHelper.h"
20 #include "COLLADAMayaExportOptions.h"
21 #include "COLLADAMayaGeometryExporter.h"
22 #include "COLLADAMayaPhysXExporter.h"
23 #include "COLLADAMayaRotateHelper.h"
24 #include "COLLADAMayaSceneGraph.h"
25 #include "COLLADAMayaSyntax.h"
26 #include "COLLADAMayaVisualSceneExporter.h"
27 #include "COLLADASWConstants.h"
28 #include "Math/COLLADABUMathUtils.h"
29
30 #include <libxml/tree.h>
31 #include <maya/MAngle.h>
32 #include <maya/MDistance.h>
33 #include <maya/MFnAttribute.h>
34 #define MNoPluginEntry
35 #define MNoVersionString
36 #include <maya/MFnPlugin.h>
37 #include <maya/MFnTransform.h>
38 #include <maya/MString.h>
39 #include <maya/MTime.h>
40
infinite()41 double infinite()
42 {
43 union ieee754 {
44 int64_t i;
45 double d;
46 };
47 ieee754 inf;
48 inf.i = 0x7FF0000000000000;
49 return inf.d;
50 }
51
isInf(double d)52 bool isInf(double d)
53 {
54 return
55 d == infinite() ||
56 d == -infinite();
57 }
58
59 using namespace COLLADASW;
60
61 // Note:
62 // Maya matrix: row major vectors, T1 x T2 x T3...
63 // DAE matrix/transforms: column major vectors, ...T3 x T2 x T1
64 // -> reverse order
65
66 namespace COLLADAMaya
67 {
uiToInternal(const MVector & v)68 MVector uiToInternal(const MVector & v)
69 {
70 return MVector(
71 MDistance::uiToInternal(v.x),
72 MDistance::uiToInternal(v.y),
73 MDistance::uiToInternal(v.z));
74 }
75
PxTransformToMMatrix(const MVector & t,const MQuaternion & r)76 MMatrix PxTransformToMMatrix(const MVector & t, const MQuaternion & r)
77 {
78 MTransformationMatrix tm;
79 tm.setRotationQuaternion(r.x, r.y, r.z, r.w);
80 tm.setTranslation(uiToInternal(t), MSpace::kTransform);
81 return tm.asMatrix();
82 }
83
84 const bool withPrefix = true;
85 const bool withoutPrefix = false;
86
87 // Helper class used to open and auto close an element.
88 class Element
89 {
90 public:
Element(PhysXExporter & exporter,const String & name,bool elementForm=withoutPrefix)91 Element(PhysXExporter& exporter, const String & name, bool elementForm = withoutPrefix)
92 : mPhysXExporter(exporter)
93 {
94 if (elementForm == withoutPrefix)
95 {
96 mPhysXExporter.getStreamWriter().openElement(name, String());
97 }
98 else
99 {
100 mPhysXExporter.getStreamWriter().openElement(name, CSWC::CSW_PREFIX_PX);
101 }
102 }
103
~Element()104 virtual ~Element()
105 {
106 mPhysXExporter.getStreamWriter().closeElement();
107 }
108
109 protected:
getStreamWriter()110 StreamWriter& getStreamWriter()
111 {
112 return mPhysXExporter.getStreamWriter();
113 }
114
getDocumentExporter()115 DocumentExporter& getDocumentExporter()
116 {
117 return mPhysXExporter.getDocumentExporter();
118 }
119
getPhysXExporter()120 PhysXExporter& getPhysXExporter()
121 {
122 return mPhysXExporter;
123 }
124
125 private:
126 PhysXExporter& mPhysXExporter;
127 };
128
129 class AttributeExporter : public AttributeParser
130 {
131 public:
AttributeExporter(PhysXExporter & exporter,const std::set<MString,MStringComp> & attributes)132 AttributeExporter(PhysXExporter& exporter, const std::set<MString, MStringComp> & attributes)
133 : mPhysXExporter(exporter)
134 , mAttributes(attributes)
135 {}
136
137 protected:
onBeforePlug(MPlug & plug)138 virtual bool onBeforePlug(MPlug & plug) override
139 {
140 MStatus status;
141
142 MObject attr = plug.attribute(&status);
143 if (!status) return false;
144
145 MFnAttribute fnAttr(attr, &status);
146 if (!status) return false;
147
148 MString attrName = fnAttr.name(&status);
149 if (!status) return false;
150
151 std::set<MString, MStringComp>::const_iterator it = mAttributes.find(attrName);
152 if (it == mAttributes.end()) {
153 return false;
154 }
155
156 return true;
157 }
158
onBoolean(MPlug & plug,const MString & name,bool value)159 virtual void onBoolean(MPlug & plug, const MString & name, bool value) override
160 {
161 String nameStr(name.asChar());
162 Element e(mPhysXExporter, nameStr);
163 mPhysXExporter.getStreamWriter().appendValues(value);
164 }
165
onByte(MPlug & plug,const MString & name,char value)166 virtual void onByte(MPlug & plug, const MString & name, char value) override
167 {
168 String nameStr(name.asChar());
169 const size_t size = 5;
170 char text[size];
171 snprintf(text, size, "0x%X", value);
172 Element e(mPhysXExporter, nameStr);
173 mPhysXExporter.getStreamWriter().appendValues(text);
174 }
175
onChar(MPlug & plug,const MString & name,char value)176 virtual void onChar(MPlug & plug, const MString & name, char value) override
177 {
178 String nameStr(name.asChar());
179 char text[] = { value, '\0' };
180 Element e(mPhysXExporter, nameStr);
181 mPhysXExporter.getStreamWriter().appendValues(text);
182 }
183
onShort(MPlug & plug,const MString & name,short value)184 virtual void onShort(MPlug & plug, const MString & name, short value) override
185 {
186 String nameStr(name.asChar());
187 Element e(mPhysXExporter, nameStr);
188 mPhysXExporter.getStreamWriter().appendValues(value);
189 }
190
onShort2(MPlug & plug,const MString & name,short value[2])191 virtual void onShort2(MPlug & plug, const MString & name, short value[2]) override
192 {
193 String nameStr(name.asChar());
194 int values[3] = { value[0], value[1] };
195 Element e(mPhysXExporter, nameStr);
196 mPhysXExporter.getStreamWriter().appendValues(values, 2);
197 }
198
onShort3(MPlug & plug,const MString & name,short value[3])199 virtual void onShort3(MPlug & plug, const MString & name, short value[3]) override
200 {
201
202 String nameStr(name.asChar());
203 int values[3] = { value[0], value[1], value[2] };
204 Element e(mPhysXExporter, nameStr);
205 mPhysXExporter.getStreamWriter().appendValues(values, 3);
206 }
207
onInteger(MPlug & plug,const MString & name,int value)208 virtual void onInteger(MPlug & plug, const MString & name, int value) override
209 {
210 String nameStr(name.asChar());
211 Element e(mPhysXExporter, nameStr);
212 mPhysXExporter.getStreamWriter().appendValues(value);
213 }
214
onInteger2(MPlug & plug,const MString & name,int value[2])215 virtual void onInteger2(MPlug & plug, const MString & name, int value[2]) override
216 {
217 String nameStr(name.asChar());
218 Element e(mPhysXExporter, nameStr);
219 mPhysXExporter.getStreamWriter().appendValues(value, 2);
220 }
221
onInteger3(MPlug & plug,const MString & name,int value[3])222 virtual void onInteger3(MPlug & plug, const MString & name, int value[3]) override
223 {
224 String nameStr(name.asChar());
225 Element e(mPhysXExporter, nameStr);
226 mPhysXExporter.getStreamWriter().appendValues(value, 3);
227 }
228
onFloat(MPlug & plug,const MString & name,float value)229 virtual void onFloat(MPlug & plug, const MString & name, float value) override
230 {
231 String nameStr(name.asChar());
232 Element e(mPhysXExporter, nameStr);
233 mPhysXExporter.getStreamWriter().appendValues(value);
234 }
235
onFloat2(MPlug & plug,const MString & name,float value[2])236 virtual void onFloat2(MPlug & plug, const MString & name, float value[2]) override
237 {
238 String nameStr(name.asChar());
239 Element e(mPhysXExporter, nameStr);
240 mPhysXExporter.getStreamWriter().appendValues(value, 2);
241 }
242
onFloat3(MPlug & plug,const MString & name,float value[3])243 virtual void onFloat3(MPlug & plug, const MString & name, float value[3]) override
244 {
245 String nameStr(name.asChar());
246 Element e(mPhysXExporter, nameStr);
247 mPhysXExporter.getStreamWriter().appendValues(value, 3);
248 }
249
onDouble(MPlug & plug,const MString & name,double value)250 virtual void onDouble(MPlug & plug, const MString & name, double value) override
251 {
252 String nameStr(name.asChar());
253 Element e(mPhysXExporter, nameStr);
254 mPhysXExporter.getStreamWriter().appendValues(value);
255 }
256
onDouble2(MPlug & plug,const MString & name,double value[2])257 virtual void onDouble2(MPlug & plug, const MString & name, double value[2]) override
258 {
259 String nameStr(name.asChar());
260 Element e(mPhysXExporter, nameStr);
261 mPhysXExporter.getStreamWriter().appendValues(value, 2);
262 }
263
onDouble3(MPlug & plug,const MString & name,double value[3])264 virtual void onDouble3(MPlug & plug, const MString & name, double value[3]) override
265 {
266 String nameStr(name.asChar());
267 Element e(mPhysXExporter, nameStr);
268 mPhysXExporter.getStreamWriter().appendValues(value, 3);
269 }
270
onDouble4(MPlug & plug,const MString & name,double value[4])271 virtual void onDouble4(MPlug & plug, const MString & name, double value[4]) override
272 {
273 String nameStr(name.asChar());
274 Element e(mPhysXExporter, nameStr);
275 mPhysXExporter.getStreamWriter().appendValues(value, 4);
276 }
277
onString(MPlug & plug,const MString & name,const MString & value)278 virtual void onString(MPlug & plug, const MString & name, const MString & value) override
279 {
280 String nameStr(name.asChar());
281 Element e(mPhysXExporter, nameStr);
282 mPhysXExporter.getStreamWriter().appendText(value.asChar());
283 }
284
onEnum(MPlug & plug,const MString & name,int enumValue,const MString & enumName)285 virtual void onEnum(MPlug & plug, const MString & name, int enumValue, const MString & enumName) override
286 {
287 String nameStr(name.asChar());
288 Element e(mPhysXExporter, nameStr);
289 mPhysXExporter.getStreamWriter().appendText(enumName.asChar());
290 }
291
onMesh(MPlug & plug,const MString & name,MObject & meshObject)292 virtual void onMesh(MPlug & plug, const MString & name, MObject & meshObject) override
293 {
294 String nameStr(name.asChar());
295 URI meshURI;
296 mPhysXExporter.getMeshURI(meshObject, meshURI);
297 Element e(mPhysXExporter, nameStr);
298 mPhysXExporter.getStreamWriter().appendURIAttribute(CSWC::CSW_ATTRIBUTE_URL, meshURI);
299 }
300
onAngle(MPlug & plug,const MString & name,const MAngle & angle)301 virtual void onAngle(MPlug & plug, const MString & name, const MAngle & angle) override
302 {
303 String nameStr(name.asChar());
304 Element e(mPhysXExporter, nameStr);
305 mPhysXExporter.getStreamWriter().appendValues(
306 angle.asDegrees());
307 }
308
onAngle2(MPlug & plug,const MString & name,const MAngle angle[2])309 virtual void onAngle2(MPlug & plug, const MString & name, const MAngle angle[2]) override
310 {
311 String nameStr(name.asChar());
312 Element e(mPhysXExporter, nameStr);
313 mPhysXExporter.getStreamWriter().appendValues(
314 angle[0].asDegrees(),
315 angle[1].asDegrees());
316 }
317
onAngle3(MPlug & plug,const MString & name,const MAngle angle[3])318 virtual void onAngle3(MPlug & plug, const MString & name, const MAngle angle[3]) override
319 {
320 String nameStr(name.asChar());
321 Element e(mPhysXExporter, nameStr);
322 mPhysXExporter.getStreamWriter().appendValues(
323 angle[0].asDegrees(),
324 angle[1].asDegrees(),
325 angle[2].asDegrees());
326 }
327
onAngle4(MPlug & plug,const MString & name,const MAngle angle[4])328 virtual void onAngle4(MPlug & plug, const MString & name, const MAngle angle[4]) override
329 {
330 String nameStr(name.asChar());
331 Element e(mPhysXExporter, nameStr);
332 mPhysXExporter.getStreamWriter().appendValues(
333 angle[0].asDegrees(),
334 angle[1].asDegrees(),
335 angle[2].asDegrees(),
336 angle[3].asDegrees());
337 }
338
onDistance(MPlug & plug,const MString & name,const MDistance & distance)339 virtual void onDistance(MPlug & plug, const MString & name, const MDistance & distance) override
340 {
341 String nameStr(name.asChar());
342 Element e(mPhysXExporter, nameStr);
343 mPhysXExporter.getStreamWriter().appendValues(
344 MDistance::internalToUI(distance.asCentimeters()));
345 }
346
onDistance2(MPlug & plug,const MString & name,const MDistance distance[2])347 virtual void onDistance2(MPlug & plug, const MString & name, const MDistance distance[2]) override
348 {
349 String nameStr(name.asChar());
350 Element e(mPhysXExporter, nameStr);
351 mPhysXExporter.getStreamWriter().appendValues(
352 MDistance::internalToUI(distance[0].asCentimeters()),
353 MDistance::internalToUI(distance[1].asCentimeters()));
354 }
355
onDistance3(MPlug & plug,const MString & name,const MDistance distance[3])356 virtual void onDistance3(MPlug & plug, const MString & name, const MDistance distance[3]) override
357 {
358 String nameStr(name.asChar());
359 Element e(mPhysXExporter, nameStr);
360 mPhysXExporter.getStreamWriter().appendValues(
361 MDistance::internalToUI(distance[0].asCentimeters()),
362 MDistance::internalToUI(distance[1].asCentimeters()),
363 MDistance::internalToUI(distance[2].asCentimeters()));
364 }
365
onDistance4(MPlug & plug,const MString & name,const MDistance distance[4])366 virtual void onDistance4(MPlug & plug, const MString & name, const MDistance distance[4]) override
367 {
368 String nameStr(name.asChar());
369 Element e(mPhysXExporter, nameStr);
370 mPhysXExporter.getStreamWriter().appendValues(
371 MDistance::internalToUI(distance[0].asCentimeters()),
372 MDistance::internalToUI(distance[1].asCentimeters()),
373 MDistance::internalToUI(distance[2].asCentimeters()),
374 MDistance::internalToUI(distance[3].asCentimeters()));
375 }
376
onTime(MPlug & plug,const MString & name,MTime & time)377 virtual void onTime(MPlug & plug, const MString & name, MTime & time) override
378 {
379 String nameStr(name.asChar());
380 Element e(mPhysXExporter, nameStr);
381 mPhysXExporter.getStreamWriter().appendValues(time.as(MTime::kSeconds));
382 }
383
384 private:
385 PhysXExporter& mPhysXExporter;
386 const std::set<MString, MStringComp>& mAttributes;
387 int mAttributeLevel;
388 };
389
GetType(const MObject & shape,MString & type)390 void PhysXShape::GetType(const MObject & shape, MString & type)
391 {
392 int dummy = 0;
393 DagHelper::getPlugValue(shape, ATTR_SHAPE_TYPE, dummy, type);
394 }
395
GetInMesh(const MObject & shape,MObject & mesh)396 void PhysXShape::GetInMesh(const MObject & shape, MObject & mesh)
397 {
398 DagHelper::getPlugValue(shape, ATTR_IN_MESH, mesh);
399 }
400
GetConnectedInMesh(const MObject & shape,MObject & mesh)401 void PhysXShape::GetConnectedInMesh(const MObject & shape, MObject & mesh)
402 {
403 PhysXExporter::GetPluggedObject(shape, ATTR_IN_MESH, mesh);
404 }
405
findPxMaterial(const MObject & rigidBody) const406 const PhysXXML::PxMaterial* PhysXExporter::findPxMaterial(const MObject & rigidBody) const
407 {
408 std::map<MObject, const PhysXXML::PxMaterial*>::const_iterator it = mRigidBodyToPxMaterialMap.find(rigidBody);
409 if (it != mRigidBodyToPxMaterialMap.end())
410 {
411 return it->second;
412 }
413 return NULL;
414 }
415
findPxMaterial(uint64_t ref) const416 const PhysXXML::PxMaterial* PhysXExporter::findPxMaterial(uint64_t ref) const
417 {
418 return mPhysXDoc->findMaterial(ref);
419 }
420
findPxMaterial(const PhysXXML::PxRigidBody & rigidBody) const421 const PhysXXML::PxMaterial* PhysXExporter::findPxMaterial(const PhysXXML::PxRigidBody & rigidBody) const
422 {
423 if (rigidBody.shapes.shapes.size() > 0)
424 {
425 return findPxMaterial(rigidBody.shapes.shapes[0].materials.materialRef.materialRef);
426 }
427 return NULL;
428 }
429
findPxShape(const MObject & shape) const430 const PhysXXML::PxShape* PhysXExporter::findPxShape(const MObject & shape) const
431 {
432 std::map<MObject, const PhysXXML::PxShape*>::const_iterator it = mShapeToPxShapeMap.find(shape);
433 if (it != mShapeToPxShapeMap.end())
434 {
435 return it->second;
436 }
437 return NULL;
438 }
439
findPxRigidBody(const MObject & rigidBody) const440 const PhysXXML::PxRigidBody* PhysXExporter::findPxRigidBody(const MObject & rigidBody) const
441 {
442 std::map<MObject, const PhysXXML::PxRigidBody*>::const_iterator it = mRigidBodyToPxRigidBodyMap.find(rigidBody);
443 if (it != mRigidBodyToPxRigidBodyMap.end())
444 {
445 return it->second;
446 }
447 return NULL;
448 }
449
findPxRigidBody(const String & name) const450 const PhysXXML::PxRigidBody* PhysXExporter::findPxRigidBody(const String & name) const
451 {
452 return mPhysXDoc->findRigidBody(name);
453 }
454
findPxRigidBody(uint64_t id) const455 const PhysXXML::PxRigidBody* PhysXExporter::findPxRigidBody(uint64_t id) const
456 {
457 return mPhysXDoc->findRigidBody(id);
458 }
459
findPxD6Joint(const MObject & rigidConstraint) const460 const PhysXXML::PxD6Joint* PhysXExporter::findPxD6Joint(const MObject & rigidConstraint) const
461 {
462 std::map<MObject, const PhysXXML::PxD6Joint*>::const_iterator it = mConstraintToPxD6JointMap.find(rigidConstraint);
463 if (it != mConstraintToPxD6JointMap.end())
464 {
465 return it->second;
466 }
467 return NULL;
468 }
469
findMObject(const PhysXXML::PxRigidBody & rigidBody) const470 const MObject & PhysXExporter::findMObject(const PhysXXML::PxRigidBody & rigidBody) const
471 {
472 std::map<const PhysXXML::PxRigidBody*, MObject>::const_iterator it = mPxRigidBodyToRigidBodyMap.find(&rigidBody);
473 if (it != mPxRigidBodyToRigidBodyMap.end())
474 {
475 return it->second;
476 }
477 return MObject::kNullObj;
478 }
479
findMObject(const PhysXXML::PxShape & shape) const480 const MObject & PhysXExporter::findMObject(const PhysXXML::PxShape & shape) const
481 {
482 std::map<const PhysXXML::PxShape*, MObject>::const_iterator it = mPxShapeToShapeMap.find(&shape);
483 if (it != mPxShapeToShapeMap.end())
484 {
485 return it->second;
486 }
487 return MObject::kNullObj;
488 }
489
findMObject(const PhysXXML::PxD6Joint & joint) const490 const MObject & PhysXExporter::findMObject(const PhysXXML::PxD6Joint & joint) const
491 {
492 std::map<const PhysXXML::PxD6Joint*, MObject>::const_iterator it = mPxD6JointToConstraintMap.find(&joint);
493 if (it != mPxD6JointToConstraintMap.end())
494 {
495 return it->second;
496 }
497 return MObject::kNullObj;
498 }
499
getNodeRigidBody(const MObject & node) const500 const MObject & PhysXExporter::getNodeRigidBody(const MObject& node) const
501 {
502 std::map<MObject, MObject>::const_iterator it = mTargetToRigidBodyMap.find(node);
503 if (it != mTargetToRigidBodyMap.end())
504 {
505 return it->second;
506 }
507 return MObject::kNullObj;
508 }
509
getShapeLocalPose(const MObject & shape,MMatrix & localPose) const510 void PhysXExporter::getShapeLocalPose(/*const MObject& rigidBody, */const MObject& shape, MMatrix& localPose) const
511 {
512 const PhysXXML::PxShape* pxShape = findPxShape(/*rigidBody, */shape);
513 if (!pxShape)
514 return;
515 localPose = PxTransformToMMatrix(pxShape->localPose.translation, pxShape->localPose.rotation);
516 }
517
getShapeVertices(const MObject & shape,std::vector<PhysXXML::Point> & vertices,MString & meshId)518 bool PhysXExporter::getShapeVertices(const MObject& shape, std::vector<PhysXXML::Point> & vertices, MString & meshId)
519 {
520 const PhysXXML::PxShape* pxShape = findPxShape(shape);
521 if (pxShape == NULL) return false;
522
523 if (pxShape->geometry.type == PhysXXML::Geometry::ConvexMesh)
524 {
525 if (PhysXXML::PxConvexMesh* convexMesh = mPhysXDoc->findConvexMesh(pxShape->geometry.convexMeshGeometry.convexMesh.convexMesh))
526 {
527 vertices = convexMesh->points.points;
528 std::stringstream s;
529 s << "_" << convexMesh->id.id;
530 meshId = s.str().c_str();
531 return true;
532 }
533 }
534 else if (pxShape->geometry.type == PhysXXML::Geometry::TriangleMesh)
535 {
536 if (PhysXXML::PxTriangleMesh* triangleMesh = mPhysXDoc->findTriangleMesh(pxShape->geometry.triangleMeshGeometry.triangleMesh.triangleMesh))
537 {
538 vertices = triangleMesh->points.points;
539 std::stringstream s;
540 s << "_" << triangleMesh->id.id;
541 meshId = s.str().c_str();
542 return true;
543 }
544 }
545 return false;
546 }
547
getShapeTriangles(const MObject & shape,std::vector<PhysXXML::Triangle> & triangles)548 bool PhysXExporter::getShapeTriangles(const MObject& shape, std::vector<PhysXXML::Triangle> & triangles)
549 {
550 const PhysXXML::PxShape* pxShape = findPxShape(shape);
551 if (pxShape == NULL) return false;
552
553 if (pxShape->geometry.type == PhysXXML::Geometry::TriangleMesh)
554 {
555 if (PhysXXML::PxTriangleMesh* triangleMesh = mPhysXDoc->findTriangleMesh(pxShape->geometry.triangleMeshGeometry.triangleMesh.triangleMesh))
556 {
557 triangles = triangleMesh->triangles.triangles;
558 return true;
559 }
560 }
561 return false;
562 }
563
getRigidBodyGlobalPose(const MObject & rigidBody,MMatrix & globalPose)564 void PhysXExporter::getRigidBodyGlobalPose(const MObject& rigidBody, MMatrix& globalPose)
565 {
566 if (const PhysXXML::PxRigidBody* pxRigidBody = findPxRigidBody(rigidBody))
567 {
568 globalPose = PxTransformToMMatrix(pxRigidBody->globalPose.translation, pxRigidBody->globalPose.rotation);
569 }
570 }
571
getRigidSolver() const572 const MObject & PhysXExporter::getRigidSolver() const
573 {
574 return mRigidSolver;
575 }
576
577 class Dynamic : public Element
578 {
579 public:
Dynamic(PhysXExporter & exporter,bool value)580 Dynamic(PhysXExporter& exporter, bool value)
581 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY_DYNAMIC)
582 {
583 getStreamWriter().appendValues(value);
584 }
585 };
586
587 class Mass : public Element
588 {
589 public:
Mass(PhysXExporter & exporter,double mass)590 Mass(PhysXExporter& exporter, double mass)
591 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY_MASS)
592 {
593 getStreamWriter().appendValues(mass);
594 }
595 };
596
597 class MassFrame : public Element
598 {
599 public:
MassFrame(PhysXExporter & exporter,const MVector & t,const MQuaternion & r,const String & tSid="",const String & rSid="")600 MassFrame(PhysXExporter& exporter, const MVector & t, const MQuaternion & r, const String & tSid = "", const String & rSid = "")
601 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY_MASS_FRAME)
602 {
603 getPhysXExporter().exportTranslationWithoutConversion(t, tSid);
604 getPhysXExporter().exportRotation(r.asEulerRotation(), rSid);
605 }
606
AreDefaultValues(PhysXExporter & exporter,const MVector & t,const MQuaternion & r)607 static bool AreDefaultValues(PhysXExporter & exporter, const MVector & t, const MQuaternion & r)
608 {
609 bool zero_translation =
610 COLLADABU::Math::Utils::equalsZero(t.x, exporter.getDocumentExporter().getTolerance()) &&
611 COLLADABU::Math::Utils::equalsZero(t.y, exporter.getDocumentExporter().getTolerance()) &&
612 COLLADABU::Math::Utils::equalsZero(t.z, exporter.getDocumentExporter().getTolerance());
613
614 RotateHelper rotation(r.asEulerRotation());
615 bool zero_rotation = rotation.isIdentity(exporter.getDocumentExporter().getTolerance());
616
617 return zero_translation && zero_rotation;
618 }
619 };
620
621 class Inertia : public Element
622 {
623 public:
Inertia(PhysXExporter & exporter,const MVector & inertia)624 Inertia(PhysXExporter& exporter, const MVector & inertia)
625 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY_INERTIA)
626 {
627 getStreamWriter().appendValues(inertia.x, inertia.y, inertia.z);
628 }
629 };
630
631 class Restitution : public Element
632 {
633 public:
Restitution(PhysXExporter & exporter,double restitution)634 Restitution(PhysXExporter& exporter, double restitution)
635 : Element(exporter, CSWC::CSW_ELEMENT_RESTITUTION)
636 {
637 getStreamWriter().appendValues(restitution);
638 }
639
DefaultValue()640 static double DefaultValue()
641 {
642 return 0.0;
643 }
644 };
645
646 class DynamicFriction : public Element
647 {
648 public:
DynamicFriction(PhysXExporter & exporter,double dynamicFriction)649 DynamicFriction(PhysXExporter& exporter, double dynamicFriction)
650 : Element(exporter, CSWC::CSW_ELEMENT_DYNAMIC_FRICTION)
651 {
652 getStreamWriter().appendValues(dynamicFriction);
653 }
654
DefaultValue()655 static double DefaultValue()
656 {
657 return 0.0;
658 }
659 };
660
661 class StaticFriction : public Element
662 {
663 public:
StaticFriction(PhysXExporter & exporter,double staticFriction)664 StaticFriction(PhysXExporter& exporter, double staticFriction)
665 : Element(exporter, CSWC::CSW_ELEMENT_STATIC_FRICTION)
666 {
667 getStreamWriter().appendValues(staticFriction);
668 }
669
DefaultValue()670 static double DefaultValue()
671 {
672 return 0.0;
673 }
674 };
675
676 class FrictionCombineMode : public Element
677 {
678 public:
FrictionCombineMode(PhysXExporter & exporter,const PhysXXML::CombineMode::FlagEnum & combineMode)679 FrictionCombineMode(PhysXExporter & exporter, const PhysXXML::CombineMode::FlagEnum & combineMode)
680 : Element(exporter, CSWC::CSW_ELEMENT_FRICTION_COMBINE_MODE, withPrefix)
681 {
682 getStreamWriter().appendValues(PhysXExporter::CombineModeToCOLLADA(combineMode));
683 }
684
DefaultValue()685 static PhysXXML::CombineMode::FlagEnum DefaultValue()
686 {
687 return PhysXXML::CombineMode::Average;
688 }
689 };
690
691 class RestitutionCombineMode : public Element
692 {
693 public:
RestitutionCombineMode(PhysXExporter & exporter,const PhysXXML::CombineMode::FlagEnum & combineMode)694 RestitutionCombineMode(PhysXExporter & exporter, const PhysXXML::CombineMode::FlagEnum & combineMode)
695 : Element(exporter, CSWC::CSW_ELEMENT_RESTITUTION_COMBINE_MODE, withPrefix)
696 {
697 getStreamWriter().appendValues(PhysXExporter::CombineModeToCOLLADA(combineMode));
698 }
699
DefaultValue()700 static PhysXXML::CombineMode::FlagEnum DefaultValue()
701 {
702 return PhysXXML::CombineMode::Average;
703 }
704 };
705
706 class PxMaterial : public Element
707 {
708 public:
PxMaterial(PhysXExporter & exporter,const PhysXXML::PxMaterial & mat)709 PxMaterial(PhysXExporter & exporter, const PhysXXML::PxMaterial & mat)
710 : Element(exporter, CSWC::CSW_ELEMENT_PX_MATERIAL, withPrefix)
711 {
712 exportFrictionCombineMode(mat);
713 exportRestitutionCombineMode(mat);
714 }
715
HasDefaultValues(const PhysXXML::PxMaterial & mat)716 static bool HasDefaultValues(const PhysXXML::PxMaterial & mat)
717 {
718 return
719 mat.frictionCombineMode.frictionCombineMode == FrictionCombineMode::DefaultValue() &&
720 mat.restitutionCombineMode.restitutionCombineMode == RestitutionCombineMode::DefaultValue();
721 }
722
723 private:
exportFrictionCombineMode(const PhysXXML::PxMaterial & mat)724 void exportFrictionCombineMode(const PhysXXML::PxMaterial & mat)
725 {
726 if (mat.frictionCombineMode.frictionCombineMode != FrictionCombineMode::DefaultValue())
727 {
728 FrictionCombineMode e(getPhysXExporter(), mat.frictionCombineMode.frictionCombineMode);
729 }
730 }
731
exportRestitutionCombineMode(const PhysXXML::PxMaterial & mat)732 void exportRestitutionCombineMode(const PhysXXML::PxMaterial & mat)
733 {
734 if (mat.restitutionCombineMode.restitutionCombineMode != RestitutionCombineMode::DefaultValue())
735 {
736 RestitutionCombineMode e(getPhysXExporter(), mat.restitutionCombineMode.restitutionCombineMode);
737 }
738 }
739 };
740
741 class PhysicsMaterialTechnique : public Element
742 {
743 public:
PhysicsMaterialTechnique(PhysXExporter & exporter,const PhysXXML::PxMaterial & material,const String & profile)744 PhysicsMaterialTechnique(PhysXExporter& exporter, const PhysXXML::PxMaterial & material, const String& profile)
745 : Element(exporter, CSWC::CSW_ELEMENT_TECHNIQUE)
746 {
747 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_PROFILE, profile);
748 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_XMLNS + ":" + CSWC::CSW_PREFIX_PX, PhysXExporter::GetXMLNS());
749 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_XSI_SCHEMALOCATION, PhysXExporter::GetXSISchemaLocation());
750 if (profile == PhysXExporter::GetPhysXProfile())
751 {
752 exportPxMaterial(material);
753 }
754 }
755
HasDefaultValues(const PhysXXML::PxMaterial & mat,const String & profile)756 static bool HasDefaultValues(const PhysXXML::PxMaterial & mat, const String & profile)
757 {
758 if (profile == PhysXExporter::GetPhysXProfile())
759 {
760 return PxMaterial::HasDefaultValues(mat);
761 }
762 return false;
763 }
764
765 private:
exportPxMaterial(const PhysXXML::PxMaterial & mat)766 void exportPxMaterial(const PhysXXML::PxMaterial & mat)
767 {
768 if (!PxMaterial::HasDefaultValues(mat))
769 {
770 PxMaterial e(getPhysXExporter(), mat);
771 }
772 }
773 };
774
775 class PhysicsMaterialExtra : public Element
776 {
777 public:
PhysicsMaterialExtra(PhysXExporter & exporter,const PhysXXML::PxMaterial & material)778 PhysicsMaterialExtra(PhysXExporter& exporter, const PhysXXML::PxMaterial & material)
779 : Element(exporter, CSWC::CSW_ELEMENT_EXTRA)
780 {
781 exportTechnique(material, PhysXExporter::GetPhysXProfile());
782 }
783
HasDefaultValues(const PhysXXML::PxMaterial & mat)784 static bool HasDefaultValues(const PhysXXML::PxMaterial & mat)
785 {
786 return PhysicsMaterialTechnique::HasDefaultValues(mat, PhysXExporter::GetPhysXProfile());
787 }
788
789 private:
exportTechnique(const PhysXXML::PxMaterial & material,const String & profile)790 void exportTechnique(const PhysXXML::PxMaterial & material, const String & profile)
791 {
792 if (!PhysicsMaterialTechnique::HasDefaultValues(material, profile))
793 {
794 PhysicsMaterialTechnique e(getPhysXExporter(), material, profile);
795 }
796 }
797
deprecated_exportTechnique(const PhysXXML::PxMaterial & material,const String & profile)798 void deprecated_exportTechnique(const PhysXXML::PxMaterial & material, const String& profile)
799 {
800 if (!PhysicsMaterialTechnique::HasDefaultValues(material, profile))
801 {
802 PhysicsMaterialTechnique e(getPhysXExporter(), material, profile);
803 }
804 }
805 };
806
807 class PhysicsMaterialTechniqueCommon : public Element
808 {
809 public:
PhysicsMaterialTechniqueCommon(PhysXExporter & exporter,const PhysXXML::PxMaterial & material)810 PhysicsMaterialTechniqueCommon(PhysXExporter& exporter, const PhysXXML::PxMaterial & material)
811 : Element(exporter, CSWC::CSW_ELEMENT_TECHNIQUE_COMMON)
812 {
813 exportDynamicFriction(material);
814 exportRestitution(material);
815 exportStaticFriction(material);
816 }
817
818 private:
exportRestitution(const PhysXXML::PxMaterial & material)819 void exportRestitution(const PhysXXML::PxMaterial & material)
820 {
821 if (material.restitution.restitution != Restitution::DefaultValue())
822 {
823 Restitution e(getPhysXExporter(), material.restitution.restitution);
824 }
825 }
826
exportDynamicFriction(const PhysXXML::PxMaterial & material)827 void exportDynamicFriction(const PhysXXML::PxMaterial & material)
828 {
829 if (material.dynamicFriction.dynamicFriction != DynamicFriction::DefaultValue())
830 {
831 DynamicFriction e(getPhysXExporter(), material.dynamicFriction.dynamicFriction);
832 }
833 }
834
exportStaticFriction(const PhysXXML::PxMaterial & material)835 void exportStaticFriction(const PhysXXML::PxMaterial & material)
836 {
837 if (material.staticFriction.staticFriction != StaticFriction::DefaultValue())
838 {
839 StaticFriction e(getPhysXExporter(), material.staticFriction.staticFriction);
840 }
841 }
842 };
843
844 class PhysicsMaterial : public Element
845 {
846 public:
PhysicsMaterial(PhysXExporter & exporter,const PhysXXML::PxMaterial & material,const String & id)847 PhysicsMaterial(PhysXExporter& exporter, const PhysXXML::PxMaterial & material, const String & id)
848 : Element(exporter, CSWC::CSW_ELEMENT_PHYSICS_MATERIAL)
849 {
850 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_ID, id);
851
852 exportTechniqueCommon(material);
853 exportExtra(material);
854 }
855
856 private:
exportTechniqueCommon(const PhysXXML::PxMaterial & material)857 void exportTechniqueCommon(const PhysXXML::PxMaterial & material)
858 {
859 PhysicsMaterialTechniqueCommon e(getPhysXExporter(), material);
860 }
861
exportExtra(const PhysXXML::PxMaterial & material)862 void exportExtra(const PhysXXML::PxMaterial & material)
863 {
864 if (!PhysicsMaterialExtra::HasDefaultValues(material))
865 {
866 PhysicsMaterialExtra e(getPhysXExporter(), material);
867 }
868 }
869 };
870
871 class Hollow : public Element
872 {
873 public:
Hollow(PhysXExporter & exporter,bool hollow)874 Hollow(PhysXExporter& exporter, bool hollow)
875 : Element(exporter, CSWC::CSW_ELEMENT_HOLLOW)
876 {
877 getStreamWriter().appendValues(hollow);
878 }
879 };
880
881 class HalfExtents : public Element
882 {
883 public:
HalfExtents(PhysXExporter & exporter,const MVector & halfExtents)884 HalfExtents(PhysXExporter& exporter, const MVector & halfExtents)
885 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY_SHAPE_BOX_EXTENTS)
886 {
887 getStreamWriter().appendValues(halfExtents.x, halfExtents.y, halfExtents.z);
888 }
889 };
890
891 class ShapeBox : public Element
892 {
893 public:
ShapeBox(PhysXExporter & exporter,const PhysXXML::PxShape & shape)894 ShapeBox(PhysXExporter& exporter, const PhysXXML::PxShape & shape)
895 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY_SHAPE_BOX)
896 {
897 exportHalfExtents(shape);
898 }
899
900 private:
exportHalfExtents(const PhysXXML::PxShape & shape)901 void exportHalfExtents(const PhysXXML::PxShape & shape)
902 {
903 HalfExtents e(getPhysXExporter(), shape.geometry.boxGeometry.halfExtents.halfExtents);
904 }
905 };
906
907 class CapsuleRadius : public Element
908 {
909 public:
CapsuleRadius(PhysXExporter & exporter,double radiusX,double radiusZ)910 CapsuleRadius(PhysXExporter& exporter, double radiusX, double radiusZ)
911 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY_SHAPE_CAPSULE_RADIUS)
912 {
913 getStreamWriter().appendValues(radiusX, radiusZ);
914 }
915 };
916
917 class SphereRadius : public Element
918 {
919 public:
SphereRadius(PhysXExporter & exporter,double radius)920 SphereRadius(PhysXExporter& exporter, double radius)
921 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY_SHAPE_CAPSULE_RADIUS)
922 {
923 getStreamWriter().appendValues(radius);
924 }
925 };
926
927 class ShapeSphere : public Element
928 {
929 public:
ShapeSphere(PhysXExporter & exporter,const PhysXXML::PxShape & shape)930 ShapeSphere(PhysXExporter& exporter, const PhysXXML::PxShape & shape)
931 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY_SHAPE_SPHERE)
932 {
933 exportRadius(shape);
934 }
935
936 private:
exportRadius(const PhysXXML::PxShape & shape)937 void exportRadius(const PhysXXML::PxShape & shape)
938 {
939 SphereRadius e(getPhysXExporter(), shape.geometry.sphereGeometry.radius.radius);
940 }
941 };
942
943 class Height : public Element
944 {
945 public:
Height(PhysXExporter & exporter,double height)946 Height(PhysXExporter& exporter, double height)
947 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY_SHAPE_CAPSULE_HEIGHT)
948 {
949 getStreamWriter().appendValues(height);
950 }
951 };
952
953 class ShapeCapsule : public Element
954 {
955 public:
ShapeCapsule(PhysXExporter & exporter,const PhysXXML::PxShape & shape)956 ShapeCapsule(PhysXExporter& exporter, const PhysXXML::PxShape & shape)
957 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY_SHAPE_CAPSULE)
958 {
959 exportHeight(shape);
960 exportRadius(shape);
961 }
962
963 private:
exportRadius(const PhysXXML::PxShape & shape)964 void exportRadius(const PhysXXML::PxShape & shape)
965 {
966 CapsuleRadius e(getPhysXExporter(), shape.geometry.capsuleGeometry.radius.radius, shape.geometry.capsuleGeometry.radius.radius);
967 }
968
exportHeight(const PhysXXML::PxShape & shape)969 void exportHeight(const PhysXXML::PxShape & shape)
970 {
971 Height e(getPhysXExporter(), shape.geometry.capsuleGeometry.halfHeight.halfHeight * 2.0);
972 }
973 };
974
975 class Equation : public Element
976 {
977 public:
Equation(PhysXExporter & exporter,double a,double b,double c,double d)978 Equation(PhysXExporter& exporter, double a, double b, double c, double d)
979 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY_SHAPE_PLANE_EQUATION)
980 {
981 getStreamWriter().appendValues(a, b, c, d);
982 }
983 };
984
985 class ShapePlane : public Element
986 {
987 public:
ShapePlane(PhysXExporter & exporter,double a,double b,double c,double d)988 ShapePlane(PhysXExporter& exporter, double a, double b, double c, double d)
989 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY_SHAPE_PLANE)
990 {
991 exportEquation(a, b, c, d);
992 }
993
994 private:
exportEquation(double a,double b,double c,double d)995 void exportEquation(double a, double b, double c, double d)
996 {
997 Equation e(getPhysXExporter(), a, b, c, d);
998 }
999 };
1000
1001 class InstanceGeometry : public Element
1002 {
1003 public:
InstanceGeometry(PhysXExporter & exporter,const URI & geometryURI)1004 InstanceGeometry(PhysXExporter& exporter, const URI & geometryURI)
1005 : Element(exporter, CSWC::CSW_ELEMENT_INSTANCE_GEOMETRY)
1006 {
1007 getStreamWriter().appendURIAttribute(CSWC::CSW_ATTRIBUTE_URL, geometryURI);
1008 }
1009 };
1010
1011 class Density : public Element
1012 {
1013 public:
Density(PhysXExporter & exporter,double density)1014 Density(PhysXExporter& exporter, double density)
1015 : Element(exporter, CSWC::CSW_ELEMENT_DENSITY)
1016 {
1017 getStreamWriter().appendValues(density);
1018 }
1019 };
1020
1021 class LocalPose : public Element
1022 {
1023 public:
LocalPose(PhysXExporter & exporter,const MQuaternion & rotation,const MVector & translation)1024 LocalPose(PhysXExporter& exporter, const MQuaternion& rotation, const MVector& translation)
1025 : Element(exporter, CSWC::CSW_ELEMENT_LOCAL_POSE, withPrefix)
1026 {
1027 double localPose[] = { rotation.x, rotation.y, rotation.z, rotation.w, translation.x, translation.y, translation.z };
1028 getStreamWriter().appendValues(localPose, sizeof(localPose) / sizeof(localPose[0]));
1029 }
1030 };
1031
1032 class SimulationFilterData : public Element
1033 {
1034 public:
SimulationFilterData(PhysXExporter & exporter,int f0,int f1,int f2,int f3)1035 SimulationFilterData(PhysXExporter & exporter, int f0, int f1, int f2, int f3)
1036 : Element(exporter, CSWC::CSW_ELEMENT_SIMULATION_FILTER_DATA, withPrefix)
1037 {
1038 getStreamWriter().appendValues(f0, f1, f2, f3);
1039 }
1040
AreDefaultValues(int f0,int f1,int f2,int f3)1041 static bool AreDefaultValues(int f0, int f1, int f2, int f3)
1042 {
1043 return f0 == 0 && f1 == 0 && f2 == 0 && f3 == 0;
1044 }
1045 };
1046
1047 class QueryFilterData : public Element
1048 {
1049 public:
QueryFilterData(PhysXExporter & exporter,int f0,int f1,int f2,int f3)1050 QueryFilterData(PhysXExporter & exporter, int f0, int f1, int f2, int f3)
1051 : Element(exporter, CSWC::CSW_ELEMENT_QUERY_FILTER_DATA, withPrefix)
1052 {
1053 getStreamWriter().appendValues(f0, f1, f2, f3);
1054 }
1055
AreDefaultValues(int f0,int f1,int f2,int f3)1056 static bool AreDefaultValues(int f0, int f1, int f2, int f3)
1057 {
1058 return f0 == 0 && f1 == 0 && f2 == 0 && f3 == 0;
1059 }
1060 };
1061
1062 class ContactOffset : public Element
1063 {
1064 public:
ContactOffset(PhysXExporter & exporter,double contactOffset)1065 ContactOffset(PhysXExporter & exporter, double contactOffset)
1066 : Element(exporter, CSWC::CSW_ELEMENT_CONTACT_OFFSET, withPrefix)
1067 {
1068 getStreamWriter().appendValues(contactOffset);
1069 }
1070
DefaultValue()1071 static double DefaultValue()
1072 {
1073 return 0.02;
1074 }
1075 };
1076
1077 class RestOffset : public Element
1078 {
1079 public:
RestOffset(PhysXExporter & exporter,double restOffset)1080 RestOffset(PhysXExporter & exporter, double restOffset)
1081 : Element(exporter, CSWC::CSW_ELEMENT_REST_OFFSET, withPrefix)
1082 {
1083 getStreamWriter().appendValues(restOffset);
1084 }
1085
DefaultValue()1086 static double DefaultValue()
1087 {
1088 return 0.0;
1089 }
1090 };
1091
1092 class ShapeFlags : public Element
1093 {
1094 public:
ShapeFlags(PhysXExporter & exporter,const Flags<PhysXXML::ShapeFlags::FlagEnum> & flags)1095 ShapeFlags(PhysXExporter & exporter, const Flags<PhysXXML::ShapeFlags::FlagEnum> & flags)
1096 : Element(exporter, CSWC::CSW_ELEMENT_SHAPE_FLAGS, withPrefix)
1097 {
1098 getStreamWriter().appendText(PhysXExporter::ShapeFlagsToCOLLADA(flags));
1099 }
1100
DefaultValue()1101 static Flags<PhysXXML::ShapeFlags::FlagEnum> DefaultValue()
1102 {
1103 return Flags<PhysXXML::ShapeFlags::FlagEnum>(
1104 PhysXXML::ShapeFlags::Visualization |
1105 PhysXXML::ShapeFlags::SimulationShape |
1106 PhysXXML::ShapeFlags::SceneQueryShape);
1107 }
1108 };
1109
1110 class DebugName : public Element
1111 {
1112 public:
DebugName(PhysXExporter & exporter,const String & name)1113 DebugName(PhysXExporter & exporter, const String & name)
1114 : Element(exporter, CSWC::CSW_ELEMENT_NAME, withPrefix)
1115 {
1116 getStreamWriter().appendText(name);
1117 }
1118
DefaultValue()1119 static String DefaultValue()
1120 {
1121 return "";
1122 }
1123 };
1124
1125 class PxShape : public Element
1126 {
1127 public:
PxShape(PhysXExporter & exporter,const PhysXXML::PxShape & shape)1128 PxShape(PhysXExporter& exporter, const PhysXXML::PxShape & shape)
1129 : Element(exporter, CSWC::CSW_ELEMENT_PX_SHAPE, withPrefix)
1130 {
1131 exportLocalPose(shape);
1132 exportSimulationFilterData(shape);
1133 exportQueryFilterData(shape);
1134 exportContactOffset(shape);
1135 exportRestOffset(shape);
1136 exportShapeFlags(shape);
1137 exportName(shape);
1138 }
1139
HasDefaultValues(const PhysXXML::PxShape & shape)1140 static bool HasDefaultValues(const PhysXXML::PxShape & shape)
1141 {
1142 // Always export local pose
1143 return false;
1144 }
1145
1146 private:
exportLocalPose(const PhysXXML::PxShape & shape)1147 void exportLocalPose(const PhysXXML::PxShape & shape)
1148 {
1149 LocalPose e(getPhysXExporter(), shape.localPose.rotation, shape.localPose.translation);
1150 }
1151
exportSimulationFilterData(const PhysXXML::PxShape & shape)1152 void exportSimulationFilterData(const PhysXXML::PxShape & shape)
1153 {
1154 if (!SimulationFilterData::AreDefaultValues(
1155 shape.simulationFilterData.filter0,
1156 shape.simulationFilterData.filter1,
1157 shape.simulationFilterData.filter2,
1158 shape.simulationFilterData.filter3))
1159 {
1160 SimulationFilterData e(
1161 getPhysXExporter(),
1162 shape.simulationFilterData.filter0,
1163 shape.simulationFilterData.filter1,
1164 shape.simulationFilterData.filter2,
1165 shape.simulationFilterData.filter3
1166 );
1167 }
1168 }
1169
exportQueryFilterData(const PhysXXML::PxShape & shape)1170 void exportQueryFilterData(const PhysXXML::PxShape & shape)
1171 {
1172 if (!QueryFilterData::AreDefaultValues(
1173 shape.queryFilterData.filter0,
1174 shape.queryFilterData.filter1,
1175 shape.queryFilterData.filter2,
1176 shape.queryFilterData.filter3))
1177 {
1178 QueryFilterData e(
1179 getPhysXExporter(),
1180 shape.queryFilterData.filter0,
1181 shape.queryFilterData.filter1,
1182 shape.queryFilterData.filter2,
1183 shape.queryFilterData.filter3
1184 );
1185 }
1186 }
1187
exportContactOffset(const PhysXXML::PxShape & shape)1188 void exportContactOffset(const PhysXXML::PxShape & shape)
1189 {
1190 if (shape.contactOffset.contactOffset != ContactOffset::DefaultValue())
1191 {
1192 ContactOffset e(getPhysXExporter(), shape.contactOffset.contactOffset);
1193 }
1194 }
1195
exportRestOffset(const PhysXXML::PxShape & shape)1196 void exportRestOffset(const PhysXXML::PxShape & shape)
1197 {
1198 if (shape.restOffset.restOffset != RestOffset::DefaultValue())
1199 {
1200 RestOffset e(getPhysXExporter(), shape.restOffset.restOffset);
1201 }
1202 }
1203
exportShapeFlags(const PhysXXML::PxShape & shape)1204 void exportShapeFlags(const PhysXXML::PxShape & shape)
1205 {
1206 if (shape.flags.flags != ShapeFlags::DefaultValue())
1207 {
1208 ShapeFlags e(getPhysXExporter(), shape.flags.flags);
1209 }
1210 }
1211
exportName(const PhysXXML::PxShape & shape)1212 void exportName(const PhysXXML::PxShape & shape)
1213 {
1214 if (shape.name.name != DebugName::DefaultValue())
1215 {
1216 DebugName e(getPhysXExporter(), shape.name.name);
1217 }
1218 }
1219 };
1220
1221 class ShapeTechnique : public Element
1222 {
1223 public:
ShapeTechnique(PhysXExporter & exporter,const MObject & shape,const PhysXXML::PxShape & pxShape,const String & profile)1224 ShapeTechnique(PhysXExporter& exporter, const MObject& shape, const PhysXXML::PxShape & pxShape, const String & profile)
1225 : Element(exporter, CSWC::CSW_ELEMENT_TECHNIQUE)
1226 {
1227 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_PROFILE, profile);
1228 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_XMLNS + ":" + CSWC::CSW_PREFIX_PX, PhysXExporter::GetXMLNS());
1229 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_XSI_SCHEMALOCATION, PhysXExporter::GetXSISchemaLocation());
1230 if (profile == PROFILE_MAYA) {
1231 exporter.exportExtraAttributes(shape);
1232 }
1233 else if (profile == PhysXExporter::GetPhysXProfile()) {
1234 exportPxShape(pxShape);
1235 }
1236 }
1237
HasDefaultValues(const MObject & shape,const PhysXXML::PxShape & pxShape,const String & profile)1238 static bool HasDefaultValues(const MObject & shape, const PhysXXML::PxShape & pxShape, const String & profile)
1239 {
1240 if (profile == PhysXExporter::GetPhysXProfile())
1241 {
1242 return PxShape::HasDefaultValues(pxShape);
1243 }
1244 else if (profile == PROFILE_MAYA)
1245 {
1246 return !PhysXExporter::HasExtraAttributes(shape);
1247 }
1248 return true;
1249 }
1250
1251 private:
exportPxShape(const PhysXXML::PxShape & shape)1252 void exportPxShape(const PhysXXML::PxShape & shape)
1253 {
1254 if (!PxShape::HasDefaultValues(shape))
1255 {
1256 PxShape e(getPhysXExporter(), shape);
1257 }
1258 }
1259
1260 private:
1261 static std::set<MString, MStringComp> mAttributes;
1262 };
1263 std::set<MString, MStringComp> ShapeTechnique::mAttributes;
1264
1265 class ShapeExtra : public Element
1266 {
1267 public:
ShapeExtra(PhysXExporter & exporter,const MObject & shape,const PhysXXML::PxShape & pxShape)1268 ShapeExtra(PhysXExporter& exporter, const MObject& shape, const PhysXXML::PxShape & pxShape)
1269 : Element(exporter, CSWC::CSW_ELEMENT_EXTRA)
1270 {
1271 if (PhysXExporter::HasExtraAttributes(shape)) {
1272 exportProfile(shape, pxShape, PROFILE_MAYA);
1273 }
1274
1275 exportProfile(shape, pxShape, PhysXExporter::GetPhysXProfile());
1276 }
1277
HasDefaultValues(const MObject & shape,const PhysXXML::PxShape & pxShape)1278 static bool HasDefaultValues(const MObject & shape, const PhysXXML::PxShape & pxShape)
1279 {
1280 return
1281 ShapeTechnique::HasDefaultValues(shape, pxShape, PROFILE_MAYA) &&
1282 ShapeTechnique::HasDefaultValues(shape, pxShape, PhysXExporter::GetPhysXProfile());
1283 }
1284
1285 private:
exportProfile(const MObject & shape,const PhysXXML::PxShape & pxShape,const String & profile)1286 void exportProfile(const MObject& shape, const PhysXXML::PxShape & pxShape, const String& profile)
1287 {
1288 if (!ShapeTechnique::HasDefaultValues(shape, pxShape, profile))
1289 {
1290 ShapeTechnique e(getPhysXExporter(), shape, pxShape, profile);
1291 }
1292 }
1293 };
1294
1295 class Shape : public Element
1296 {
1297 public:
Shape(PhysXExporter & exporter,const MObject & rigidBody,const PhysXXML::PxRigidBody & pxRigidBody,const MObject & shape,const PhysXXML::PxShape & pxShape)1298 Shape(PhysXExporter& exporter,
1299 const MObject & rigidBody,
1300 const PhysXXML::PxRigidBody & pxRigidBody,
1301 const MObject & shape,
1302 const PhysXXML::PxShape & pxShape)
1303 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY_SHAPE)
1304 {
1305 exportHollow(shape);
1306
1307 int dummy = 0;
1308 MString useMassOrDensity;
1309 DagHelper::getPlugValue(shape, ATTR_USE_MASS_OR_DENSITY, dummy, useMassOrDensity);
1310 if (useMassOrDensity == USE_MASS_OR_DENSITY_MASS)
1311 {
1312 exportMass(shape);
1313 }
1314 else //if (useMassOrDensity == USE_MASS_OR_DENSITY_DENSITY)
1315 {
1316 exportDensity(shape);
1317 }
1318
1319 //no <physics_material> exported for shapes. Use rigid body's one.
1320
1321 switch (pxShape.geometry.type)
1322 {
1323 case PhysXXML::Geometry::Box: exportBox(pxShape); break;
1324 case PhysXXML::Geometry::Sphere: exportSphere(pxShape); break;
1325 case PhysXXML::Geometry::Capsule: exportCapsule(pxShape); break;
1326 case PhysXXML::Geometry::ConvexMesh: exportConvexHull(rigidBody, shape); break;
1327 case PhysXXML::Geometry::TriangleMesh: exportTriangleMesh(rigidBody, shape); break;
1328 case PhysXXML::Geometry::Plane: exportPlane(pxShape); break;
1329 }
1330
1331 exportRotateTranslate(rigidBody, pxRigidBody, shape, pxShape);
1332 exportExtra(shape, pxShape);
1333 }
1334
1335 private:
exportHollow(const MObject & shape)1336 void exportHollow(const MObject & shape)
1337 {
1338 //Hollow hollow(getPhysXExporter(), false);
1339 }
1340
exportMass(const MObject & shape)1341 void exportMass(const MObject & shape)
1342 {
1343 double mass = 0.0;
1344 DagHelper::getPlugValue(shape, ATTR_MASS, mass);
1345 Mass e(getPhysXExporter(), mass);
1346 }
1347
exportDensity(const MObject & shape)1348 void exportDensity(const MObject & shape)
1349 {
1350 double density = 0.0;
1351 DagHelper::getPlugValue(shape, ATTR_DENSITY, density);
1352 // g/cm3 to kg/m3
1353 Density e(getPhysXExporter(), density * 1000.0);
1354 }
1355
exportBox(const PhysXXML::PxShape & shape)1356 void exportBox(const PhysXXML::PxShape & shape)
1357 {
1358 ShapeBox e(getPhysXExporter(), shape);
1359 }
1360
exportSphere(const PhysXXML::PxShape & shape)1361 void exportSphere(const PhysXXML::PxShape & shape)
1362 {
1363 ShapeSphere e(getPhysXExporter(), shape);
1364 }
1365
exportCapsule(const PhysXXML::PxShape & shape)1366 void exportCapsule(const PhysXXML::PxShape & shape)
1367 {
1368 ShapeCapsule e(getPhysXExporter(), shape);
1369 }
1370
exportConvexHull(const MObject & rigidBody,const MObject & shape)1371 void exportConvexHull(const MObject & rigidBody, const MObject & shape)
1372 {
1373 // TODO PhysX: apply "inflate" attribute to convex hull geometry.
1374 // Note: apply inflation like done for box shape. See ShapeBox::exportHalfExtents().
1375 // However "inflate" attribute is limited to [0; 0.839] for some unknown reason.
1376 exportInstanceGeometry(rigidBody, shape, "_");
1377 }
1378
exportTriangleMesh(const MObject & rigidBody,const MObject & shape)1379 void exportTriangleMesh(const MObject & rigidBody, const MObject & shape)
1380 {
1381 exportInstanceGeometry(rigidBody, shape);
1382 }
1383
exportPlane(const PhysXXML::PxShape & shape)1384 void exportPlane(const PhysXXML::PxShape & shape)
1385 {
1386 // Plane equation. PhysX plane normal is along X axis. Normal and distance are calculated from shape transform.
1387 double a = 1.0;
1388 double b = 0.0;
1389 double c = 0.0;
1390 double d = 0.0;
1391
1392 ShapePlane e(getPhysXExporter(), a, b, c, d);
1393 }
1394
exportInstanceGeometry(const MObject & rigidBody,const MObject & shape,const String & URISuffix="")1395 void exportInstanceGeometry(const MObject & rigidBody, const MObject & shape, const String & URISuffix = "")
1396 {
1397 // Get geometry URI
1398 MObject meshObject;
1399 PhysXShape::GetConnectedInMesh(shape, meshObject);
1400
1401 if (meshObject.isNull() || !ExportOptions::exportPolygonMeshes())
1402 {
1403 // If connected mesh doesn't exist anymore then we use the PhysX shape internal geometry
1404 // This should rarely happen but this is possible...
1405 // Also use shape internal geometry if we don't export polygon meshes.
1406 meshObject = shape;
1407 }
1408
1409 URI geometryURI;
1410 getPhysXExporter().getMeshURI(meshObject, geometryURI);
1411 if (URISuffix.length() > 0) {
1412 geometryURI.setFragment(geometryURI.getFragment() + URISuffix);
1413 }
1414 InstanceGeometry e(getPhysXExporter(), geometryURI);
1415 }
1416
exportRotateTranslate(const MObject & rigidBody,const PhysXXML::PxRigidBody & pxRigidBody,const MObject & shape,const PhysXXML::PxShape & pxShape)1417 void exportRotateTranslate(
1418 const MObject& rigidBody,
1419 const PhysXXML::PxRigidBody & pxRigidBody,
1420 const MObject & shape,
1421 const PhysXXML::PxShape & pxShape)
1422 {
1423 // Get shape local pose.
1424 MMatrix localPose = PxTransformToMMatrix(pxShape.localPose.translation, pxShape.localPose.rotation);
1425
1426 // Rigid body world pose
1427 MMatrix globalPose = PxTransformToMMatrix(pxRigidBody.globalPose.translation, pxRigidBody.globalPose.rotation);
1428
1429 // Target world pose
1430 MMatrix targetGlobalPose = PhysXExporter::GetRigidBodyTargetTM(rigidBody);
1431
1432 MMatrix DAEShapeLocalPose = localPose * globalPose * targetGlobalPose.inverse();
1433
1434 int dummy = 0;
1435 MString shapeType;
1436 DagHelper::getPlugValue(shape, ATTR_SHAPE_TYPE, dummy, shapeType);
1437 if (shapeType == SHAPE_TYPE_CAPSULE) {
1438 // PhysX capsules are X axis oriented. COLLADA capsules are Y axis oriented.
1439 MTransformationMatrix rotation;
1440 rotation.rotateBy(MEulerRotation(0.0, 0.0, -M_PI / 2.0, MEulerRotation::kXYZ), MSpace::kTransform);
1441 MMatrix rotationMatrix = rotation.asMatrix();
1442 DAEShapeLocalPose = DAEShapeLocalPose * rotationMatrix;
1443 }
1444
1445 MTransformationMatrix transform(DAEShapeLocalPose);
1446
1447 MVector translation = transform.getTranslation(MSpace::kTransform);
1448 MVector rotatePivotTranslation = transform.rotatePivotTranslation(MSpace::kTransform);
1449 MPoint rotatePivot = transform.rotatePivot(MSpace::kTransform);
1450 MEulerRotation rotation = transform.eulerRotation();
1451 rotation.order = static_cast<MEulerRotation::RotationOrder>(static_cast<int>(transform.rotationOrder()) - MTransformationMatrix::kXYZ + MEulerRotation::kXYZ);
1452
1453 getPhysXExporter().exportTranslation(translation, ATTR_TRANSLATE);
1454 getPhysXExporter().exportTranslation(rotatePivotTranslation, ATTR_ROTATE_PIVOT_TRANSLATION);
1455 getPhysXExporter().exportTranslation(rotatePivot, ATTR_ROTATE_PIVOT);
1456 getPhysXExporter().exportRotation(rotation, ATTR_ROTATE);
1457 getPhysXExporter().exportTranslation(rotatePivot * -1, ATTR_ROTATE_PIVOT_INVERSE);
1458 }
1459
exportExtra(const MObject & shape,const PhysXXML::PxShape & pxShape)1460 void exportExtra(const MObject & shape, const PhysXXML::PxShape & pxShape)
1461 {
1462 if (!ShapeExtra::HasDefaultValues(shape, pxShape))
1463 {
1464 ShapeExtra e(getPhysXExporter(), shape, pxShape);
1465 }
1466 }
1467 };
1468
1469 class Enabled : public Element
1470 {
1471 public:
Enabled(PhysXExporter & exporter,bool enabled)1472 Enabled(PhysXExporter& exporter, bool enabled)
1473 : Element(exporter, CSWC::CSW_ELEMENT_ENABLED)
1474 {
1475 getStreamWriter().appendValues(enabled);
1476 }
1477 };
1478
1479 class Interpenetrate : public Element
1480 {
1481 public:
Interpenetrate(PhysXExporter & exporter,bool interpenetrate)1482 Interpenetrate(PhysXExporter& exporter, bool interpenetrate)
1483 : Element(exporter, CSWC::CSW_ELEMENT_INTERPENETRATE)
1484 {
1485 getStreamWriter().appendValues(interpenetrate);
1486 }
1487
DefaultValue()1488 static bool DefaultValue()
1489 {
1490 return false;
1491 }
1492 };
1493
1494 class Min : public Element
1495 {
1496 public:
Min(PhysXExporter & exporter,const MVector & min)1497 Min(PhysXExporter& exporter, const MVector & min)
1498 : Element(exporter, CSWC::CSW_ELEMENT_MIN)
1499 {
1500 for (uint i = 0; i < 3; ++i)
1501 {
1502 if (isInf(min(i))) {
1503 getStreamWriter().appendValues("-INF");
1504 }
1505 else {
1506 getStreamWriter().appendValues(min(i));
1507 }
1508 }
1509 }
1510
DefaultValue()1511 static const MVector & DefaultValue()
1512 {
1513 return MVector::zero;
1514 }
1515 };
1516
1517 class Max : public Element
1518 {
1519 public:
Max(PhysXExporter & exporter,const MVector & max)1520 Max(PhysXExporter& exporter, const MVector & max)
1521 : Element(exporter, CSWC::CSW_ELEMENT_MAX)
1522 {
1523 for (uint i = 0; i < 3; ++i)
1524 {
1525 if (isInf(max(i))) {
1526 getStreamWriter().appendValues("INF");
1527 }
1528 else {
1529 getStreamWriter().appendValues(max(i));
1530 }
1531 }
1532 }
1533
DefaultValue()1534 static const MVector & DefaultValue()
1535 {
1536 return MVector::zero;
1537 }
1538 };
1539
1540 class SwingConeAndTwist : public Element
1541 {
1542 public:
SwingConeAndTwist(PhysXExporter & exporter,const MVector & min,const MVector & max)1543 SwingConeAndTwist(PhysXExporter& exporter,
1544 const MVector & min,
1545 const MVector & max)
1546 : Element(exporter, CSWC::CSW_ELEMENT_SWING_CONE_AND_TWIST)
1547 {
1548 exportMin(min);
1549 exportMax(max);
1550 }
1551
AreDefaultValues(const MVector & min,const MVector & max)1552 static bool AreDefaultValues(const MVector & min, const MVector & max)
1553 {
1554 return min == Min::DefaultValue() &&
1555 max == Max::DefaultValue();
1556 }
1557
1558 private:
exportMin(const MVector & min)1559 void exportMin(const MVector & min)
1560 {
1561 if (min != Min::DefaultValue())
1562 {
1563 Min e(getPhysXExporter(), min);
1564 }
1565 }
1566
exportMax(const MVector & max)1567 void exportMax(const MVector & max)
1568 {
1569 if (max != Max::DefaultValue())
1570 {
1571 Max e(getPhysXExporter(), max);
1572 }
1573 }
1574 };
1575
1576 class LimitsLinear : public Element
1577 {
1578 public:
LimitsLinear(PhysXExporter & exporter,const MVector & min,const MVector & max)1579 LimitsLinear(PhysXExporter& exporter,
1580 const MVector & min,
1581 const MVector & max)
1582 : Element(exporter, CSWC::CSW_ELEMENT_LINEAR)
1583 {
1584 exportMin(min);
1585 exportMax(max);
1586 }
1587
AreDefaultValues(const MVector & min,const MVector & max)1588 static bool AreDefaultValues(const MVector & min, const MVector & max)
1589 {
1590 return min == Min::DefaultValue() && max == Max::DefaultValue();
1591 }
1592
1593 private:
exportMin(const MVector & min)1594 void exportMin(const MVector & min)
1595 {
1596 if (min != Min::DefaultValue())
1597 {
1598 Min e(getPhysXExporter(), min);
1599 }
1600 }
1601
exportMax(const MVector & max)1602 void exportMax(const MVector & max)
1603 {
1604 if (max != Max::DefaultValue())
1605 {
1606 Max e(getPhysXExporter(), max);
1607 }
1608 }
1609 };
1610
1611 class Limits : public Element
1612 {
1613 public:
Limits(PhysXExporter & exporter,const MVector & swingConeAndTwistMin,const MVector & swingConeAndTwistMax,const MVector & linearMin,const MVector & linearMax)1614 Limits(PhysXExporter& exporter,
1615 const MVector & swingConeAndTwistMin,
1616 const MVector & swingConeAndTwistMax,
1617 const MVector & linearMin,
1618 const MVector & linearMax)
1619 : Element(exporter, CSWC::CSW_ELEMENT_LIMITS)
1620 {
1621 exportSwingConeAndTwist(swingConeAndTwistMin, swingConeAndTwistMax);
1622 exportLinear(linearMin, linearMax);
1623 }
1624
AreDefaultValues(const MVector & swingConeAndTwistMin,const MVector & swingConeAndTwistMax,const MVector & linearMin,const MVector & linearMax)1625 static bool AreDefaultValues(
1626 const MVector & swingConeAndTwistMin,
1627 const MVector & swingConeAndTwistMax,
1628 const MVector & linearMin,
1629 const MVector & linearMax)
1630 {
1631 return SwingConeAndTwist::AreDefaultValues(swingConeAndTwistMin, swingConeAndTwistMax) &&
1632 LimitsLinear::AreDefaultValues(linearMin, linearMax);
1633 }
1634
1635 private:
exportSwingConeAndTwist(const MVector & min,const MVector & max)1636 void exportSwingConeAndTwist(
1637 const MVector & min,
1638 const MVector & max)
1639 {
1640 if (!SwingConeAndTwist::AreDefaultValues(min, max))
1641 {
1642 SwingConeAndTwist e(getPhysXExporter(), min, max);
1643 }
1644 }
1645
exportLinear(const MVector & min,const MVector & max)1646 void exportLinear(
1647 const MVector & min,
1648 const MVector & max)
1649 {
1650 if (!LimitsLinear::AreDefaultValues(min, max))
1651 {
1652 LimitsLinear e(getPhysXExporter(), min, max);
1653 }
1654 }
1655 };
1656
1657 class Stiffness : public Element
1658 {
1659 public:
Stiffness(PhysXExporter & exporter,double stiffness,bool elementForm,const String & sid="")1660 Stiffness(PhysXExporter& exporter, double stiffness, bool elementForm, const String & sid = "")
1661 : Element(exporter, CSWC::CSW_ELEMENT_STIFFNESS, elementForm)
1662 {
1663 if (!sid.empty()) {
1664 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_SID, sid);
1665 }
1666 getStreamWriter().appendValues(stiffness);
1667 }
1668
DefaultValue()1669 static double DefaultValue()
1670 {
1671 return 1.0;
1672 }
1673 };
1674
1675 class Damping : public Element
1676 {
1677 public:
Damping(PhysXExporter & exporter,double damping,bool elementForm,const String & sid="")1678 Damping(PhysXExporter& exporter, double damping, bool elementForm, const String & sid = "")
1679 : Element(exporter, CSWC::CSW_ELEMENT_DAMPING, elementForm)
1680 {
1681 if (!sid.empty()) {
1682 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_SID, sid);
1683 }
1684 getStreamWriter().appendValues(damping);
1685 }
1686
DefaultValue()1687 static double DefaultValue()
1688 {
1689 return 0.0;
1690 }
1691 };
1692
1693 class TargetValue : public Element
1694 {
1695 public:
TargetValue(PhysXExporter & exporter,double targetValue,const String & sid="")1696 TargetValue(PhysXExporter& exporter, double targetValue, const String & sid = "")
1697 : Element(exporter, CSWC::CSW_ELEMENT_TARGET_VALUE)
1698 {
1699 if (!sid.empty()) {
1700 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_SID, sid);
1701 }
1702 getStreamWriter().appendValues(targetValue);
1703 }
1704
DefaultValue()1705 static double DefaultValue()
1706 {
1707 return 0.0;
1708 }
1709 };
1710
1711 class SpringLinear : public Element
1712 {
1713 public:
SpringLinear(PhysXExporter & exporter,double stiffness,double damping,double targetValue)1714 SpringLinear(PhysXExporter& exporter,
1715 double stiffness,
1716 double damping,
1717 double targetValue)
1718 : Element(exporter, CSWC::CSW_ELEMENT_LINEAR)
1719 {
1720 exportStiffness(stiffness);
1721 exportDamping(damping);
1722 exportTargetValue(targetValue);
1723 }
1724
AreDefaultValues(double stiffness,double damping,double targetValue)1725 static bool AreDefaultValues(double stiffness, double damping, double targetValue)
1726 {
1727 return stiffness == Stiffness::DefaultValue() &&
1728 damping == Damping::DefaultValue() &&
1729 targetValue == TargetValue::DefaultValue();
1730 }
1731
1732 private:
exportStiffness(double stiffness)1733 void exportStiffness(double stiffness)
1734 {
1735 if (stiffness != Stiffness::DefaultValue())
1736 {
1737 Stiffness e(getPhysXExporter(), stiffness, withoutPrefix);
1738 }
1739 }
1740
exportDamping(double damping)1741 void exportDamping(double damping)
1742 {
1743 if (damping != Damping::DefaultValue())
1744 {
1745 Damping e(getPhysXExporter(), damping, withoutPrefix);
1746 }
1747 }
1748
exportTargetValue(double targetValue)1749 void exportTargetValue(double targetValue)
1750 {
1751 if (targetValue != TargetValue::DefaultValue())
1752 {
1753 TargetValue e(getPhysXExporter(), targetValue);
1754 }
1755 }
1756 };
1757
1758 class Angular : public Element
1759 {
1760 public:
Angular(PhysXExporter & exporter,double stiffness,double damping,double targetValue)1761 Angular(PhysXExporter& exporter,
1762 double stiffness,
1763 double damping,
1764 double targetValue)
1765 : Element(exporter, CSWC::CSW_ELEMENT_ANGULAR)
1766 {
1767 exportStiffness(stiffness);
1768 exportDamping(damping);
1769 exportTargetValue(targetValue);
1770 }
1771
AreDefaultValues(double stiffness,double damping,double targetValue)1772 static bool AreDefaultValues(double stiffness, double damping, double targetValue)
1773 {
1774 return stiffness == Stiffness::DefaultValue() &&
1775 damping == Damping::DefaultValue() &&
1776 targetValue == TargetValue::DefaultValue();
1777 }
1778
1779 private:
exportStiffness(double stiffness)1780 void exportStiffness(double stiffness)
1781 {
1782 if (stiffness != Stiffness::DefaultValue())
1783 {
1784 Stiffness e(getPhysXExporter(), stiffness, withoutPrefix);
1785 }
1786 }
1787
exportDamping(double damping)1788 void exportDamping(double damping)
1789 {
1790 if (damping != Damping::DefaultValue())
1791 {
1792 Damping e(getPhysXExporter(), damping, withoutPrefix);
1793 }
1794 }
1795
exportTargetValue(double targetValue)1796 void exportTargetValue(double targetValue)
1797 {
1798 if (targetValue != TargetValue::DefaultValue())
1799 {
1800 TargetValue e(getPhysXExporter(), targetValue);
1801 }
1802 }
1803 };
1804
1805 class Spring : public Element
1806 {
1807 public:
Spring(PhysXExporter & exporter,double angularStiffness,double angularDamping,double angularTargetValue,double linearStiffness,double linearDamping,double linearTargetValue)1808 Spring(PhysXExporter& exporter,
1809 double angularStiffness,
1810 double angularDamping,
1811 double angularTargetValue,
1812 double linearStiffness,
1813 double linearDamping,
1814 double linearTargetValue)
1815 : Element(exporter, CSWC::CSW_ELEMENT_SPRING)
1816 {
1817 exportAngular(angularStiffness, angularDamping, angularTargetValue);
1818 exportLinear(linearStiffness, linearDamping, linearTargetValue);
1819 }
1820
AreDefaultValues(double angularStiffness,double angularDamping,double angularTargetValue,double linearStiffness,double linearDamping,double linearTargetValue)1821 static bool AreDefaultValues(
1822 double angularStiffness,
1823 double angularDamping,
1824 double angularTargetValue,
1825 double linearStiffness,
1826 double linearDamping,
1827 double linearTargetValue)
1828 {
1829 return Angular::AreDefaultValues(angularStiffness, angularDamping, angularTargetValue) &&
1830 SpringLinear::AreDefaultValues(linearStiffness, linearDamping, linearTargetValue);
1831 }
1832
1833 private:
exportLinear(double stiffness,double damping,double targetValue)1834 void exportLinear(
1835 double stiffness,
1836 double damping,
1837 double targetValue)
1838 {
1839 if (!SpringLinear::AreDefaultValues(stiffness, damping, targetValue))
1840 {
1841 SpringLinear e(getPhysXExporter(), stiffness, damping, targetValue);
1842 }
1843 }
1844
exportAngular(double stiffness,double damping,double targetValue)1845 void exportAngular(
1846 double stiffness,
1847 double damping,
1848 double targetValue)
1849 {
1850 if (!Angular::AreDefaultValues(stiffness, damping, targetValue))
1851 {
1852 Angular e(getPhysXExporter(), stiffness, damping, targetValue);
1853 }
1854 }
1855 };
1856
1857 class RigidBodyTechniqueCommon : public Element
1858 {
1859 public:
RigidBodyTechniqueCommon(PhysXExporter & exporter,const MObject & rigidBody,const PhysXXML::PxRigidBody & pxRigidBody,const String & rigidBodySid)1860 RigidBodyTechniqueCommon(PhysXExporter& exporter, const MObject & rigidBody, const PhysXXML::PxRigidBody & pxRigidBody, const String & rigidBodySid)
1861 : Element(exporter, CSWC::CSW_ELEMENT_TECHNIQUE_COMMON)
1862 {
1863 exportDynamic(pxRigidBody);
1864 exportMass(rigidBody, pxRigidBody);
1865 exportMassFrame(rigidBody, pxRigidBody);
1866 exportInertia(rigidBody, pxRigidBody);
1867 exportPhysicsMaterial(pxRigidBody, rigidBodySid);
1868 exportShapes(rigidBody, pxRigidBody);
1869 }
1870
1871 private:
exportDynamic(const PhysXXML::PxRigidBody & rigidBody)1872 void exportDynamic(const PhysXXML::PxRigidBody & rigidBody)
1873 {
1874 Dynamic e(getPhysXExporter(), rigidBody.getType() == PhysXXML::PxRigidBody::Dynamic);
1875 }
1876
exportMass(const MObject & rigidBody,const PhysXXML::PxRigidBody & pxRigidBody)1877 void exportMass(const MObject & rigidBody, const PhysXXML::PxRigidBody & pxRigidBody)
1878 {
1879 int dummy = 0;
1880 MString overrideMassOrDensityStr;
1881 DagHelper::getPlugValue(rigidBody, ATTR_OVERRIDE_MASS_OR_DENSITY, dummy, overrideMassOrDensityStr);
1882 bool overrideMassOrDensity = overrideMassOrDensityStr != OVERRIDE_MASS_OR_DENSITY_DISABLED;
1883
1884 if (overrideMassOrDensity)
1885 {
1886 if (pxRigidBody.getType() == PhysXXML::PxRigidBody::Dynamic)
1887 {
1888 const PhysXXML::PxRigidDynamic & rigidDynamic = static_cast<const PhysXXML::PxRigidDynamic&>(pxRigidBody);
1889 // PhysX mass is in grams. COLLADA uses kilograms.
1890 Mass e(getPhysXExporter(), rigidDynamic.mass.mass / 1000.0);
1891 }
1892 else
1893 {
1894 double mass = getPhysXExporter().GetRigidBodyMass(rigidBody);
1895 Mass e(getPhysXExporter(), mass);
1896 }
1897 }
1898 }
1899
exportMassFrame(const MObject & rigidBody,const PhysXXML::PxRigidBody & pxRigidBody)1900 void exportMassFrame(const MObject & rigidBody, const PhysXXML::PxRigidBody & pxRigidBody)
1901 {
1902 MVector translation = MVector::zero;
1903 MQuaternion rotation = MQuaternion::identity;
1904
1905 if (pxRigidBody.getType() == PhysXXML::PxRigidBody::Dynamic)
1906 {
1907 const PhysXXML::PxRigidDynamic & dyn = static_cast<const PhysXXML::PxRigidDynamic&>(pxRigidBody);
1908
1909 MMatrix targetWorld = PhysXExporter::GetRigidBodyTargetTM(rigidBody);
1910 MMatrix cMassLocal = PxTransformToMMatrix(dyn.cMassLocalPose.translation, dyn.cMassLocalPose.rotation);
1911 MMatrix rigidBodyWorld = PxTransformToMMatrix(dyn.globalPose.translation, dyn.globalPose.rotation);
1912
1913 // Center of mass relative to target
1914 cMassLocal = cMassLocal * rigidBodyWorld * targetWorld.inverse();
1915
1916 MTransformationMatrix transform(cMassLocal);
1917
1918 translation = transform.getTranslation(MSpace::kTransform);
1919
1920 MEulerRotation euler = transform.eulerRotation();
1921 euler.order = static_cast<MEulerRotation::RotationOrder>(static_cast<int>(transform.rotationOrder()) - MTransformationMatrix::kXYZ + MEulerRotation::kXYZ);
1922 rotation = euler.asQuaternion();
1923 }
1924 else
1925 {
1926 int dummy = 0;
1927 MString centerOfMassMode;
1928 DagHelper::getPlugValue(rigidBody, ATTR_CENTER_OF_MASS_MODE, dummy, centerOfMassMode);
1929
1930 MString overrideMassOrDensityStr;
1931 DagHelper::getPlugValue(rigidBody, ATTR_OVERRIDE_MASS_OR_DENSITY, dummy, overrideMassOrDensityStr);
1932 bool overrideMassOrDensity = overrideMassOrDensityStr != OVERRIDE_MASS_OR_DENSITY_DISABLED;
1933
1934 if (centerOfMassMode == CENTER_OF_MASS_MODE_CALCULATE_FROM_SHAPES)
1935 {
1936 std::vector<MObject> physicsShapes;
1937 getPhysXExporter().GetRigidBodyShapes(rigidBody, physicsShapes);
1938
1939 double totalFactor = 0.0;
1940 for (size_t i = 0; i < physicsShapes.size(); ++i)
1941 {
1942 const MObject & shape = physicsShapes[i];
1943 MDagPath shapeDagPath;
1944 MDagPath::getAPathTo(shape, shapeDagPath);
1945 MFnTransform shapeTransform(shapeDagPath.transform());
1946 double shapeFactor = overrideMassOrDensity ? getPhysXExporter().GetShapeVolume(shape) : getPhysXExporter().GetShapeMass(shape);
1947 translation += shapeTransform.getTranslation(MSpace::kObject) * shapeFactor;
1948 totalFactor += shapeFactor;
1949 }
1950 if (totalFactor > 0.0)
1951 {
1952 translation /= totalFactor;
1953 }
1954 }
1955 else //if (centerOfMassMode == CENTER_OF_MASS_MODE_MANUAL_OVERRIDE)
1956 {
1957 DagHelper::getPlugValue(rigidBody, ATTR_CENTER_OF_MASS_OVERRIDE, translation);
1958 }
1959
1960 translation.x = MDistance::internalToUI(translation.x);
1961 translation.y = MDistance::internalToUI(translation.y);
1962 translation.z = MDistance::internalToUI(translation.z);
1963 }
1964
1965 if (!MassFrame::AreDefaultValues(getPhysXExporter(), translation, rotation))
1966 {
1967 MassFrame e(getPhysXExporter(), translation, rotation, ATTR_TRANSLATE, ATTR_ROTATE);
1968 }
1969 }
1970
exportInertia(const MObject & rigidBody,const PhysXXML::PxRigidBody & pxRigidBody)1971 void exportInertia(const MObject & rigidBody, const PhysXXML::PxRigidBody & pxRigidBody)
1972 {
1973 MVector inertiaMatrixDiagonal = MVector::one;
1974
1975 if (pxRigidBody.getType() == PhysXXML::PxRigidBody::Dynamic)
1976 {
1977 const PhysXXML::PxRigidDynamic & dyn = static_cast<const PhysXXML::PxRigidDynamic&>(pxRigidBody);
1978 // g to kg
1979 inertiaMatrixDiagonal = dyn.massSpaceInertiaTensor.massSpaceInertiaTensor / 1000.0;
1980 }
1981 else
1982 {
1983 /*
1984 Bounding box inertia matrix =
1985
1986 m(b�+c�)/12 0 0
1987 0 m(a�+c�)/12 0
1988 0 0 m(a�+b�)/12
1989
1990 m -> mass
1991 a, b, c -> edge lengths
1992 */
1993
1994 MVector bb = MVector::zero;
1995 DagHelper::getPlugValue(rigidBody, ATTR_BOUNDING_BOX_SIZE, bb);
1996
1997 // Convert to DAE unit
1998 bb.x = MDistance::internalToUI(bb.x);
1999 bb.y = MDistance::internalToUI(bb.y);
2000 bb.z = MDistance::internalToUI(bb.z);
2001
2002 double mass = getPhysXExporter().GetRigidBodyMass(rigidBody);
2003
2004 inertiaMatrixDiagonal.x = mass * (bb.y * bb.y + bb.z * bb.z) / 12.0;
2005 inertiaMatrixDiagonal.y = mass * (bb.x * bb.x + bb.z * bb.z) / 12.0;
2006 inertiaMatrixDiagonal.z = mass * (bb.x * bb.x + bb.y * bb.y) / 12.0;
2007 }
2008
2009 Inertia e(getPhysXExporter(), inertiaMatrixDiagonal);
2010 }
2011
exportPhysicsMaterial(const PhysXXML::PxRigidBody & rigidBody,const String & rigidBodySid)2012 void exportPhysicsMaterial(const PhysXXML::PxRigidBody & rigidBody, const String & rigidBodySid)
2013 {
2014 if (const PhysXXML::PxMaterial* material = getPhysXExporter().findPxMaterial(rigidBody))
2015 {
2016 String id = rigidBodySid + "_material";
2017 PhysicsMaterial e(getPhysXExporter(), *material, id);
2018 }
2019 }
2020
exportShapes(const MObject & rigidBody,const PhysXXML::PxRigidBody & pxRigidBody)2021 void exportShapes(const MObject & rigidBody, const PhysXXML::PxRigidBody & pxRigidBody)
2022 {
2023 for (size_t i = 0; i < pxRigidBody.shapes.shapes.size(); ++i)
2024 {
2025 MObject shape = getPhysXExporter().findMObject(pxRigidBody.shapes.shapes[i]);
2026 Shape e(getPhysXExporter(), rigidBody, pxRigidBody, shape, pxRigidBody.shapes.shapes[i]);
2027 }
2028 }
2029 };
2030
2031 class RigidConstraintTechniqueCommon : public Element
2032 {
2033 public:
RigidConstraintTechniqueCommon(PhysXExporter & exporter,const MObject & rigidConstraint,const PhysXXML::PxD6Joint & joint)2034 RigidConstraintTechniqueCommon(PhysXExporter& exporter, const MObject & rigidConstraint, const PhysXXML::PxD6Joint & joint)
2035 : Element(exporter, CSWC::CSW_ELEMENT_TECHNIQUE_COMMON)
2036 {
2037 exportEnabled(rigidConstraint);
2038 exportInterpenetrate(joint);
2039 exportLimits(joint);
2040 exportSpring(joint);
2041 }
2042
2043 private:
exportEnabled(const MObject & rigidConstraint)2044 void exportEnabled(const MObject & rigidConstraint)
2045 {
2046 bool isEnabled = true;
2047 DagHelper::getPlugValue(rigidConstraint, ATTR_CONSTRAIN, isEnabled);
2048 if (!isEnabled)
2049 {
2050 Enabled e(getPhysXExporter(), isEnabled);
2051 }
2052 }
2053
exportInterpenetrate(const PhysXXML::PxD6Joint & joint)2054 void exportInterpenetrate(const PhysXXML::PxD6Joint & joint)
2055 {
2056 bool interpenetrate = !joint.constraintFlags.flags.isSet(PhysXXML::ConstraintFlags::CollisionEnabled);
2057 if (interpenetrate == Interpenetrate::DefaultValue())
2058 {
2059 Interpenetrate e(getPhysXExporter(), interpenetrate);
2060 }
2061 }
2062
exportLimits(const PhysXXML::PxD6Joint & joint)2063 void exportLimits(const PhysXXML::PxD6Joint & joint)
2064 {
2065 MVector swingConeAndTwistMin = MVector::zero;
2066 MVector swingConeAndTwistMax = MVector::zero;
2067 MVector linearMin = MVector::zero;
2068 MVector linearMax = MVector::zero;
2069
2070 if (joint.motion.eSwing1.eSwing1 == PhysXXML::MotionFlags::Locked)
2071 {
2072 swingConeAndTwistMin.x = 0.0;
2073 swingConeAndTwistMax.x = 0.0;
2074 }
2075 else if (joint.motion.eSwing1.eSwing1 == PhysXXML::MotionFlags::Free)
2076 {
2077 swingConeAndTwistMin.x = -infinite();
2078 swingConeAndTwistMax.x = infinite();
2079 }
2080 else
2081 {
2082 swingConeAndTwistMin.x = COLLADABU::Math::Utils::radToDeg(-joint.swingLimit.yAngle.yAngle);
2083 swingConeAndTwistMax.x = COLLADABU::Math::Utils::radToDeg(joint.swingLimit.yAngle.yAngle);
2084 }
2085
2086 if (joint.motion.eSwing2.eSwing2 == PhysXXML::MotionFlags::Locked)
2087 {
2088 swingConeAndTwistMin.y = 0.0;
2089 swingConeAndTwistMax.y = 0.0;
2090 }
2091 else if (joint.motion.eSwing2.eSwing2 == PhysXXML::MotionFlags::Free)
2092 {
2093 swingConeAndTwistMin.y = -infinite();
2094 swingConeAndTwistMax.y = infinite();
2095 }
2096 else
2097 {
2098 swingConeAndTwistMin.y = COLLADABU::Math::Utils::radToDeg(-joint.swingLimit.zAngle.zAngle);
2099 swingConeAndTwistMax.y = COLLADABU::Math::Utils::radToDeg(joint.swingLimit.zAngle.zAngle);
2100 }
2101
2102 if (joint.motion.eTwist.eTwist == PhysXXML::MotionFlags::Locked)
2103 {
2104 swingConeAndTwistMin.z = 0.0;
2105 swingConeAndTwistMax.z = 0.0;
2106 }
2107 else if (joint.motion.eTwist.eTwist == PhysXXML::MotionFlags::Free)
2108 {
2109 swingConeAndTwistMin.z = -infinite();
2110 swingConeAndTwistMax.z = infinite();
2111 }
2112 else
2113 {
2114 swingConeAndTwistMin.z = COLLADABU::Math::Utils::radToDeg(joint.twistLimit.lower.lower);
2115 swingConeAndTwistMax.z = COLLADABU::Math::Utils::radToDeg(joint.twistLimit.upper.upper);
2116 }
2117
2118 if (joint.motion.eX.eX == PhysXXML::MotionFlags::Locked)
2119 {
2120 linearMin.x = 0.0;
2121 linearMax.x = 0.0;
2122 }
2123 else if (joint.motion.eX.eX == PhysXXML::MotionFlags::Free)
2124 {
2125 linearMin.x = -infinite();
2126 linearMax.x = infinite();
2127 }
2128 else
2129 {
2130 linearMin.x = -joint.linearLimit.value.value;
2131 linearMax.x = joint.linearLimit.value.value;
2132 }
2133
2134 if (joint.motion.eY.eY == PhysXXML::MotionFlags::Locked)
2135 {
2136 linearMin.y = 0.0;
2137 linearMax.y = 0.0;
2138 }
2139 else if (joint.motion.eY.eY == PhysXXML::MotionFlags::Free)
2140 {
2141 linearMin.y = -infinite();
2142 linearMax.y = infinite();
2143 }
2144 else
2145 {
2146 linearMin.y = -joint.linearLimit.value.value;
2147 linearMax.y = joint.linearLimit.value.value;
2148 }
2149
2150 if (joint.motion.eZ.eZ == PhysXXML::MotionFlags::Locked)
2151 {
2152 linearMin.z = 0.0;
2153 linearMax.z = 0.0;
2154 }
2155 else if (joint.motion.eZ.eZ == PhysXXML::MotionFlags::Free)
2156 {
2157 linearMin.z = -infinite();
2158 linearMax.z = infinite();
2159 }
2160 else
2161 {
2162 linearMin.z = -joint.linearLimit.value.value;
2163 linearMax.z = joint.linearLimit.value.value;
2164 }
2165
2166 if (!Limits::AreDefaultValues(swingConeAndTwistMin, swingConeAndTwistMax, linearMin, linearMax))
2167 {
2168 Limits e(getPhysXExporter(),
2169 swingConeAndTwistMin,
2170 swingConeAndTwistMax,
2171 linearMin,
2172 linearMax);
2173 }
2174 }
2175
exportSpring(const PhysXXML::PxD6Joint & joint)2176 void exportSpring(const PhysXXML::PxD6Joint & joint)
2177 {
2178 double linearStiffness = joint.linearLimit.stiffness.stiffness;
2179 double linearDamping = joint.linearLimit.damping.damping;
2180 double linearTargetValue = 0.0;
2181 double angularStiffness = joint.swingLimit.stiffness.stiffness;
2182 double angularDamping = joint.swingLimit.damping.damping;
2183 double angularTargetValue = 0.0;
2184
2185 if (!Spring::AreDefaultValues(
2186 linearStiffness,
2187 linearDamping,
2188 linearTargetValue,
2189 angularStiffness,
2190 angularDamping,
2191 angularTargetValue))
2192 {
2193 Spring e(getPhysXExporter(),
2194 angularStiffness,
2195 angularDamping,
2196 angularTargetValue,
2197 linearStiffness,
2198 linearDamping,
2199 linearTargetValue);
2200 }
2201 }
2202 };
2203
2204 class ActorFlags : public Element
2205 {
2206 public:
ActorFlags(PhysXExporter & exporter,const Flags<PhysXXML::ActorFlags::FlagEnum> & flags)2207 ActorFlags(PhysXExporter & exporter, const Flags<PhysXXML::ActorFlags::FlagEnum> & flags)
2208 : Element(exporter, CSWC::CSW_ELEMENT_ACTOR_FLAGS, withPrefix)
2209 {
2210 getStreamWriter().appendValues(PhysXExporter::ActorFlagsToCOLLADA(flags));
2211 }
2212
DefaultValue()2213 static Flags<PhysXXML::ActorFlags::FlagEnum> DefaultValue()
2214 {
2215 return Flags<PhysXXML::ActorFlags::FlagEnum>(PhysXXML::ActorFlags::Visualization);
2216 }
2217 };
2218
2219 class DominanceGroup : public Element
2220 {
2221 public:
DominanceGroup(PhysXExporter & exporter,int dominanceGroup)2222 DominanceGroup(PhysXExporter & exporter, int dominanceGroup)
2223 : Element(exporter, CSWC::CSW_ELEMENT_DOMINANCE_GROUP, withPrefix)
2224 {
2225 getStreamWriter().appendValues(dominanceGroup);
2226 }
2227
DefaultValue()2228 static int DefaultValue()
2229 {
2230 return 0;
2231 }
2232 };
2233
2234 class OwnerClient : public Element
2235 {
2236 public:
OwnerClient(PhysXExporter & exporter,int ownerClient)2237 OwnerClient(PhysXExporter & exporter, int ownerClient)
2238 : Element(exporter, CSWC::CSW_ELEMENT_OWNER_CLIENT, withPrefix)
2239 {
2240 getStreamWriter().appendValues(ownerClient);
2241 }
2242
DefaultValue()2243 static int DefaultValue()
2244 {
2245 return 0;
2246 }
2247 };
2248
2249 class RigidBodyFlags : public Element
2250 {
2251 public:
RigidBodyFlags(PhysXExporter & exporter,const Flags<PhysXXML::RigidBodyFlags::FlagEnum> & flags)2252 RigidBodyFlags(PhysXExporter & exporter, const Flags<PhysXXML::RigidBodyFlags::FlagEnum> & flags)
2253 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY_FLAGS, withPrefix)
2254 {
2255 getStreamWriter().appendValues(PhysXExporter::RigidBodyFlagsToCOLLADA(flags));
2256 }
2257
DefaultValue()2258 static Flags<PhysXXML::RigidBodyFlags::FlagEnum> DefaultValue()
2259 {
2260 return Flags<PhysXXML::RigidBodyFlags::FlagEnum>();
2261 }
2262 };
2263
2264 class MinCCDAdvanceCoefficient : public Element
2265 {
2266 public:
MinCCDAdvanceCoefficient(PhysXExporter & exporter,double minCCDAdvanceCoefficient)2267 MinCCDAdvanceCoefficient(PhysXExporter & exporter, double minCCDAdvanceCoefficient)
2268 : Element(exporter, CSWC::CSW_ELEMENT_MIN_CCD_ADVANCE_COEFFICIENT, withPrefix)
2269 {
2270 getStreamWriter().appendValues(minCCDAdvanceCoefficient);
2271 }
2272
DefaultValue()2273 static double DefaultValue()
2274 {
2275 return 0.15;
2276 }
2277 };
2278
2279 class MaxDepenetrationVelocity : public Element
2280 {
2281 public:
MaxDepenetrationVelocity(PhysXExporter & exporter,double maxDepenetrationVelocity)2282 MaxDepenetrationVelocity(PhysXExporter & exporter, double maxDepenetrationVelocity)
2283 : Element(exporter, CSWC::CSW_ELEMENT_MAX_DEPENETRATION_VELOCITY, withPrefix)
2284 {
2285 getStreamWriter().appendValues(maxDepenetrationVelocity);
2286 }
2287
DefaultValue()2288 static double DefaultValue()
2289 {
2290 return infinite();
2291 }
2292 };
2293
2294 class LinearDamping : public Element
2295 {
2296 public:
LinearDamping(PhysXExporter & exporter,double linearDamping)2297 LinearDamping(PhysXExporter & exporter, double linearDamping)
2298 : Element(exporter, CSWC::CSW_ELEMENT_LINEAR_DAMPING, withPrefix)
2299 {
2300 getStreamWriter().appendValues(linearDamping);
2301 }
2302
DefaultValue()2303 static double DefaultValue()
2304 {
2305 return 0.0;
2306 }
2307 };
2308
2309 class AngularDamping : public Element
2310 {
2311 public:
AngularDamping(PhysXExporter & exporter,double angularDamping)2312 AngularDamping(PhysXExporter & exporter, double angularDamping)
2313 : Element(exporter, CSWC::CSW_ELEMENT_ANGULAR_DAMPING, withPrefix)
2314 {
2315 getStreamWriter().appendValues(angularDamping);
2316 }
2317
DefaultValue()2318 static double DefaultValue()
2319 {
2320 return 0.0;
2321 }
2322 };
2323
2324 class MaxAngularVelocity : public Element
2325 {
2326 public:
MaxAngularVelocity(PhysXExporter & exporter,double maxAngularDamping)2327 MaxAngularVelocity(PhysXExporter & exporter, double maxAngularDamping)
2328 : Element(exporter, CSWC::CSW_ELEMENT_MAX_ANGULAR_VELOCITY, withPrefix)
2329 {
2330 getStreamWriter().appendValues(maxAngularDamping);
2331 }
2332
DefaultValue()2333 static double DefaultValue()
2334 {
2335 return 7.0;
2336 }
2337 };
2338
2339 class SleepThreshold : public Element
2340 {
2341 public:
SleepThreshold(PhysXExporter & exporter,double sleepThreshold)2342 SleepThreshold(PhysXExporter & exporter, double sleepThreshold)
2343 : Element(exporter, CSWC::CSW_ELEMENT_SLEEP_THRESHOLD, withPrefix)
2344 {
2345 getStreamWriter().appendValues(sleepThreshold);
2346 }
2347
DefaultValue()2348 static double DefaultValue()
2349 {
2350 return 5e-5;
2351 }
2352 };
2353
2354 class StabilizationThreshold : public Element
2355 {
2356 public:
StabilizationThreshold(PhysXExporter & exporter,double stabilizationThreshold)2357 StabilizationThreshold(PhysXExporter & exporter, double stabilizationThreshold)
2358 : Element(exporter, CSWC::CSW_ELEMENT_STABILIZATION_THRESHOLD, withPrefix)
2359 {
2360 getStreamWriter().appendValues(stabilizationThreshold);
2361 }
2362
DefaultValue()2363 static double DefaultValue()
2364 {
2365 return 1e-5;
2366 }
2367 };
2368
2369 class WakeCounter : public Element
2370 {
2371 public:
WakeCounter(PhysXExporter & exporter,double wakeCounter)2372 WakeCounter(PhysXExporter & exporter, double wakeCounter)
2373 : Element(exporter, CSWC::CSW_ELEMENT_WAKE_COUNTER, withPrefix)
2374 {
2375 getStreamWriter().appendValues(wakeCounter);
2376 }
2377
DefaultValue()2378 static double DefaultValue()
2379 {
2380 return 0.4;
2381 }
2382 };
2383
2384 class MinPositionIters : public Element
2385 {
2386 public:
MinPositionIters(PhysXExporter & exporter,int minPositionIters)2387 MinPositionIters(PhysXExporter & exporter, int minPositionIters)
2388 : Element(exporter, CSWC::CSW_ELEMENT_MIN_POSITION_ITERS, withPrefix)
2389 {
2390 getStreamWriter().appendValues(minPositionIters);
2391 }
2392
DefaultValue()2393 static int DefaultValue()
2394 {
2395 return 4;
2396 }
2397 };
2398
2399 class MinVelocityIters : public Element
2400 {
2401 public:
MinVelocityIters(PhysXExporter & exporter,int minVelocityIters)2402 MinVelocityIters(PhysXExporter & exporter, int minVelocityIters)
2403 : Element(exporter, CSWC::CSW_ELEMENT_MIN_VELOCITY_ITERS, withPrefix)
2404 {
2405 getStreamWriter().appendValues(minVelocityIters);
2406 }
2407
DefaultValue()2408 static int DefaultValue()
2409 {
2410 return 1;
2411 }
2412 };
2413
2414 class ContactReportThreshold : public Element
2415 {
2416 public:
ContactReportThreshold(PhysXExporter & exporter,double contactReportThreshold)2417 ContactReportThreshold(PhysXExporter & exporter, double contactReportThreshold)
2418 : Element(exporter, CSWC::CSW_ELEMENT_CONTACT_REPORT_THRESHOLD, withPrefix)
2419 {
2420 getStreamWriter().appendValues(contactReportThreshold);
2421 }
2422
DefaultValue()2423 static double DefaultValue()
2424 {
2425 return infinite();
2426 }
2427 };
2428
2429 class GlobalPose : public Element
2430 {
2431 public:
GlobalPose(PhysXExporter & exporter,const MQuaternion & rotation,const MVector & translation)2432 GlobalPose(PhysXExporter& exporter, const MQuaternion & rotation, const MVector & translation)
2433 : Element(exporter, CSWC::CSW_ELEMENT_GLOBAL_POSE, withPrefix)
2434 {
2435 double pose [] = { rotation.x, rotation.y, rotation.z, rotation.w, translation.x, translation.y, translation.z };
2436 getStreamWriter().appendValues(pose, sizeof(pose) / sizeof(pose[0]));
2437 }
2438 };
2439
2440 class PxRigidBody : public Element
2441 {
2442 public:
PxRigidBody(PhysXExporter & exporter,const PhysXXML::PxRigidBody & rb)2443 PxRigidBody(PhysXExporter& exporter, const PhysXXML::PxRigidBody & rb)
2444 : Element(exporter, CSWC::CSW_ELEMENT_PX_RIGID_BODY, withPrefix)
2445 {
2446 exportGlobalPose(rb);
2447 exportActorFlags(rb);
2448 exportDominanceGroup(rb);
2449 exportOwnerClient(rb);
2450 if (rb.getType() == PhysXXML::PxRigidBody::Dynamic)
2451 {
2452 const PhysXXML::PxRigidDynamic & rd = static_cast<const PhysXXML::PxRigidDynamic&>(rb);
2453 exportRigidBodyFlags(rd);
2454 exportMinCCDAdvanceCoefficient(rd);
2455 exportMaxDepenetrationVelocity(rd);
2456 exportLinearDamping(rd);
2457 exportAngularDamping(rd);
2458 exportMaxAngularVelocity(rd);
2459 exportSleepThreshold(rd);
2460 exportStabilizationThreshold(rd);
2461 exportWakeCounter(rd);
2462 exportMinPositionIters(rd);
2463 exportMinVelocityIters(rd);
2464 exportContactReportThreshold(rd);
2465 }
2466 }
2467
HasDefaultValues(const PhysXXML::PxRigidBody & rb)2468 static bool HasDefaultValues(const PhysXXML::PxRigidBody & rb)
2469 {
2470 // Always export global pose
2471 return false;
2472 }
2473
2474 private:
exportGlobalPose(const PhysXXML::PxRigidBody & pxRigidBody)2475 void exportGlobalPose(const PhysXXML::PxRigidBody & pxRigidBody)
2476 {
2477 GlobalPose e(getPhysXExporter(), pxRigidBody.globalPose.rotation, pxRigidBody.globalPose.translation);
2478 }
2479
exportActorFlags(const PhysXXML::PxRigidBody & pxRigidBody)2480 void exportActorFlags(const PhysXXML::PxRigidBody & pxRigidBody)
2481 {
2482 if (pxRigidBody.actorFlags.actorFlags != ActorFlags::DefaultValue())
2483 {
2484 ActorFlags e(getPhysXExporter(), pxRigidBody.actorFlags.actorFlags);
2485 }
2486 }
2487
exportDominanceGroup(const PhysXXML::PxRigidBody & pxRigidBody)2488 void exportDominanceGroup(const PhysXXML::PxRigidBody & pxRigidBody)
2489 {
2490 if (pxRigidBody.dominanceGroup.dominanceGroup != DominanceGroup::DefaultValue())
2491 {
2492 DominanceGroup e(getPhysXExporter(), pxRigidBody.dominanceGroup.dominanceGroup);
2493 }
2494 }
2495
exportOwnerClient(const PhysXXML::PxRigidBody & pxRigidBody)2496 void exportOwnerClient(const PhysXXML::PxRigidBody & pxRigidBody)
2497 {
2498 if (pxRigidBody.ownerClient.ownerClient != OwnerClient::DefaultValue())
2499 {
2500 OwnerClient e(getPhysXExporter(), pxRigidBody.ownerClient.ownerClient);
2501 }
2502 }
2503
exportRigidBodyFlags(const PhysXXML::PxRigidDynamic & pxRigidDynamic)2504 void exportRigidBodyFlags(const PhysXXML::PxRigidDynamic & pxRigidDynamic)
2505 {
2506 if (pxRigidDynamic.rigidBodyFlags.rigidBodyFlags != RigidBodyFlags::DefaultValue())
2507 {
2508 RigidBodyFlags e(getPhysXExporter(), pxRigidDynamic.rigidBodyFlags.rigidBodyFlags);
2509 }
2510 }
2511
exportMinCCDAdvanceCoefficient(const PhysXXML::PxRigidDynamic & pxRigidDynamic)2512 void exportMinCCDAdvanceCoefficient(const PhysXXML::PxRigidDynamic & pxRigidDynamic)
2513 {
2514 if (pxRigidDynamic.minCCDAdvanceCoefficient.minCCDAdvanceCoefficient != MinCCDAdvanceCoefficient::DefaultValue())
2515 {
2516 MinCCDAdvanceCoefficient e(getPhysXExporter(), pxRigidDynamic.minCCDAdvanceCoefficient.minCCDAdvanceCoefficient);
2517 }
2518 }
2519
exportMaxDepenetrationVelocity(const PhysXXML::PxRigidDynamic & pxRigidDynamic)2520 void exportMaxDepenetrationVelocity(const PhysXXML::PxRigidDynamic & pxRigidDynamic)
2521 {
2522 if (pxRigidDynamic.maxDepenetrationVelocity.maxDepenetrationVelocity != MaxDepenetrationVelocity::DefaultValue())
2523 {
2524 MaxDepenetrationVelocity e(getPhysXExporter(), pxRigidDynamic.maxDepenetrationVelocity.maxDepenetrationVelocity);
2525 }
2526 }
2527
exportLinearDamping(const PhysXXML::PxRigidDynamic & pxRigidDynamic)2528 void exportLinearDamping(const PhysXXML::PxRigidDynamic & pxRigidDynamic)
2529 {
2530 if (pxRigidDynamic.linearDamping.linearDamping != LinearDamping::DefaultValue())
2531 {
2532 LinearDamping e(getPhysXExporter(), pxRigidDynamic.linearDamping.linearDamping);
2533 }
2534 }
2535
exportAngularDamping(const PhysXXML::PxRigidDynamic & pxRigidDynamic)2536 void exportAngularDamping(const PhysXXML::PxRigidDynamic & pxRigidDynamic)
2537 {
2538 if (pxRigidDynamic.angularDamping.angularDamping != AngularDamping::DefaultValue())
2539 {
2540 AngularDamping e(getPhysXExporter(), pxRigidDynamic.angularDamping.angularDamping);
2541 }
2542 }
2543
exportMaxAngularVelocity(const PhysXXML::PxRigidDynamic & pxRigidDynamic)2544 void exportMaxAngularVelocity(const PhysXXML::PxRigidDynamic & pxRigidDynamic)
2545 {
2546 if (pxRigidDynamic.maxAngularVelocity.maxAngularVelocity != MaxAngularVelocity::DefaultValue())
2547 {
2548 MaxAngularVelocity e(getPhysXExporter(), pxRigidDynamic.maxAngularVelocity.maxAngularVelocity);
2549 }
2550 }
2551
exportSleepThreshold(const PhysXXML::PxRigidDynamic & pxRigidDynamic)2552 void exportSleepThreshold(const PhysXXML::PxRigidDynamic & pxRigidDynamic)
2553 {
2554 if (pxRigidDynamic.sleepThreshold.sleepThreshold != SleepThreshold::DefaultValue())
2555 {
2556 SleepThreshold e(getPhysXExporter(), pxRigidDynamic.sleepThreshold.sleepThreshold);
2557 }
2558 }
2559
exportStabilizationThreshold(const PhysXXML::PxRigidDynamic & pxRigidDynamic)2560 void exportStabilizationThreshold(const PhysXXML::PxRigidDynamic & pxRigidDynamic)
2561 {
2562 if (pxRigidDynamic.stabilizationThreshold.stabilizationThreshold != StabilizationThreshold::DefaultValue())
2563 {
2564 StabilizationThreshold e(getPhysXExporter(), pxRigidDynamic.stabilizationThreshold.stabilizationThreshold);
2565 }
2566 }
2567
exportWakeCounter(const PhysXXML::PxRigidDynamic & pxRigidDynamic)2568 void exportWakeCounter(const PhysXXML::PxRigidDynamic & pxRigidDynamic)
2569 {
2570 if (pxRigidDynamic.wakeCounter.wakeCounter != WakeCounter::DefaultValue())
2571 {
2572 WakeCounter e(getPhysXExporter(), pxRigidDynamic.wakeCounter.wakeCounter);
2573 }
2574 }
2575
exportMinPositionIters(const PhysXXML::PxRigidDynamic & pxRigidDynamic)2576 void exportMinPositionIters(const PhysXXML::PxRigidDynamic & pxRigidDynamic)
2577 {
2578 if (pxRigidDynamic.solverIterationCounts.minPositionIters.minPositionIters != MinPositionIters::DefaultValue())
2579 {
2580 MinPositionIters e(getPhysXExporter(), pxRigidDynamic.solverIterationCounts.minPositionIters.minPositionIters);
2581 }
2582 }
2583
exportMinVelocityIters(const PhysXXML::PxRigidDynamic & pxRigidDynamic)2584 void exportMinVelocityIters(const PhysXXML::PxRigidDynamic & pxRigidDynamic)
2585 {
2586 if (pxRigidDynamic.solverIterationCounts.minVelocityIters.minVelocityIters != MinVelocityIters::DefaultValue())
2587 {
2588 MinVelocityIters e(getPhysXExporter(), pxRigidDynamic.solverIterationCounts.minVelocityIters.minVelocityIters);
2589 }
2590 }
2591
exportContactReportThreshold(const PhysXXML::PxRigidDynamic & pxRigidDynamic)2592 void exportContactReportThreshold(const PhysXXML::PxRigidDynamic & pxRigidDynamic)
2593 {
2594 if (pxRigidDynamic.contactReportThreshold.contactReportThreshold != ContactReportThreshold::DefaultValue())
2595 {
2596 ContactReportThreshold e(getPhysXExporter(), pxRigidDynamic.contactReportThreshold.contactReportThreshold);
2597 }
2598 }
2599 };
2600
2601 class ForceToSleep : public Element
2602 {
2603 public:
ForceToSleep(PhysXExporter & exporter,const MObject & rigidBody,bool forceToSleep)2604 ForceToSleep(PhysXExporter& exporter, const MObject & rigidBody, bool forceToSleep)
2605 : Element(exporter, CSWC::CSW_ELEMENT_FORCE_TO_SLEEP)
2606 {
2607 getStreamWriter().appendValues(forceToSleep);
2608 }
2609
DefaultValue()2610 static bool DefaultValue()
2611 {
2612 return false;
2613 }
2614
GetForceToSleep(const MObject & rb)2615 static bool GetForceToSleep(const MObject & rb)
2616 {
2617 bool forceToSleep = false;
2618 DagHelper::getPlugValue(rb, ATTR_FORCE_TO_SLEEP, forceToSleep);
2619 return forceToSleep;
2620 }
2621 };
2622
2623 class RigidBodyTechnique : public Element
2624 {
2625 public:
RigidBodyTechnique(PhysXExporter & exporter,const MObject & rigidBody,const PhysXXML::PxRigidBody & pxRigidBody,const String & profile)2626 RigidBodyTechnique(PhysXExporter& exporter, const MObject & rigidBody, const PhysXXML::PxRigidBody & pxRigidBody, const String & profile)
2627 : Element(exporter, CSWC::CSW_ELEMENT_TECHNIQUE)
2628 {
2629 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_PROFILE, profile);
2630 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_XMLNS + ":" + CSWC::CSW_PREFIX_PX, PhysXExporter::GetXMLNS());
2631 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_XSI_SCHEMALOCATION, PhysXExporter::GetXSISchemaLocation());
2632 if (profile == PROFILE_MAYA) {
2633 exportForceToSleep(rigidBody);
2634 exporter.exportExtraAttributes(rigidBody);
2635 }
2636 else if (profile == PhysXExporter::GetPhysXProfile()) {
2637 exportPxRigidBody(pxRigidBody);
2638 }
2639 }
2640
HasDefaultValues(const MObject & rigidBody,const PhysXXML::PxRigidBody & rb,const String & profile)2641 static bool HasDefaultValues(const MObject & rigidBody, const PhysXXML::PxRigidBody & rb, const String & profile)
2642 {
2643 if (profile == PhysXExporter::GetPhysXProfile())
2644 {
2645 return PxRigidBody::HasDefaultValues(rb);
2646 }
2647 else if (profile == PROFILE_MAYA)
2648 {
2649 return ForceToSleep::GetForceToSleep(rigidBody) == ForceToSleep::DefaultValue() &&
2650 !PhysXExporter::HasExtraAttributes(rigidBody);
2651 }
2652 return true;
2653 }
2654
2655 private:
exportForceToSleep(const MObject & rigidBody)2656 void exportForceToSleep(const MObject & rigidBody)
2657 {
2658 bool forceToSleep = ForceToSleep::GetForceToSleep(rigidBody);
2659 if (forceToSleep != ForceToSleep::DefaultValue())
2660 {
2661 ForceToSleep e(getPhysXExporter(), rigidBody, forceToSleep);
2662 }
2663 }
2664
exportPxRigidBody(const PhysXXML::PxRigidBody & rb)2665 void exportPxRigidBody(const PhysXXML::PxRigidBody & rb)
2666 {
2667 if (!PxRigidBody::HasDefaultValues(rb))
2668 {
2669 PxRigidBody e(getPhysXExporter(), rb);
2670 }
2671 }
2672
2673 private:
2674 static std::set<MString, MStringComp> mAttributes;
2675 };
2676 std::set<MString, MStringComp> RigidBodyTechnique::mAttributes;
2677
2678 class RigidBodyExtra : public Element
2679 {
2680 public:
RigidBodyExtra(PhysXExporter & exporter,const MObject & rigidBody,const PhysXXML::PxRigidBody & pxRigidBody)2681 RigidBodyExtra(PhysXExporter& exporter, const MObject & rigidBody, const PhysXXML::PxRigidBody & pxRigidBody)
2682 : Element(exporter, CSWC::CSW_ELEMENT_EXTRA)
2683 {
2684 exportProfile(rigidBody, pxRigidBody, PROFILE_MAYA);
2685 exportProfile(rigidBody, pxRigidBody, PhysXExporter::GetPhysXProfile());
2686 }
2687
HasDefaultValues(const MObject & rigidBody,const PhysXXML::PxRigidBody & pxRigidBody)2688 static bool HasDefaultValues(const MObject & rigidBody, const PhysXXML::PxRigidBody & pxRigidBody)
2689 {
2690 return
2691 RigidBodyTechnique::HasDefaultValues(rigidBody, pxRigidBody, PROFILE_MAYA) &&
2692 RigidBodyTechnique::HasDefaultValues(rigidBody, pxRigidBody, PhysXExporter::GetPhysXProfile());
2693 }
2694
2695 private:
exportProfile(const MObject & rigidBody,const PhysXXML::PxRigidBody & pxRigidBody,const String & profile)2696 void exportProfile(const MObject& rigidBody, const PhysXXML::PxRigidBody & pxRigidBody, const String& profile)
2697 {
2698 if (!RigidBodyTechnique::HasDefaultValues(rigidBody, pxRigidBody, profile))
2699 {
2700 RigidBodyTechnique e(getPhysXExporter(), rigidBody, pxRigidBody, profile);
2701 }
2702 }
2703 };
2704
2705 class RigidBody : public Element
2706 {
2707 public:
RigidBody(PhysXExporter & exporter,const MObject & rigidBody,const String & sid,const String & name="")2708 RigidBody(PhysXExporter& exporter, const MObject & rigidBody, const String & sid, const String & name = "")
2709 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY)
2710 {
2711 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_SID, sid);
2712 if (name.length() > 0) {
2713 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_NAME, name);
2714 }
2715
2716 const PhysXXML::PxRigidBody* pxRigidBody = exporter.findPxRigidBody(rigidBody);
2717 if (pxRigidBody)
2718 {
2719 exportTechniqueCommon(rigidBody, *pxRigidBody, sid);
2720 exportExtra(rigidBody, *pxRigidBody);
2721 }
2722 }
2723
RigidBody(PhysXExporter & exporter,const PhysXXML::PxRigidBody & pxRigidBody,const String & sid,const String & name="")2724 RigidBody(PhysXExporter& exporter, const PhysXXML::PxRigidBody & pxRigidBody, const String & sid, const String & name = "")
2725 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_BODY)
2726 {
2727 MObject rigidBody;
2728 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_SID, sid);
2729 if (name.length() > 0) {
2730 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_NAME, name);
2731 }
2732
2733 exportTechniqueCommon(rigidBody, pxRigidBody, sid);
2734 exportExtra(rigidBody, pxRigidBody);
2735 }
2736
2737 private:
exportTechniqueCommon(const MObject & rigidBody,const PhysXXML::PxRigidBody & pxRigidBody,const String & sid)2738 void exportTechniqueCommon(const MObject & rigidBody, const PhysXXML::PxRigidBody & pxRigidBody, const String & sid)
2739 {
2740 RigidBodyTechniqueCommon e(getPhysXExporter(), rigidBody, pxRigidBody, sid);
2741 }
2742
exportExtra(const MObject & rigidBody,const PhysXXML::PxRigidBody & pxRigidBody)2743 void exportExtra(const MObject & rigidBody, const PhysXXML::PxRigidBody & pxRigidBody)
2744 {
2745 if (!RigidBodyExtra::HasDefaultValues(rigidBody, pxRigidBody))
2746 {
2747 RigidBodyExtra e(getPhysXExporter(), rigidBody, pxRigidBody);
2748 }
2749 }
2750 };
2751
2752 class IAttachment
2753 {
2754 public:
exportRotateTranslate(PhysXExporter & exporter,uint64_t actor,const MVector & localPoseActorTranslation,const MQuaternion & localPoseActorRotation)2755 void exportRotateTranslate(PhysXExporter & exporter, uint64_t actor, const MVector & localPoseActorTranslation, const MQuaternion & localPoseActorRotation)
2756 {
2757 const PhysXXML::PxRigidBody* pxRigidBody = exporter.findPxRigidBody(actor);
2758
2759 MVector translation = uiToInternal(localPoseActorTranslation);
2760 MEulerRotation rotation = localPoseActorRotation.asEulerRotation();
2761
2762 if (pxRigidBody)
2763 {
2764 MObject target = DagHelper::getNode(pxRigidBody->name.name.c_str());
2765 MObject rigidBody = exporter.getNodeRigidBody(target);
2766 if (!rigidBody.isNull())
2767 {
2768 MMatrix targetWorld = PhysXExporter::GetRigidBodyTargetTM(rigidBody);
2769 MMatrix constraintLocal = PxTransformToMMatrix(localPoseActorTranslation, localPoseActorRotation);
2770 MMatrix rigidBodyWorld = PxTransformToMMatrix(pxRigidBody->globalPose.translation, pxRigidBody->globalPose.rotation);
2771
2772 constraintLocal = constraintLocal * rigidBodyWorld * targetWorld.inverse();
2773
2774 MTransformationMatrix tm(constraintLocal);
2775 translation = tm.getTranslation(MSpace::kTransform);
2776 rotation = tm.eulerRotation();
2777 rotation.order = static_cast<MEulerRotation::RotationOrder>(static_cast<int>(tm.rotationOrder()) - MTransformationMatrix::kXYZ + MEulerRotation::kXYZ);
2778 }
2779 }
2780
2781 exporter.exportTranslation(translation, ATTR_TRANSLATE);
2782 exporter.exportRotation(rotation, ATTR_ROTATE);
2783 }
2784 };
2785
2786 class RefAttachment : public Element, public IAttachment
2787 {
2788 public:
RefAttachment(PhysXExporter & exporter,const PhysXXML::PxD6Joint & joint,const URI & attachmentURI)2789 RefAttachment(PhysXExporter& exporter, const PhysXXML::PxD6Joint & joint, const URI & attachmentURI)
2790 : Element(exporter, CSWC::CSW_ELEMENT_REF_ATTACHMENT)
2791 {
2792 getStreamWriter().appendURIAttribute(CSWC::CSW_ATTRIBUTE_RIGID_BODY, attachmentURI);
2793 exportRotateTranslate(joint);
2794 }
2795
2796 private:
exportRotateTranslate(const PhysXXML::PxD6Joint & joint)2797 void exportRotateTranslate(const PhysXXML::PxD6Joint & joint)
2798 {
2799 IAttachment::exportRotateTranslate(getPhysXExporter(), joint.actors.actor0.actor0, joint.localPose.eActor0.translation, joint.localPose.eActor0.rotation);
2800 }
2801 };
2802
2803 class Attachment : public Element, public IAttachment
2804 {
2805 public:
Attachment(PhysXExporter & exporter,const PhysXXML::PxD6Joint & joint,const URI & attachmentURI)2806 Attachment(PhysXExporter& exporter, const PhysXXML::PxD6Joint & joint, const URI & attachmentURI)
2807 : Element(exporter, CSWC::CSW_ELEMENT_ATTACHMENT)
2808 {
2809 getStreamWriter().appendURIAttribute(CSWC::CSW_ATTRIBUTE_RIGID_BODY, attachmentURI);
2810 exportRotateTranslate(joint);
2811 }
2812
2813 private:
exportRotateTranslate(const PhysXXML::PxD6Joint & joint)2814 void exportRotateTranslate(const PhysXXML::PxD6Joint & joint)
2815 {
2816 IAttachment::exportRotateTranslate(getPhysXExporter(), joint.actors.actor1.actor1, joint.localPose.eActor1.translation, joint.localPose.eActor1.rotation);
2817 }
2818 };
2819
2820 class BreakForce : public Element
2821 {
2822 public:
BreakForce(PhysXExporter & exporter,double breakForce)2823 BreakForce(PhysXExporter & exporter, double breakForce)
2824 : Element(exporter, CSWC::CSW_ELEMENT_BREAK_FORCE, withPrefix)
2825 {
2826 getStreamWriter().appendValues(breakForce);
2827 }
2828
DefaultValue()2829 static double DefaultValue()
2830 {
2831 return infinite();
2832 }
2833 };
2834
2835 class BreakTorque : public Element
2836 {
2837 public:
BreakTorque(PhysXExporter & exporter,double breakTorque)2838 BreakTorque(PhysXExporter & exporter, double breakTorque)
2839 : Element(exporter, CSWC::CSW_ELEMENT_BREAK_TORQUE, withPrefix)
2840 {
2841 getStreamWriter().appendValues(breakTorque);
2842 }
2843
DefaultValue()2844 static double DefaultValue()
2845 {
2846 return infinite();
2847 }
2848 };
2849
2850 class ConstraintFlags : public Element
2851 {
2852 public:
ConstraintFlags(PhysXExporter & exporter,const Flags<PhysXXML::ConstraintFlags::FlagEnum> & flags)2853 ConstraintFlags(PhysXExporter & exporter, const Flags<PhysXXML::ConstraintFlags::FlagEnum> & flags)
2854 : Element(exporter, CSWC::CSW_ELEMENT_CONSTRAINT_FLAGS, withPrefix)
2855 {
2856 getStreamWriter().appendValues(PhysXExporter::ConstraintFlagsToCOLLADA(flags));
2857 }
2858
DefaultValue()2859 static Flags<PhysXXML::ConstraintFlags::FlagEnum> DefaultValue()
2860 {
2861 return Flags<PhysXXML::ConstraintFlags::FlagEnum>();
2862 }
2863 };
2864
2865 class InvMassScale0 : public Element
2866 {
2867 public:
InvMassScale0(PhysXExporter & exporter,double invMassScale0)2868 InvMassScale0(PhysXExporter & exporter, double invMassScale0)
2869 : Element(exporter, CSWC::CSW_ELEMENT_INV_MASS_SCALE_0, withPrefix)
2870 {
2871 getStreamWriter().appendValues(invMassScale0);
2872 }
2873
DefaultValue()2874 static double DefaultValue()
2875 {
2876 return 1.0;
2877 }
2878 };
2879
2880 class InvInertiaScale0 : public Element
2881 {
2882 public:
InvInertiaScale0(PhysXExporter & exporter,double invInertiaScale0)2883 InvInertiaScale0(PhysXExporter & exporter, double invInertiaScale0)
2884 : Element(exporter, CSWC::CSW_ELEMENT_INV_INERTIA_SCALE_0, withPrefix)
2885 {
2886 getStreamWriter().appendValues(invInertiaScale0);
2887 }
2888
DefaultValue()2889 static double DefaultValue()
2890 {
2891 return 1.0;
2892 }
2893 };
2894
2895 class InvMassScale1 : public Element
2896 {
2897 public:
InvMassScale1(PhysXExporter & exporter,double invMassScale1)2898 InvMassScale1(PhysXExporter & exporter, double invMassScale1)
2899 : Element(exporter, CSWC::CSW_ELEMENT_INV_MASS_SCALE_1, withPrefix)
2900 {
2901 getStreamWriter().appendValues(invMassScale1);
2902 }
2903
DefaultValue()2904 static double DefaultValue()
2905 {
2906 return 1.0;
2907 }
2908 };
2909
2910 class InvInertiaScale1 : public Element
2911 {
2912 public:
InvInertiaScale1(PhysXExporter & exporter,double invInertiaScale1)2913 InvInertiaScale1(PhysXExporter & exporter, double invInertiaScale1)
2914 : Element(exporter, CSWC::CSW_ELEMENT_INV_INERTIA_SCALE_1, withPrefix)
2915 {
2916 getStreamWriter().appendValues(invInertiaScale1);
2917 }
2918
DefaultValue()2919 static double DefaultValue()
2920 {
2921 return 1.0;
2922 }
2923 };
2924
2925 class ProjectionLinearTolerance : public Element
2926 {
2927 public:
ProjectionLinearTolerance(PhysXExporter & exporter,double projectionLinearTolerance)2928 ProjectionLinearTolerance(PhysXExporter & exporter, double projectionLinearTolerance)
2929 : Element(exporter, CSWC::CSW_ELEMENT_PROJECTION_LINEAR_TOLERANCE, withPrefix)
2930 {
2931 getStreamWriter().appendValues(projectionLinearTolerance);
2932 }
2933
DefaultValue()2934 static double DefaultValue()
2935 {
2936 return 1e10;
2937 }
2938 };
2939
2940 class ProjectionAngularTolerance : public Element
2941 {
2942 public:
ProjectionAngularTolerance(PhysXExporter & exporter,double projectionAngularTolerance)2943 ProjectionAngularTolerance(PhysXExporter & exporter, double projectionAngularTolerance)
2944 : Element(exporter, CSWC::CSW_ELEMENT_PROJECTION_ANGULAR_TOLERANCE, withPrefix)
2945 {
2946 getStreamWriter().appendValues(COLLADABU::Math::Utils::radToDeg(projectionAngularTolerance));
2947 }
2948
DefaultValue()2949 static double DefaultValue()
2950 {
2951 return M_PI;
2952 }
2953 };
2954
2955 class BounceThreshold : public Element
2956 {
2957 public:
BounceThreshold(PhysXExporter & exporter,double bounceThreshold)2958 BounceThreshold(PhysXExporter & exporter, double bounceThreshold)
2959 : Element(exporter, CSWC::CSW_ELEMENT_BOUNCE_THRESHOLD, withPrefix)
2960 {
2961 getStreamWriter().appendValues(bounceThreshold);
2962 }
2963
DefaultValue()2964 static double DefaultValue()
2965 {
2966 return 0.0;
2967 }
2968 };
2969
2970 class ContactDistance : public Element
2971 {
2972 public:
ContactDistance(PhysXExporter & exporter,double contactDistance)2973 ContactDistance(PhysXExporter & exporter, double contactDistance)
2974 : Element(exporter, CSWC::CSW_ELEMENT_CONTACT_DISTANCE, withPrefix)
2975 {
2976 getStreamWriter().appendValues(contactDistance);
2977 }
2978
DefaultValue()2979 static double DefaultValue()
2980 {
2981 return 0.0;
2982 }
2983 };
2984
2985 class LimitsLinearExtra : public Element
2986 {
2987 public:
LimitsLinearExtra(PhysXExporter & exporter,const PhysXXML::PxD6Joint & joint)2988 LimitsLinearExtra(PhysXExporter & exporter, const PhysXXML::PxD6Joint & joint)
2989 : Element(exporter, CSWC::CSW_ELEMENT_LINEAR_EXTRA, withPrefix)
2990 {
2991 exportRestitution(joint);
2992 exportBounceThreshold(joint);
2993 exportContactDistance(joint);
2994 }
2995
HasDefaultValues(const PhysXXML::PxD6Joint & joint)2996 static bool HasDefaultValues(const PhysXXML::PxD6Joint & joint)
2997 {
2998 return
2999 joint.linearLimit.restitution.restitution == Restitution::DefaultValue() &&
3000 joint.linearLimit.bounceThreshold.bounceThreshold == BounceThreshold::DefaultValue() &&
3001 joint.linearLimit.contactDistance.contactDistance == ContactDistance::DefaultValue();
3002 }
3003
3004 private:
exportRestitution(const PhysXXML::PxD6Joint & joint)3005 void exportRestitution(const PhysXXML::PxD6Joint & joint)
3006 {
3007 if (joint.linearLimit.restitution.restitution != Restitution::DefaultValue())
3008 {
3009 Restitution e(getPhysXExporter(), joint.linearLimit.restitution.restitution);
3010 }
3011 }
3012
exportBounceThreshold(const PhysXXML::PxD6Joint & joint)3013 void exportBounceThreshold(const PhysXXML::PxD6Joint & joint)
3014 {
3015 if (joint.linearLimit.bounceThreshold.bounceThreshold != BounceThreshold::DefaultValue())
3016 {
3017 BounceThreshold e(getPhysXExporter(), joint.linearLimit.bounceThreshold.bounceThreshold);
3018 }
3019 }
3020
exportContactDistance(const PhysXXML::PxD6Joint & joint)3021 void exportContactDistance(const PhysXXML::PxD6Joint & joint)
3022 {
3023 if (joint.linearLimit.contactDistance.contactDistance != ContactDistance::DefaultValue())
3024 {
3025 ContactDistance e(getPhysXExporter(), joint.linearLimit.contactDistance.contactDistance);
3026 }
3027 }
3028 };
3029
3030 class Restitution2 : public Element
3031 {
3032 public:
Restitution2(PhysXExporter & exporter,double swingRestitution,double twistRestitution)3033 Restitution2(PhysXExporter & exporter, double swingRestitution, double twistRestitution)
3034 : Element(exporter, CSWC::CSW_ELEMENT_RESTITUTION, withPrefix)
3035 {
3036 getStreamWriter().appendValues(swingRestitution, twistRestitution);
3037 }
3038
AreDefaultValues(double swingRestitution,double twistRestitution)3039 static bool AreDefaultValues(double swingRestitution, double twistRestitution)
3040 {
3041 return swingRestitution == Restitution::DefaultValue() && twistRestitution == Restitution::DefaultValue();
3042 }
3043 };
3044
3045 class BounceThreshold2 : public Element
3046 {
3047 public:
BounceThreshold2(PhysXExporter & exporter,double swingBounceThreshold,double twistBounceThreshold)3048 BounceThreshold2(PhysXExporter & exporter, double swingBounceThreshold, double twistBounceThreshold)
3049 : Element(exporter, CSWC::CSW_ELEMENT_BOUNCE_THRESHOLD, withPrefix)
3050 {
3051 getStreamWriter().appendValues(swingBounceThreshold, twistBounceThreshold);
3052 }
3053
AreDefaultValues(double swingBounceThreshold,double twistBounceThreshold)3054 static bool AreDefaultValues(double swingBounceThreshold, double twistBounceThreshold)
3055 {
3056 return swingBounceThreshold == BounceThreshold::DefaultValue() && twistBounceThreshold == BounceThreshold::DefaultValue();
3057 }
3058 };
3059
3060 class ContactDistance2 : public Element
3061 {
3062 public:
ContactDistance2(PhysXExporter & exporter,double swingContactDistance,double twistContactDistance)3063 ContactDistance2(PhysXExporter & exporter, double swingContactDistance, double twistContactDistance)
3064 : Element(exporter, CSWC::CSW_ELEMENT_CONTACT_DISTANCE, withPrefix)
3065 {
3066 getStreamWriter().appendValues(swingContactDistance, twistContactDistance);
3067 }
3068
AreDefaultValues(double swingContactDistance,double twistContactDistance)3069 static bool AreDefaultValues(double swingContactDistance, double twistContactDistance)
3070 {
3071 return swingContactDistance == ContactDistance::DefaultValue() && twistContactDistance == ContactDistance::DefaultValue();
3072 }
3073 };
3074
3075 class SwingConeAndTwistExtra : public Element
3076 {
3077 public:
SwingConeAndTwistExtra(PhysXExporter & exporter,const PhysXXML::PxD6Joint & joint)3078 SwingConeAndTwistExtra(PhysXExporter & exporter, const PhysXXML::PxD6Joint & joint)
3079 : Element(exporter, CSWC::CSW_ELEMENT_SWING_CONE_AND_TWIST_EXTRA, withPrefix)
3080 {
3081 exportRestitution(joint);
3082 exportBounceThreshold(joint);
3083 exportContactDistance(joint);
3084 }
3085
HasDefaultValues(const PhysXXML::PxD6Joint & joint)3086 static bool HasDefaultValues(const PhysXXML::PxD6Joint & joint)
3087 {
3088 return
3089 Restitution2::AreDefaultValues(joint.swingLimit.restitution.restitution, joint.twistLimit.restitution.restitution) &&
3090 BounceThreshold2::AreDefaultValues(joint.swingLimit.bounceThreshold.bounceThreshold, joint.twistLimit.bounceThreshold.bounceThreshold) &&
3091 ContactDistance2::AreDefaultValues(joint.swingLimit.contactDistance.contactDistance, joint.twistLimit.contactDistance.contactDistance);
3092 }
3093
3094 private:
exportRestitution(const PhysXXML::PxD6Joint & joint)3095 void exportRestitution(const PhysXXML::PxD6Joint & joint)
3096 {
3097 if (!Restitution2::AreDefaultValues(joint.swingLimit.restitution.restitution, joint.twistLimit.restitution.restitution))
3098 {
3099 Restitution2 e(getPhysXExporter(), joint.swingLimit.restitution.restitution, joint.twistLimit.restitution.restitution);
3100 }
3101 }
3102
exportBounceThreshold(const PhysXXML::PxD6Joint & joint)3103 void exportBounceThreshold(const PhysXXML::PxD6Joint & joint)
3104 {
3105 if (!BounceThreshold2::AreDefaultValues(joint.swingLimit.bounceThreshold.bounceThreshold, joint.twistLimit.bounceThreshold.bounceThreshold))
3106 {
3107 BounceThreshold2 e(getPhysXExporter(), joint.swingLimit.bounceThreshold.bounceThreshold, joint.twistLimit.bounceThreshold.bounceThreshold);
3108 }
3109 }
3110
exportContactDistance(const PhysXXML::PxD6Joint & joint)3111 void exportContactDistance(const PhysXXML::PxD6Joint & joint)
3112 {
3113 if (!ContactDistance2::AreDefaultValues(joint.swingLimit.contactDistance.contactDistance, joint.twistLimit.contactDistance.contactDistance))
3114 {
3115 ContactDistance2 e(getPhysXExporter(), joint.swingLimit.contactDistance.contactDistance, joint.twistLimit.contactDistance.contactDistance);
3116 }
3117 }
3118 };
3119
3120 class LimitsExtra : public Element
3121 {
3122 public:
LimitsExtra(PhysXExporter & exporter,const PhysXXML::PxD6Joint & joint)3123 LimitsExtra(PhysXExporter & exporter, const PhysXXML::PxD6Joint & joint)
3124 : Element(exporter, CSWC::CSW_ELEMENT_LIMITS_EXTRA, withPrefix)
3125 {
3126 exportLinearExtra(joint);
3127 exportSwingConeAndTwistExtra(joint);
3128 }
3129
HasDefaultValues(const PhysXXML::PxD6Joint & joint)3130 static bool HasDefaultValues(const PhysXXML::PxD6Joint & joint)
3131 {
3132 return LimitsLinearExtra::HasDefaultValues(joint) &&
3133 SwingConeAndTwistExtra::HasDefaultValues(joint);
3134 }
3135
3136 private:
exportLinearExtra(const PhysXXML::PxD6Joint & joint)3137 void exportLinearExtra(const PhysXXML::PxD6Joint & joint)
3138 {
3139 if (!LimitsLinearExtra::HasDefaultValues(joint))
3140 {
3141 LimitsLinearExtra e(getPhysXExporter(), joint);
3142 }
3143 }
3144
exportSwingConeAndTwistExtra(const PhysXXML::PxD6Joint & joint)3145 void exportSwingConeAndTwistExtra(const PhysXXML::PxD6Joint & joint)
3146 {
3147 if (!SwingConeAndTwistExtra::HasDefaultValues(joint))
3148 {
3149 SwingConeAndTwistExtra e(getPhysXExporter(), joint);
3150 }
3151 }
3152 };
3153
3154 class SpringAngularExtra : public Element
3155 {
3156 public:
SpringAngularExtra(PhysXExporter & exporter,const PhysXXML::PxD6Joint & joint)3157 SpringAngularExtra(PhysXExporter & exporter, const PhysXXML::PxD6Joint & joint)
3158 : Element(exporter, CSWC::CSW_ELEMENT_ANGULAR_EXTRA, withPrefix)
3159 {
3160 exportStiffness(joint);
3161 exportDamping(joint);
3162 }
3163
HasDefaultValues(const PhysXXML::PxD6Joint & joint)3164 static bool HasDefaultValues(const PhysXXML::PxD6Joint & joint)
3165 {
3166 return joint.twistLimit.stiffness.stiffness == Stiffness::DefaultValue() &&
3167 joint.twistLimit.damping.damping == Damping::DefaultValue();
3168 }
3169
3170 private:
exportStiffness(const PhysXXML::PxD6Joint & joint)3171 void exportStiffness(const PhysXXML::PxD6Joint & joint)
3172 {
3173 if (joint.twistLimit.stiffness.stiffness != Stiffness::DefaultValue())
3174 {
3175 Stiffness e(getPhysXExporter(), joint.twistLimit.stiffness.stiffness, withPrefix);
3176 }
3177 }
3178
exportDamping(const PhysXXML::PxD6Joint & joint)3179 void exportDamping(const PhysXXML::PxD6Joint & joint)
3180 {
3181 if (joint.twistLimit.damping.damping != Damping::DefaultValue())
3182 {
3183 Damping e(getPhysXExporter(), joint.twistLimit.damping.damping, withPrefix);
3184 }
3185 }
3186 };
3187
3188 class SpringExtra : public Element
3189 {
3190 public:
SpringExtra(PhysXExporter & exporter,const PhysXXML::PxD6Joint & joint)3191 SpringExtra(PhysXExporter & exporter, const PhysXXML::PxD6Joint & joint)
3192 : Element(exporter, CSWC::CSW_ELEMENT_SPRING_EXTRA, withPrefix)
3193 {
3194 exportAngularExtra(joint);
3195 }
3196
HasDefaultValues(const PhysXXML::PxD6Joint & joint)3197 static bool HasDefaultValues(const PhysXXML::PxD6Joint & joint)
3198 {
3199 return SpringAngularExtra::HasDefaultValues(joint);
3200 }
3201
3202 private:
exportAngularExtra(const PhysXXML::PxD6Joint & joint)3203 void exportAngularExtra(const PhysXXML::PxD6Joint & joint)
3204 {
3205 if (!SpringAngularExtra::HasDefaultValues(joint))
3206 {
3207 SpringAngularExtra e(getPhysXExporter(), joint);
3208 }
3209 }
3210 };
3211
3212 class ForceLimit : public Element
3213 {
3214 public:
ForceLimit(PhysXExporter & exporter,double forceLimit)3215 ForceLimit(PhysXExporter & exporter, double forceLimit)
3216 : Element(exporter, CSWC::CSW_ELEMENT_FORCE_LIMIT, withPrefix)
3217 {
3218 getStreamWriter().appendValues(forceLimit);
3219 }
3220
DefaultValue()3221 static double DefaultValue()
3222 {
3223 return infinite();
3224 }
3225 };
3226
3227 class DriveFlags : public Element
3228 {
3229 public:
DriveFlags(PhysXExporter & exporter,const Flags<PhysXXML::DriveFlags::FlagEnum> & flags)3230 DriveFlags(PhysXExporter & exporter, const Flags<PhysXXML::DriveFlags::FlagEnum> & flags)
3231 : Element(exporter, CSWC::CSW_ELEMENT_DRIVE_FLAGS, withPrefix)
3232 {
3233 getStreamWriter().appendValues(PhysXExporter::DriveFlagsToCOLLADA(flags));
3234 }
3235
DefaultValue()3236 static Flags<PhysXXML::DriveFlags::FlagEnum> DefaultValue()
3237 {
3238 return Flags<PhysXXML::DriveFlags::FlagEnum>();
3239 }
3240 };
3241
3242 class LinearX : public Element
3243 {
3244 public:
LinearX(PhysXExporter & exporter,const PhysXXML::PxD6Joint & joint)3245 LinearX(PhysXExporter & exporter, const PhysXXML::PxD6Joint & joint)
3246 : Element(exporter, CSWC::CSW_ELEMENT_LINEAR_X, withPrefix)
3247 {
3248 exportStiffness(joint);
3249 exportDamping(joint);
3250 exportForceLimit(joint);
3251 exportDriveFlags(joint);
3252 }
3253
HasDefaultValues(const PhysXXML::PxD6Joint & joint)3254 static bool HasDefaultValues(const PhysXXML::PxD6Joint & joint)
3255 {
3256 return joint.drive.driveX.stiffness.stiffness == Stiffness::DefaultValue() &&
3257 joint.drive.driveX.damping.damping == Damping::DefaultValue() &&
3258 joint.drive.driveX.forceLimit.forceLimit == ForceLimit::DefaultValue() &&
3259 joint.drive.driveX.flags.flags == DriveFlags::DefaultValue();
3260 }
3261
3262 private:
exportStiffness(const PhysXXML::PxD6Joint & joint)3263 void exportStiffness(const PhysXXML::PxD6Joint & joint)
3264 {
3265 if (joint.drive.driveX.stiffness.stiffness != Stiffness::DefaultValue())
3266 {
3267 Stiffness e(getPhysXExporter(), joint.drive.driveX.stiffness.stiffness, withPrefix);
3268 }
3269 }
3270
exportDamping(const PhysXXML::PxD6Joint & joint)3271 void exportDamping(const PhysXXML::PxD6Joint & joint)
3272 {
3273 if (joint.drive.driveX.damping.damping != Damping::DefaultValue())
3274 {
3275 Damping e(getPhysXExporter(), joint.drive.driveX.damping.damping, withPrefix);
3276 }
3277 }
3278
exportForceLimit(const PhysXXML::PxD6Joint & joint)3279 void exportForceLimit(const PhysXXML::PxD6Joint & joint)
3280 {
3281 if (joint.drive.driveX.forceLimit.forceLimit != ForceLimit::DefaultValue())
3282 {
3283 ForceLimit e(getPhysXExporter(), joint.drive.driveX.forceLimit.forceLimit);
3284 }
3285 }
3286
exportDriveFlags(const PhysXXML::PxD6Joint & joint)3287 void exportDriveFlags(const PhysXXML::PxD6Joint & joint)
3288 {
3289 if (joint.drive.driveX.flags.flags != DriveFlags::DefaultValue())
3290 {
3291 DriveFlags e(getPhysXExporter(), joint.drive.driveX.flags.flags);
3292 }
3293 }
3294 };
3295
3296 class LinearY : public Element
3297 {
3298 public:
LinearY(PhysXExporter & exporter,const PhysXXML::PxD6Joint & joint)3299 LinearY(PhysXExporter & exporter, const PhysXXML::PxD6Joint & joint)
3300 : Element(exporter, CSWC::CSW_ELEMENT_LINEAR_Y, withPrefix)
3301 {
3302 exportStiffness(joint);
3303 exportDamping(joint);
3304 exportForceLimit(joint);
3305 exportDriveFlags(joint);
3306 }
3307
HasDefaultValues(const PhysXXML::PxD6Joint & joint)3308 static bool HasDefaultValues(const PhysXXML::PxD6Joint & joint)
3309 {
3310 return joint.drive.driveY.stiffness.stiffness == Stiffness::DefaultValue() &&
3311 joint.drive.driveY.damping.damping == Damping::DefaultValue() &&
3312 joint.drive.driveY.forceLimit.forceLimit == ForceLimit::DefaultValue() &&
3313 joint.drive.driveY.flags.flags == DriveFlags::DefaultValue();
3314 }
3315
3316 private:
exportStiffness(const PhysXXML::PxD6Joint & joint)3317 void exportStiffness(const PhysXXML::PxD6Joint & joint)
3318 {
3319 if (joint.drive.driveY.stiffness.stiffness != Stiffness::DefaultValue())
3320 {
3321 Stiffness e(getPhysXExporter(), joint.drive.driveY.stiffness.stiffness, withPrefix);
3322 }
3323 }
3324
exportDamping(const PhysXXML::PxD6Joint & joint)3325 void exportDamping(const PhysXXML::PxD6Joint & joint)
3326 {
3327 if (joint.drive.driveY.damping.damping != Damping::DefaultValue())
3328 {
3329 Damping e(getPhysXExporter(), joint.drive.driveY.damping.damping, withPrefix);
3330 }
3331 }
3332
exportForceLimit(const PhysXXML::PxD6Joint & joint)3333 void exportForceLimit(const PhysXXML::PxD6Joint & joint)
3334 {
3335 if (joint.drive.driveY.forceLimit.forceLimit != ForceLimit::DefaultValue())
3336 {
3337 ForceLimit e(getPhysXExporter(), joint.drive.driveY.forceLimit.forceLimit);
3338 }
3339 }
3340
exportDriveFlags(const PhysXXML::PxD6Joint & joint)3341 void exportDriveFlags(const PhysXXML::PxD6Joint & joint)
3342 {
3343 if (joint.drive.driveY.flags.flags != DriveFlags::DefaultValue())
3344 {
3345 DriveFlags e(getPhysXExporter(), joint.drive.driveY.flags.flags);
3346 }
3347 }
3348 };
3349
3350 class LinearZ : public Element
3351 {
3352 public:
LinearZ(PhysXExporter & exporter,const PhysXXML::PxD6Joint & joint)3353 LinearZ(PhysXExporter & exporter, const PhysXXML::PxD6Joint & joint)
3354 : Element(exporter, CSWC::CSW_ELEMENT_LINEAR_Z, withPrefix)
3355 {
3356 exportStiffness(joint);
3357 exportDamping(joint);
3358 exportForceLimit(joint);
3359 exportDriveFlags(joint);
3360 }
3361
HasDefaultValues(const PhysXXML::PxD6Joint & joint)3362 static bool HasDefaultValues(const PhysXXML::PxD6Joint & joint)
3363 {
3364 return joint.drive.driveZ.stiffness.stiffness == Stiffness::DefaultValue() &&
3365 joint.drive.driveZ.damping.damping == Damping::DefaultValue() &&
3366 joint.drive.driveZ.forceLimit.forceLimit == ForceLimit::DefaultValue() &&
3367 joint.drive.driveZ.flags.flags == DriveFlags::DefaultValue();
3368 }
3369
3370 private:
exportStiffness(const PhysXXML::PxD6Joint & joint)3371 void exportStiffness(const PhysXXML::PxD6Joint & joint)
3372 {
3373 if (joint.drive.driveZ.stiffness.stiffness != Stiffness::DefaultValue())
3374 {
3375 Stiffness e(getPhysXExporter(), joint.drive.driveZ.stiffness.stiffness, withPrefix);
3376 }
3377 }
3378
exportDamping(const PhysXXML::PxD6Joint & joint)3379 void exportDamping(const PhysXXML::PxD6Joint & joint)
3380 {
3381 if (joint.drive.driveZ.damping.damping != Damping::DefaultValue())
3382 {
3383 Damping e(getPhysXExporter(), joint.drive.driveZ.damping.damping, withPrefix);
3384 }
3385 }
3386
exportForceLimit(const PhysXXML::PxD6Joint & joint)3387 void exportForceLimit(const PhysXXML::PxD6Joint & joint)
3388 {
3389 if (joint.drive.driveZ.forceLimit.forceLimit != ForceLimit::DefaultValue())
3390 {
3391 ForceLimit e(getPhysXExporter(), joint.drive.driveZ.forceLimit.forceLimit);
3392 }
3393 }
3394
exportDriveFlags(const PhysXXML::PxD6Joint & joint)3395 void exportDriveFlags(const PhysXXML::PxD6Joint & joint)
3396 {
3397 if (joint.drive.driveZ.flags.flags != DriveFlags::DefaultValue())
3398 {
3399 DriveFlags e(getPhysXExporter(), joint.drive.driveZ.flags.flags);
3400 }
3401 }
3402 };
3403
3404 class Swing : public Element
3405 {
3406 public:
Swing(PhysXExporter & exporter,const PhysXXML::PxD6Joint & joint)3407 Swing(PhysXExporter & exporter, const PhysXXML::PxD6Joint & joint)
3408 : Element(exporter, CSWC::CSW_ELEMENT_SWING, withPrefix)
3409 {
3410 exportStiffness(joint);
3411 exportDamping(joint);
3412 exportForceLimit(joint);
3413 exportDriveFlags(joint);
3414 }
3415
HasDefaultValues(const PhysXXML::PxD6Joint & joint)3416 static bool HasDefaultValues(const PhysXXML::PxD6Joint & joint)
3417 {
3418 return joint.drive.driveSwing.stiffness.stiffness == Stiffness::DefaultValue() &&
3419 joint.drive.driveSwing.damping.damping == Damping::DefaultValue() &&
3420 joint.drive.driveSwing.forceLimit.forceLimit == ForceLimit::DefaultValue() &&
3421 joint.drive.driveSwing.flags.flags == DriveFlags::DefaultValue();
3422 }
3423
3424 private:
exportStiffness(const PhysXXML::PxD6Joint & joint)3425 void exportStiffness(const PhysXXML::PxD6Joint & joint)
3426 {
3427 if (joint.drive.driveSwing.stiffness.stiffness != Stiffness::DefaultValue())
3428 {
3429 Stiffness e(getPhysXExporter(), joint.drive.driveSwing.stiffness.stiffness, withPrefix);
3430 }
3431 }
3432
exportDamping(const PhysXXML::PxD6Joint & joint)3433 void exportDamping(const PhysXXML::PxD6Joint & joint)
3434 {
3435 if (joint.drive.driveSwing.damping.damping != Damping::DefaultValue())
3436 {
3437 Damping e(getPhysXExporter(), joint.drive.driveSwing.damping.damping, withPrefix);
3438 }
3439 }
3440
exportForceLimit(const PhysXXML::PxD6Joint & joint)3441 void exportForceLimit(const PhysXXML::PxD6Joint & joint)
3442 {
3443 if (joint.drive.driveSwing.forceLimit.forceLimit != ForceLimit::DefaultValue())
3444 {
3445 ForceLimit e(getPhysXExporter(), joint.drive.driveSwing.forceLimit.forceLimit);
3446 }
3447 }
3448
exportDriveFlags(const PhysXXML::PxD6Joint & joint)3449 void exportDriveFlags(const PhysXXML::PxD6Joint & joint)
3450 {
3451 if (joint.drive.driveSwing.flags.flags != DriveFlags::DefaultValue())
3452 {
3453 DriveFlags e(getPhysXExporter(), joint.drive.driveSwing.flags.flags);
3454 }
3455 }
3456 };
3457
3458 class Twist : public Element
3459 {
3460 public:
Twist(PhysXExporter & exporter,const PhysXXML::PxD6Joint & joint)3461 Twist(PhysXExporter & exporter, const PhysXXML::PxD6Joint & joint)
3462 : Element(exporter, CSWC::CSW_ELEMENT_TWIST, withPrefix)
3463 {
3464 exportStiffness(joint);
3465 exportDamping(joint);
3466 exportForceLimit(joint);
3467 exportDriveFlags(joint);
3468 }
3469
HasDefaultValues(const PhysXXML::PxD6Joint & joint)3470 static bool HasDefaultValues(const PhysXXML::PxD6Joint & joint)
3471 {
3472 return joint.drive.driveTwist.stiffness.stiffness == Stiffness::DefaultValue() &&
3473 joint.drive.driveTwist.damping.damping == Damping::DefaultValue() &&
3474 joint.drive.driveTwist.forceLimit.forceLimit == ForceLimit::DefaultValue() &&
3475 joint.drive.driveTwist.flags.flags == DriveFlags::DefaultValue();
3476 }
3477
3478 private:
exportStiffness(const PhysXXML::PxD6Joint & joint)3479 void exportStiffness(const PhysXXML::PxD6Joint & joint)
3480 {
3481 if (joint.drive.driveTwist.stiffness.stiffness != Stiffness::DefaultValue())
3482 {
3483 Stiffness e(getPhysXExporter(), joint.drive.driveTwist.stiffness.stiffness, withPrefix);
3484 }
3485 }
3486
exportDamping(const PhysXXML::PxD6Joint & joint)3487 void exportDamping(const PhysXXML::PxD6Joint & joint)
3488 {
3489 if (joint.drive.driveTwist.damping.damping != Damping::DefaultValue())
3490 {
3491 Damping e(getPhysXExporter(), joint.drive.driveTwist.damping.damping, withPrefix);
3492 }
3493 }
3494
exportForceLimit(const PhysXXML::PxD6Joint & joint)3495 void exportForceLimit(const PhysXXML::PxD6Joint & joint)
3496 {
3497 if (joint.drive.driveTwist.forceLimit.forceLimit != ForceLimit::DefaultValue())
3498 {
3499 ForceLimit e(getPhysXExporter(), joint.drive.driveTwist.forceLimit.forceLimit);
3500 }
3501 }
3502
exportDriveFlags(const PhysXXML::PxD6Joint & joint)3503 void exportDriveFlags(const PhysXXML::PxD6Joint & joint)
3504 {
3505 if (joint.drive.driveTwist.flags.flags != DriveFlags::DefaultValue())
3506 {
3507 DriveFlags e(getPhysXExporter(), joint.drive.driveTwist.flags.flags);
3508 }
3509 }
3510 };
3511
3512 class Slerp : public Element
3513 {
3514 public:
Slerp(PhysXExporter & exporter,const PhysXXML::PxD6Joint & joint)3515 Slerp(PhysXExporter & exporter, const PhysXXML::PxD6Joint & joint)
3516 : Element(exporter, CSWC::CSW_ELEMENT_SLERP, withPrefix)
3517 {
3518 exportStiffness(joint);
3519 exportDamping(joint);
3520 exportForceLimit(joint);
3521 exportDriveFlags(joint);
3522 }
3523
HasDefaultValues(const PhysXXML::PxD6Joint & joint)3524 static bool HasDefaultValues(const PhysXXML::PxD6Joint & joint)
3525 {
3526 return joint.drive.driveSlerp.stiffness.stiffness == Stiffness::DefaultValue() &&
3527 joint.drive.driveSlerp.damping.damping == Damping::DefaultValue() &&
3528 joint.drive.driveSlerp.forceLimit.forceLimit == ForceLimit::DefaultValue();
3529 }
3530
3531 private:
exportStiffness(const PhysXXML::PxD6Joint & joint)3532 void exportStiffness(const PhysXXML::PxD6Joint & joint)
3533 {
3534 if (joint.drive.driveSlerp.stiffness.stiffness != Stiffness::DefaultValue())
3535 {
3536 Stiffness e(getPhysXExporter(), joint.drive.driveSlerp.stiffness.stiffness, withPrefix);
3537 }
3538 }
3539
exportDamping(const PhysXXML::PxD6Joint & joint)3540 void exportDamping(const PhysXXML::PxD6Joint & joint)
3541 {
3542 if (joint.drive.driveSlerp.damping.damping != Damping::DefaultValue())
3543 {
3544 Damping e(getPhysXExporter(), joint.drive.driveSlerp.damping.damping, withPrefix);
3545 }
3546 }
3547
exportForceLimit(const PhysXXML::PxD6Joint & joint)3548 void exportForceLimit(const PhysXXML::PxD6Joint & joint)
3549 {
3550 if (joint.drive.driveSlerp.forceLimit.forceLimit != ForceLimit::DefaultValue())
3551 {
3552 ForceLimit e(getPhysXExporter(), joint.drive.driveSlerp.forceLimit.forceLimit);
3553 }
3554 }
3555
exportDriveFlags(const PhysXXML::PxD6Joint & joint)3556 void exportDriveFlags(const PhysXXML::PxD6Joint & joint)
3557 {
3558 if (joint.drive.driveSlerp.flags.flags != DriveFlags::DefaultValue())
3559 {
3560 DriveFlags e(getPhysXExporter(), joint.drive.driveSlerp.flags.flags);
3561 }
3562 }
3563 };
3564
3565 class LinearVelocity : public Element
3566 {
3567 public:
LinearVelocity(PhysXExporter & exporter,const MVector & linearVelocity)3568 LinearVelocity(PhysXExporter & exporter, const MVector & linearVelocity)
3569 : Element(exporter, CSWC::CSW_ELEMENT_LINEAR_VELOCITY, withPrefix)
3570 {
3571 getStreamWriter().appendValues(linearVelocity.x, linearVelocity.y, linearVelocity.z);
3572 }
3573
DefaultValue()3574 static const MVector & DefaultValue()
3575 {
3576 return MVector::zero;
3577 }
3578 };
3579
3580 class AngularVelocity : public Element
3581 {
3582 public:
AngularVelocity(PhysXExporter & exporter,const MVector & velocity,bool elementForm)3583 AngularVelocity(PhysXExporter & exporter, const MVector & velocity, bool elementForm)
3584 : Element(exporter, CSWC::CSW_ELEMENT_ANGULAR_VELOCITY, elementForm)
3585 {
3586 getStreamWriter().appendValues(velocity.x, velocity.y, velocity.z);
3587 }
3588
DefaultValue()3589 static const MVector & DefaultValue()
3590 {
3591 return MVector::zero;
3592 }
3593 };
3594
3595 class Drive : public Element
3596 {
3597 public:
Drive(PhysXExporter & exporter,const PhysXXML::PxD6Joint & joint)3598 Drive(PhysXExporter & exporter, const PhysXXML::PxD6Joint & joint)
3599 : Element(exporter, CSWC::CSW_ELEMENT_DRIVE, withPrefix)
3600 {
3601 exportLinearX(joint);
3602 exportLinearY(joint);
3603 exportLinearZ(joint);
3604 exportSwing(joint);
3605 exportTwist(joint);
3606 exportSlerp(joint);
3607 exportRotateTranslate(joint);
3608 exportLinearVelocity(joint);
3609 exportAngularVelocity(joint);
3610 }
3611
HasDefaultValues(const PhysXXML::PxD6Joint & joint)3612 static bool HasDefaultValues(const PhysXXML::PxD6Joint & joint)
3613 {
3614 return LinearX::HasDefaultValues(joint) &&
3615 LinearY::HasDefaultValues(joint) &&
3616 LinearZ::HasDefaultValues(joint) &&
3617 Swing::HasDefaultValues(joint) &&
3618 Twist::HasDefaultValues(joint) &&
3619 Slerp::HasDefaultValues(joint) &&
3620 joint.drivePosition.translation == MVector::zero &&
3621 joint.drivePosition.rotation == MQuaternion::identity &&
3622 joint.driveVelocity.linear.linear == LinearVelocity::DefaultValue() &&
3623 joint.driveVelocity.angular.angular == AngularVelocity::DefaultValue();
3624 }
3625
3626 private:
exportLinearX(const PhysXXML::PxD6Joint & joint)3627 void exportLinearX(const PhysXXML::PxD6Joint & joint)
3628 {
3629 if (!LinearX::HasDefaultValues(joint))
3630 {
3631 LinearX e(getPhysXExporter(), joint);
3632 }
3633 }
3634
exportLinearY(const PhysXXML::PxD6Joint & joint)3635 void exportLinearY(const PhysXXML::PxD6Joint & joint)
3636 {
3637 if (!LinearY::HasDefaultValues(joint))
3638 {
3639 LinearY e(getPhysXExporter(), joint);
3640 }
3641 }
3642
exportLinearZ(const PhysXXML::PxD6Joint & joint)3643 void exportLinearZ(const PhysXXML::PxD6Joint & joint)
3644 {
3645 if (!LinearZ::HasDefaultValues(joint))
3646 {
3647 LinearZ e(getPhysXExporter(), joint);
3648 }
3649 }
3650
exportSwing(const PhysXXML::PxD6Joint & joint)3651 void exportSwing(const PhysXXML::PxD6Joint & joint)
3652 {
3653 if (!Swing::HasDefaultValues(joint))
3654 {
3655 Swing e(getPhysXExporter(), joint);
3656 }
3657 }
3658
exportTwist(const PhysXXML::PxD6Joint & joint)3659 void exportTwist(const PhysXXML::PxD6Joint & joint)
3660 {
3661 if (!Twist::HasDefaultValues(joint))
3662 {
3663 Twist e(getPhysXExporter(), joint);
3664 }
3665 }
3666
exportSlerp(const PhysXXML::PxD6Joint & joint)3667 void exportSlerp(const PhysXXML::PxD6Joint & joint)
3668 {
3669 if (!Slerp::HasDefaultValues(joint))
3670 {
3671 Slerp e(getPhysXExporter(), joint);
3672 }
3673 }
3674
exportRotateTranslate(const PhysXXML::PxD6Joint & joint)3675 void exportRotateTranslate(const PhysXXML::PxD6Joint & joint)
3676 {
3677 MVector translation = joint.drivePosition.translation;
3678 MEulerRotation rotation = joint.drivePosition.rotation.asEulerRotation();
3679
3680 getPhysXExporter().exportTranslationWithoutConversion(translation, ATTR_TRANSLATE);
3681 getPhysXExporter().exportRotation(rotation, ATTR_ROTATE);
3682 }
3683
exportLinearVelocity(const PhysXXML::PxD6Joint & joint)3684 void exportLinearVelocity(const PhysXXML::PxD6Joint & joint)
3685 {
3686 if (joint.driveVelocity.linear.linear != LinearVelocity::DefaultValue())
3687 {
3688 LinearVelocity e(getPhysXExporter(), joint.driveVelocity.linear.linear);
3689 }
3690 }
3691
exportAngularVelocity(const PhysXXML::PxD6Joint & joint)3692 void exportAngularVelocity(const PhysXXML::PxD6Joint & joint)
3693 {
3694 if (joint.driveVelocity.angular.angular != AngularVelocity::DefaultValue())
3695 {
3696 AngularVelocity e(getPhysXExporter(), joint.driveVelocity.angular.angular, withPrefix);
3697 }
3698 }
3699 };
3700
3701 class LocalPose0 : public Element
3702 {
3703 public:
LocalPose0(PhysXExporter & exporter,const MQuaternion & rotation,const MVector & translation)3704 LocalPose0(PhysXExporter& exporter, const MQuaternion& rotation, const MVector& translation)
3705 : Element(exporter, CSWC::CSW_ELEMENT_LOCAL_POSE_0, withPrefix)
3706 {
3707 double localPose[] = { rotation.x, rotation.y, rotation.z, rotation.w, translation.x, translation.y, translation.z };
3708 getStreamWriter().appendValues(localPose, sizeof(localPose) / sizeof(localPose[0]));
3709 }
3710 };
3711
3712 class LocalPose1 : public Element
3713 {
3714 public:
LocalPose1(PhysXExporter & exporter,const MQuaternion & rotation,const MVector & translation)3715 LocalPose1(PhysXExporter& exporter, const MQuaternion& rotation, const MVector& translation)
3716 : Element(exporter, CSWC::CSW_ELEMENT_LOCAL_POSE_1, withPrefix)
3717 {
3718 double localPose[] = { rotation.x, rotation.y, rotation.z, rotation.w, translation.x, translation.y, translation.z };
3719 getStreamWriter().appendValues(localPose, sizeof(localPose) / sizeof(localPose[0]));
3720 }
3721 };
3722
3723 class PxD6Joint : public Element
3724 {
3725 public:
PxD6Joint(PhysXExporter & exporter,const PhysXXML::PxD6Joint & joint)3726 PxD6Joint(PhysXExporter& exporter, const PhysXXML::PxD6Joint & joint)
3727 : Element(exporter, CSWC::CSW_ELEMENT_PX_D6JOINT, withPrefix)
3728 {
3729 exportLocalPose0(joint);
3730 exportLocalPose1(joint);
3731 exportBreakForce(joint);
3732 exportBreakTorque(joint);
3733 exportConstraintFlags(joint);
3734 exportInvMassScale0(joint);
3735 exportInvInertiaScale0(joint);
3736 exportInvMassScale1(joint);
3737 exportInvInertiaScale1(joint);
3738 exportProjectionLinearTolerance(joint);
3739 exportProjectionAngularTolerance(joint);
3740 exportLimitsExtra(joint);
3741 exportSpringExtra(joint);
3742 exportDrive(joint);
3743 }
3744
HasDefaultValues(const PhysXXML::PxD6Joint & joint)3745 static bool HasDefaultValues(const PhysXXML::PxD6Joint & joint)
3746 {
3747 // Always export local pose 0 and 1
3748 return false;
3749 }
3750
3751 private:
exportLocalPose0(const PhysXXML::PxD6Joint & joint)3752 void exportLocalPose0(const PhysXXML::PxD6Joint & joint)
3753 {
3754 LocalPose0 e(getPhysXExporter(), joint.localPose.eActor0.rotation, joint.localPose.eActor0.translation);
3755 }
3756
exportLocalPose1(const PhysXXML::PxD6Joint & joint)3757 void exportLocalPose1(const PhysXXML::PxD6Joint & joint)
3758 {
3759 LocalPose1 e(getPhysXExporter(), joint.localPose.eActor1.rotation, joint.localPose.eActor1.translation);
3760 }
3761
exportBreakForce(const PhysXXML::PxD6Joint & joint)3762 void exportBreakForce(const PhysXXML::PxD6Joint & joint)
3763 {
3764 if (joint.breakForce.force.force != BreakForce::DefaultValue())
3765 {
3766 BreakForce e(getPhysXExporter(), joint.breakForce.force.force);
3767 }
3768 }
3769
exportBreakTorque(const PhysXXML::PxD6Joint & joint)3770 void exportBreakTorque(const PhysXXML::PxD6Joint & joint)
3771 {
3772 if (joint.breakForce.torque.torque != BreakTorque::DefaultValue())
3773 {
3774 BreakTorque e(getPhysXExporter(), joint.breakForce.torque.torque);
3775 }
3776 }
3777
exportConstraintFlags(const PhysXXML::PxD6Joint & joint)3778 void exportConstraintFlags(const PhysXXML::PxD6Joint & joint)
3779 {
3780 if (joint.constraintFlags.flags != ConstraintFlags::DefaultValue())
3781 {
3782 ConstraintFlags e(getPhysXExporter(), joint.constraintFlags.flags);
3783 }
3784 }
3785
exportInvMassScale0(const PhysXXML::PxD6Joint & joint)3786 void exportInvMassScale0(const PhysXXML::PxD6Joint & joint)
3787 {
3788 if (joint.invMassScale0.invMassScale0 != InvMassScale0::DefaultValue())
3789 {
3790 InvMassScale0 e(getPhysXExporter(), joint.invMassScale0.invMassScale0);
3791 }
3792 }
3793
exportInvInertiaScale0(const PhysXXML::PxD6Joint & joint)3794 void exportInvInertiaScale0(const PhysXXML::PxD6Joint & joint)
3795 {
3796 if (joint.invInertiaScale0.invInertiaScale0 != InvInertiaScale0::DefaultValue())
3797 {
3798 InvInertiaScale0 e(getPhysXExporter(), joint.invInertiaScale0.invInertiaScale0);
3799 }
3800 }
3801
exportInvMassScale1(const PhysXXML::PxD6Joint & joint)3802 void exportInvMassScale1(const PhysXXML::PxD6Joint & joint)
3803 {
3804 if (joint.invMassScale1.invMassScale1 != InvMassScale1::DefaultValue())
3805 {
3806 InvMassScale1 e(getPhysXExporter(), joint.invMassScale1.invMassScale1);
3807 }
3808 }
3809
exportInvInertiaScale1(const PhysXXML::PxD6Joint & joint)3810 void exportInvInertiaScale1(const PhysXXML::PxD6Joint & joint)
3811 {
3812 if (joint.invInertiaScale1.invInertiaScale1 != InvInertiaScale1::DefaultValue())
3813 {
3814 InvInertiaScale1 e(getPhysXExporter(), joint.invInertiaScale1.invInertiaScale1);
3815 }
3816 }
3817
exportProjectionLinearTolerance(const PhysXXML::PxD6Joint & joint)3818 void exportProjectionLinearTolerance(const PhysXXML::PxD6Joint & joint)
3819 {
3820 if (joint.projectionLinearTolerance.projectionLinearTolerance != ProjectionLinearTolerance::DefaultValue())
3821 {
3822 ProjectionLinearTolerance e(getPhysXExporter(), joint.projectionLinearTolerance.projectionLinearTolerance);
3823 }
3824 }
3825
exportProjectionAngularTolerance(const PhysXXML::PxD6Joint & joint)3826 void exportProjectionAngularTolerance(const PhysXXML::PxD6Joint & joint)
3827 {
3828 if (joint.projectionAngularTolerance.projectionAngularTolerance != ProjectionAngularTolerance::DefaultValue())
3829 {
3830 ProjectionAngularTolerance e(getPhysXExporter(), joint.projectionAngularTolerance.projectionAngularTolerance);
3831 }
3832 }
3833
exportLimitsExtra(const PhysXXML::PxD6Joint & joint)3834 void exportLimitsExtra(const PhysXXML::PxD6Joint & joint)
3835 {
3836 if (!LimitsExtra::HasDefaultValues(joint))
3837 {
3838 LimitsExtra e(getPhysXExporter(), joint);
3839 }
3840 }
3841
exportSpringExtra(const PhysXXML::PxD6Joint & joint)3842 void exportSpringExtra(const PhysXXML::PxD6Joint & joint)
3843 {
3844 if (!SpringExtra::HasDefaultValues(joint))
3845 {
3846 SpringExtra e(getPhysXExporter(), joint);
3847 }
3848 }
3849
exportDrive(const PhysXXML::PxD6Joint & joint)3850 void exportDrive(const PhysXXML::PxD6Joint & joint)
3851 {
3852 if (!Drive::HasDefaultValues(joint))
3853 {
3854 Drive e(getPhysXExporter(), joint);
3855 }
3856 }
3857 };
3858
3859 class RigidConstraintTechnique : public Element
3860 {
3861 public:
RigidConstraintTechnique(PhysXExporter & exporter,const MObject & rigidConstraint,const PhysXXML::PxD6Joint & joint,const String & profile)3862 RigidConstraintTechnique(PhysXExporter& exporter, const MObject & rigidConstraint, const PhysXXML::PxD6Joint & joint, const String & profile)
3863 : Element(exporter, CSWC::CSW_ELEMENT_TECHNIQUE)
3864 {
3865 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_PROFILE, profile);
3866 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_XMLNS + ":" + CSWC::CSW_PREFIX_PX, PhysXExporter::GetXMLNS());
3867 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_XSI_SCHEMALOCATION, PhysXExporter::GetXSISchemaLocation());
3868 if (profile == PROFILE_MAYA) {
3869 exporter.exportExtraAttributes(rigidConstraint);
3870 }
3871 else if (profile == PhysXExporter::GetPhysXProfile()) {
3872 exportPxD6Joint(joint);
3873 }
3874 }
3875
HasDefaultValues(const MObject & constraint,const PhysXXML::PxD6Joint & joint,const String & profile)3876 static bool HasDefaultValues(const MObject & constraint, const PhysXXML::PxD6Joint & joint, const String & profile)
3877 {
3878 if (profile == PhysXExporter::GetPhysXProfile())
3879 {
3880 return PxD6Joint::HasDefaultValues(joint);
3881 }
3882 else if (profile == PROFILE_MAYA)
3883 {
3884 return !PhysXExporter::HasExtraAttributes(constraint);
3885 }
3886 return true;
3887 }
3888
3889 private:
exportPxD6Joint(const PhysXXML::PxD6Joint & joint)3890 void exportPxD6Joint(const PhysXXML::PxD6Joint & joint)
3891 {
3892 if (!PxD6Joint::HasDefaultValues(joint))
3893 {
3894 PxD6Joint e(getPhysXExporter(), joint);
3895 }
3896 }
3897
3898 private:
3899 static std::set<MString, MStringComp> mAttributes;
3900 };
3901 std::set<MString, MStringComp> RigidConstraintTechnique::mAttributes;
3902
3903 class RigidConstraintExtra : public Element
3904 {
3905 public:
RigidConstraintExtra(PhysXExporter & exporter,const MObject & rigidConstraint,const PhysXXML::PxD6Joint & joint)3906 RigidConstraintExtra(PhysXExporter& exporter, const MObject & rigidConstraint, const PhysXXML::PxD6Joint & joint)
3907 : Element(exporter, CSWC::CSW_ELEMENT_EXTRA)
3908 {
3909 if (PhysXExporter::HasExtraAttributes(rigidConstraint)) {
3910 exportTechnique(rigidConstraint, joint, PROFILE_MAYA);
3911 }
3912 exportTechnique(rigidConstraint, joint, PhysXExporter::GetPhysXProfile());
3913 }
3914
HasDefaultValues(const MObject & constraint,const PhysXXML::PxD6Joint & joint)3915 static bool HasDefaultValues(const MObject & constraint, const PhysXXML::PxD6Joint & joint)
3916 {
3917 return
3918 RigidConstraintTechnique::HasDefaultValues(constraint, joint, PROFILE_MAYA) &&
3919 RigidConstraintTechnique::HasDefaultValues(constraint, joint, PhysXExporter::GetPhysXProfile());
3920 }
3921
3922 private:
exportTechnique(const MObject & rigidConstraint,const PhysXXML::PxD6Joint & joint,const String & profile)3923 void exportTechnique(const MObject& rigidConstraint, const PhysXXML::PxD6Joint & joint, const String& profile)
3924 {
3925 if (!RigidConstraintTechnique::HasDefaultValues(rigidConstraint, joint, profile))
3926 {
3927 RigidConstraintTechnique e(getPhysXExporter(), rigidConstraint, joint, profile);
3928 }
3929 }
3930 };
3931
3932 class RigidConstraint : public Element
3933 {
3934 public:
RigidConstraint(PhysXExporter & exporter,const MObject & rigidConstraint,const String & sid,const String & name="")3935 RigidConstraint(PhysXExporter& exporter, const MObject & rigidConstraint, const String & sid, const String & name = "")
3936 : Element(exporter, CSWC::CSW_ELEMENT_RIGID_CONSTRAINT)
3937 {
3938 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_SID, sid);
3939 if (name.length() > 0) {
3940 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_NAME, name);
3941 }
3942
3943 const PhysXXML::PxD6Joint* joint = exporter.findPxD6Joint(rigidConstraint);
3944 if (joint)
3945 {
3946 exportRefAttachment(*joint);
3947 exportAttachment(*joint);
3948 exportTechniqueCommon(rigidConstraint, *joint);
3949 exportExtra(rigidConstraint, *joint);
3950 }
3951 }
3952
3953 private:
exportRefAttachment(const PhysXXML::PxD6Joint & joint)3954 void exportRefAttachment(const PhysXXML::PxD6Joint & joint)
3955 {
3956 MObject rigidBody;
3957 if (const PhysXXML::PxRigidBody* pxRigidBody = getPhysXExporter().findPxRigidBody(joint.actors.actor0.actor0))
3958 {
3959 MObject target = DagHelper::getNode(pxRigidBody->name.name.c_str());
3960 rigidBody = getPhysXExporter().getNodeRigidBody(target);
3961 }
3962
3963 URI rigidBodyURI;
3964 if (rigidBody.isNull())
3965 {
3966 rigidBodyURI.set("");
3967 }
3968 else
3969 {
3970 MDagPath rigidBodyDagPath;
3971 MDagPath::getAPathTo(rigidBody, rigidBodyDagPath);
3972
3973 String rigidBodySid = getPhysXExporter().generateColladaId(rigidBodyDagPath);
3974 String rigidBodyId = getPhysXExporter().GetDefaultPhysicsModelId() + '/' + rigidBodySid;
3975 URI rigidBodyURI = getPhysXExporter().getDocumentExporter().getVisualSceneExporter()->getSceneElementURI(rigidBodyDagPath, rigidBodyId);
3976 }
3977
3978 RefAttachment e(getPhysXExporter(), joint, rigidBodyURI);
3979 }
3980
exportAttachment(const PhysXXML::PxD6Joint & joint)3981 void exportAttachment(const PhysXXML::PxD6Joint & joint)
3982 {
3983 const PhysXXML::PxRigidBody* pxRigidBody = getPhysXExporter().findPxRigidBody(joint.actors.actor1.actor1);
3984 if (!pxRigidBody)
3985 return;
3986
3987 MObject target = DagHelper::getNode(pxRigidBody->name.name.c_str());
3988 MObject rigidBody = getPhysXExporter().getNodeRigidBody(target);
3989
3990 MDagPath rigidBodyDagPath;
3991 MDagPath::getAPathTo(rigidBody, rigidBodyDagPath);
3992
3993 String rigidBodySid = getPhysXExporter().generateColladaId(rigidBodyDagPath);
3994 String rigidBodyId = getPhysXExporter().GetDefaultPhysicsModelId() + '/' + rigidBodySid;
3995 URI rigidBodyURI = getPhysXExporter().getDocumentExporter().getVisualSceneExporter()->getSceneElementURI(rigidBodyDagPath, rigidBodyId);
3996
3997 Attachment e(getPhysXExporter(), joint, rigidBodyURI);
3998 }
3999
exportTechniqueCommon(const MObject & rigidConstraint,const PhysXXML::PxD6Joint & joint)4000 void exportTechniqueCommon(const MObject & rigidConstraint, const PhysXXML::PxD6Joint & joint)
4001 {
4002 RigidConstraintTechniqueCommon e(getPhysXExporter(), rigidConstraint, joint);
4003 }
4004
exportExtra(const MObject & rigidConstraint,const PhysXXML::PxD6Joint & joint)4005 void exportExtra(const MObject & rigidConstraint, const PhysXXML::PxD6Joint & joint)
4006 {
4007 if (!RigidConstraintExtra::HasDefaultValues(rigidConstraint, joint))
4008 {
4009 RigidConstraintExtra e(getPhysXExporter(), rigidConstraint, joint);
4010 }
4011 }
4012 };
4013
4014 class Velocity : public Element
4015 {
4016 public:
Velocity(PhysXExporter & exporter,const MVector & velocity)4017 Velocity(PhysXExporter & exporter, const MVector & velocity)
4018 : Element(exporter, CSWC::CSW_ELEMENT_VELOCITY)
4019 {
4020 getStreamWriter().appendValues(velocity.x, velocity.y, velocity.z);
4021 }
4022
DefaultValue()4023 static const MVector & DefaultValue()
4024 {
4025 return MVector::zero;
4026 }
4027 };
4028
4029 class InstanceRigidBodyTechniqueCommon : public Element
4030 {
4031 public:
InstanceRigidBodyTechniqueCommon(PhysXExporter & exporter,const MVector & angularVelocity,const MVector & velocity)4032 InstanceRigidBodyTechniqueCommon(PhysXExporter& exporter, const MVector & angularVelocity, const MVector& velocity)
4033 : Element(exporter, CSWC::CSW_ELEMENT_TECHNIQUE_COMMON)
4034 {
4035 exportAngularVelocity(angularVelocity);
4036 exportVelocity(velocity);
4037 }
4038
AreDefaultValues(const MVector & angularVelocity,const MVector & velocity)4039 static bool AreDefaultValues(const MVector & angularVelocity, const MVector & velocity)
4040 {
4041 return
4042 angularVelocity == AngularVelocity::DefaultValue() &&
4043 velocity == Velocity::DefaultValue();
4044 }
4045
4046 private:
exportAngularVelocity(const MVector & angularVelocity)4047 void exportAngularVelocity(const MVector& angularVelocity)
4048 {
4049 if (angularVelocity != AngularVelocity::DefaultValue())
4050 {
4051 AngularVelocity e(getPhysXExporter(), angularVelocity, withoutPrefix);
4052 }
4053 }
4054
exportVelocity(const MVector & velocity)4055 void exportVelocity(const MVector& velocity)
4056 {
4057 if (velocity != Velocity::DefaultValue())
4058 {
4059 Velocity e(getPhysXExporter(), velocity);
4060 }
4061 }
4062 };
4063
4064 class InstanceRigidBody : public Element
4065 {
4066 public:
InstanceRigidBody(PhysXExporter & exporter,const MObject & rigidBody,const String & instanceRigidBodySID,const String & rigidBodySID,const URI & targetURI)4067 InstanceRigidBody(PhysXExporter& exporter, const MObject & rigidBody, const String& instanceRigidBodySID, const String & rigidBodySID, const URI & targetURI)
4068 : Element(exporter, CSWC::CSW_ELEMENT_INSTANCE_RIGID_BODY)
4069 {
4070 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_SID, instanceRigidBodySID);
4071 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_BODY, rigidBodySID);
4072 getStreamWriter().appendURIAttribute(CSWC::CSW_ATTRIBUTE_TARGET, targetURI);
4073
4074 MVector initialSpin = MVector::zero;
4075 MVector initialVelocity = MVector::zero;
4076 if (!rigidBody.isNull())
4077 {
4078 DagHelper::getPlugValue(rigidBody, ATTR_INITIAL_SPIN, initialSpin);
4079 initialSpin.x = COLLADABU::Math::Utils::radToDeg(initialSpin.x);
4080 initialSpin.y = COLLADABU::Math::Utils::radToDeg(initialSpin.y);
4081 initialSpin.z = COLLADABU::Math::Utils::radToDeg(initialSpin.z);
4082
4083 DagHelper::getPlugValue(rigidBody, ATTR_INITIAL_VELOCITY, initialVelocity);
4084 initialVelocity.x = MDistance::internalToUI(initialVelocity.x);
4085 initialVelocity.y = MDistance::internalToUI(initialVelocity.y);
4086 initialVelocity.z = MDistance::internalToUI(initialVelocity.z);
4087 }
4088 exportTechniqueCommon(initialSpin, initialVelocity);
4089 }
4090
4091 private:
exportTechniqueCommon(const MVector & angularVelocity,const MVector & velocity)4092 void exportTechniqueCommon(const MVector& angularVelocity, const MVector& velocity)
4093 {
4094 InstanceRigidBodyTechniqueCommon e(getPhysXExporter(), angularVelocity, velocity);
4095 }
4096 };
4097
4098 class InstanceRigidConstraint : public Element
4099 {
4100 public:
InstanceRigidConstraint(PhysXExporter & exporter,const String & instanceConstraintSid,const String & constraintSid)4101 InstanceRigidConstraint(PhysXExporter & exporter, const String& instanceConstraintSid, const String & constraintSid)
4102 : Element(exporter, CSWC::CSW_ELEMENT_INSTANCE_RIGID_CONSTRAINT)
4103 {
4104 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_SID, instanceConstraintSid);
4105 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_CONSTRAINT, constraintSid);
4106 }
4107 };
4108
4109 class InstancePhysicsModel : public Element
4110 {
4111 public:
InstancePhysicsModel(PhysXExporter & exporter,const String & sid,const URI & uri)4112 InstancePhysicsModel(PhysXExporter& exporter, const String& sid, const URI& uri)
4113 : Element(exporter, CSWC::CSW_ELEMENT_INSTANCE_PHYSICS_MODEL)
4114 {
4115 if (!sid.empty()) {
4116 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_SID, sid);
4117 }
4118 getStreamWriter().appendURIAttribute(CSWC::CSW_ATTRIBUTE_URL, uri);
4119
4120 exportInstanceRigidBodies();
4121 exportInstanceRigidConstraints();
4122 }
4123
4124 private:
4125 class RigidBodyParser
4126 {
4127 public:
RigidBodyParser(PhysXExporter & exporter)4128 RigidBodyParser(PhysXExporter & exporter)
4129 : mPhysXExporter(exporter)
4130 , mInstanceRigidBodyIndex(0)
4131 {}
4132
operator ()(SceneElement & element)4133 bool operator()(SceneElement & element)
4134 {
4135 if (element.getType() == SceneElement::PHYSX_RIGID_BODY &&
4136 element.getIsLocal())
4137 {
4138 const MObject & rigidBody = element.getNode();
4139
4140 MObject target = PhysXExporter::GetRigidBodyTarget(rigidBody);
4141 MDagPath targetDagPath;
4142 MDagPath::getAPathTo(target, targetDagPath);
4143 SceneElement* targetElement = mPhysXExporter.getDocumentExporter().getSceneGraph()->findElement(targetDagPath);
4144 if (targetElement)
4145 {
4146 String rigidBodySid = mPhysXExporter.generateColladaId(element.getPath());
4147 std::stringstream s;
4148 s << "_" << mInstanceRigidBodyIndex++;
4149 String instanceRigidBodySid = rigidBodySid + s.str();
4150 URI targetURI = mPhysXExporter.getDocumentExporter().getVisualSceneExporter()->getSceneElementURI(targetElement);
4151 InstanceRigidBody e(mPhysXExporter, rigidBody, instanceRigidBodySid, rigidBodySid, targetURI);
4152 }
4153 }
4154 return true;
4155 }
4156
4157 private:
4158 PhysXExporter & mPhysXExporter;
4159 int mInstanceRigidBodyIndex;
4160 };
4161
exportInstanceRigidBodies()4162 void exportInstanceRigidBodies()
4163 {
4164 PhysXExporter& exporter = getPhysXExporter();
4165
4166 // Export ground plane if enabled
4167 MObject rigidSolver = exporter.getRigidSolver();
4168 if (!rigidSolver.isNull())
4169 {
4170 String name = GROUND_PLANE_NAME;
4171 String sid = name;
4172
4173 bool useGroundPlane = false;
4174 DagHelper::getPlugValue(rigidSolver, ATTR_USE_GROUND_PLANE, useGroundPlane);
4175 const PhysXXML::PxRigidBody* groundPlane = exporter.findPxRigidBody(name);
4176 if (useGroundPlane && groundPlane)
4177 {
4178 InstanceRigidBody e(exporter, MObject::kNullObj, name, name, "");
4179 }
4180 }
4181
4182 RigidBodyParser rigidBodyParser(exporter);
4183 exporter.parseSceneElements(rigidBodyParser);
4184 }
4185
4186 class RigidConstraintParser
4187 {
4188 public:
RigidConstraintParser(PhysXExporter & exporter)4189 RigidConstraintParser(PhysXExporter & exporter)
4190 : mPhysXExporter(exporter)
4191 , mInstanceRigidConstraintIndex(0)
4192 {}
4193
operator ()(SceneElement & element)4194 bool operator()(SceneElement & element)
4195 {
4196 if (element.getType() == SceneElement::PHYSX_RIGID_CONSTRAINT &&
4197 element.getIsLocal())
4198 {
4199 const MObject & rigidConstraint = element.getNode();
4200
4201 String rigidConstraintSid = mPhysXExporter.generateColladaId(element.getPath());
4202 std::stringstream s;
4203 s << "_" << mInstanceRigidConstraintIndex++;
4204 String instanceRigidConstraintSid = rigidConstraintSid + s.str();
4205 InstanceRigidConstraint e(mPhysXExporter, instanceRigidConstraintSid, rigidConstraintSid);
4206 }
4207 return true;
4208 }
4209
4210 private:
4211 PhysXExporter & mPhysXExporter;
4212 int mInstanceRigidConstraintIndex;
4213 };
4214
exportInstanceRigidConstraints()4215 void exportInstanceRigidConstraints()
4216 {
4217 RigidConstraintParser rigidConstraintParser(getPhysXExporter());
4218 getPhysXExporter().parseSceneElements(rigidConstraintParser);
4219 }
4220 };
4221
4222 class PhysicsModel : public Element
4223 {
4224 public:
PhysicsModel(PhysXExporter & exporter,const String & id)4225 PhysicsModel(PhysXExporter& exporter, const String & id)
4226 : Element(exporter, CSWC::CSW_ELEMENT_PHYSICS_MODEL)
4227 {
4228 if (!id.empty()) {
4229 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_ID, id);
4230 }
4231 exportRigidBodies();
4232 exportRigidConstraints();
4233 //exportInstancePhysicsModels();
4234 }
4235
4236 private:
4237 class RigidBodyParser
4238 {
4239 public:
RigidBodyParser(PhysXExporter & exporter)4240 RigidBodyParser(PhysXExporter & exporter)
4241 : mPhysXExporter(exporter)
4242 {}
4243
operator ()(SceneElement & element)4244 bool operator()(SceneElement & element)
4245 {
4246 if (element.getType() == SceneElement::PHYSX_RIGID_BODY &&
4247 element.getIsLocal())
4248 {
4249 String rigidBodySid = mPhysXExporter.generateColladaId(element.getPath());
4250 String rigidBodyName = mPhysXExporter.generateColladaName(element.getPath());
4251
4252 const MObject & rigidBody = element.getNode();
4253
4254 RigidBody e(mPhysXExporter, rigidBody, rigidBodySid, rigidBodyName);
4255 }
4256 return true;
4257 }
4258
4259 private:
4260 PhysXExporter & mPhysXExporter;
4261 };
4262
exportRigidBodies()4263 void exportRigidBodies()
4264 {
4265 PhysXExporter& exporter = getPhysXExporter();
4266
4267 // Export ground plane if enabled
4268 MObject rigidSolver = exporter.getRigidSolver();
4269 if (!rigidSolver.isNull())
4270 {
4271 String name = GROUND_PLANE_NAME;
4272 String sid = name;
4273
4274 bool useGroundPlane = false;
4275 DagHelper::getPlugValue(rigidSolver, ATTR_USE_GROUND_PLANE, useGroundPlane);
4276 const PhysXXML::PxRigidBody* groundPlane = exporter.findPxRigidBody(name);
4277 if (useGroundPlane && groundPlane)
4278 {
4279 RigidBody e(exporter, *groundPlane, sid, name);
4280 }
4281 }
4282
4283 // Export the other rigid bodies
4284 RigidBodyParser rigidBodyParser(exporter);
4285 exporter.parseSceneElements(rigidBodyParser);
4286 }
4287
4288 class RigidConstraintParser
4289 {
4290 public:
RigidConstraintParser(PhysXExporter & exporter)4291 RigidConstraintParser(PhysXExporter & exporter)
4292 : mPhysXExporter(exporter)
4293 {}
4294
operator ()(SceneElement & element)4295 bool operator()(SceneElement & element)
4296 {
4297 if (element.getType() == SceneElement::PHYSX_RIGID_CONSTRAINT &&
4298 element.getIsLocal())
4299 {
4300 String rigidConstraintSid = mPhysXExporter.generateColladaId(element.getPath());
4301 String rigidConstraintName = mPhysXExporter.generateColladaName(element.getPath());
4302
4303 const MObject & rigidConstraint = element.getNode();
4304
4305 RigidConstraint e(mPhysXExporter, rigidConstraint, rigidConstraintSid, rigidConstraintName);
4306 }
4307 return true;
4308 }
4309
4310 private:
4311 PhysXExporter & mPhysXExporter;
4312 };
4313
exportRigidConstraints()4314 void exportRigidConstraints()
4315 {
4316 RigidConstraintParser rigidConstraintParser(getPhysXExporter());
4317 getPhysXExporter().parseSceneElements(rigidConstraintParser);
4318 }
4319 };
4320
4321 class LibraryPhysicsModels : public Element
4322 {
4323 public:
LibraryPhysicsModels(PhysXExporter & exporter)4324 LibraryPhysicsModels(PhysXExporter& exporter)
4325 : Element(exporter, CSWC::CSW_ELEMENT_LIBRARY_PHYSICS_MODELS)
4326 {
4327 PhysicsModel e(exporter, PhysXExporter::GetDefaultPhysicsModelId());
4328 }
4329 };
4330
4331 class Gravity : public Element
4332 {
4333 public:
Gravity(PhysXExporter & exporter,const MVector & gravity)4334 Gravity(PhysXExporter & exporter, const MVector & gravity)
4335 : Element(exporter, CSWC::CSW_ELEMENT_GRAVITY)
4336 {
4337 getStreamWriter().appendValues(gravity.x, gravity.y, gravity.z);
4338 }
4339 };
4340
4341 class PhysicsSceneTechniqueCommon : public Element
4342 {
4343 public:
PhysicsSceneTechniqueCommon(PhysXExporter & exporter)4344 PhysicsSceneTechniqueCommon(PhysXExporter & exporter)
4345 : Element(exporter, CSWC::CSW_ELEMENT_TECHNIQUE_COMMON)
4346 {
4347 MObject rigidSolver = exporter.getRigidSolver();
4348 if (!rigidSolver.isNull())
4349 {
4350 exportGravity(rigidSolver);
4351 exportTimeStep(rigidSolver);
4352 }
4353 }
4354
4355 private:
exportGravity(const MObject & rigidSolver)4356 void exportGravity(const MObject & rigidSolver)
4357 {
4358 bool gravityEnabled = false;
4359 DagHelper::getPlugValue(rigidSolver, ATTR_GRAVITY, gravityEnabled);
4360 if (gravityEnabled)
4361 {
4362 double gravityMagnitude = 9.18;
4363 DagHelper::getPlugValue(rigidSolver, ATTR_GRAVITY_MAGNITUDE, gravityMagnitude);
4364
4365 MVector gravityDirection(0.0, -1.0, 0.0);
4366 DagHelper::getPlugValue(rigidSolver, ATTR_GRAVITY_DIRECTION, gravityDirection);
4367
4368 gravityDirection.x = MDistance::internalToUI(gravityDirection.x);
4369 gravityDirection.y = MDistance::internalToUI(gravityDirection.y);
4370 gravityDirection.z = MDistance::internalToUI(gravityDirection.z);
4371
4372 Gravity e(getPhysXExporter(), gravityDirection * gravityMagnitude);
4373 }
4374 }
4375
exportTimeStep(const MObject & rigidSolver)4376 void exportTimeStep(const MObject & rigidSolver)
4377 {
4378
4379 }
4380 };
4381
4382 class PhysicsScene : public Element
4383 {
4384 public:
PhysicsScene(PhysXExporter & exporter,const String & id)4385 PhysicsScene(PhysXExporter& exporter, const String & id)
4386 : Element(exporter, CSWC::CSW_ELEMENT_PHYSICS_SCENE)
4387 {
4388 if (!id.empty()) {
4389 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_ID, id);
4390 }
4391 exportInstancePhysicsModels();
4392 exportTechniqueCommon();
4393 }
4394
4395 private:
exportInstancePhysicsModels()4396 void exportInstancePhysicsModels()
4397 {
4398 // Local physics model
4399 if (getPhysXExporter().sceneHas(SceneElement::PHYSX_RIGID_BODY, PhysXExporter::Local) ||
4400 getPhysXExporter().sceneHas(SceneElement::PHYSX_RIGID_CONSTRAINT, PhysXExporter::Local))
4401 {
4402 String physicsModelId = PhysXExporter::GetDefaultPhysicsModelId();
4403
4404 URI uri;
4405 uri.set("");
4406 uri.setFragment(physicsModelId);
4407
4408 InstancePhysicsModel e(getPhysXExporter(), PhysXExporter::GetDefaultInstancePhysicsModelSid(), uri);
4409 }
4410 }
4411
exportTechniqueCommon()4412 void exportTechniqueCommon()
4413 {
4414 PhysicsSceneTechniqueCommon e(getPhysXExporter());
4415 }
4416 };
4417
4418 class LibraryPhysicsScenes : public Element
4419 {
4420 public:
LibraryPhysicsScenes(PhysXExporter & exporter)4421 LibraryPhysicsScenes(PhysXExporter& exporter)
4422 : Element(exporter, CSWC::CSW_ELEMENT_LIBRARY_PHYSICS_SCENES)
4423 {
4424 PhysicsScene e(exporter, PhysXExporter::GetDefaultPhysicsSceneId());
4425 }
4426 };
4427
4428 class Translate : public Element
4429 {
4430 public:
Translate(PhysXExporter & exporter,const MVector & translation,const String & sid="")4431 Translate(PhysXExporter& exporter, const MVector & translation, const String & sid = "")
4432 : Element(exporter, CSWC::CSW_ELEMENT_TRANSLATE)
4433 {
4434 if (sid.length() > 0)
4435 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_SID, sid);
4436 getStreamWriter().appendValues(translation.x, translation.y, translation.z);
4437 }
4438 };
4439
4440 class Rotate : public Element
4441 {
4442 public:
Rotate(PhysXExporter & exporter,const MVector & axis,double angle,const String & sid="")4443 Rotate(PhysXExporter& exporter, const MVector & axis, double angle, const String & sid = "")
4444 : Element(exporter, CSWC::CSW_ELEMENT_ROTATE)
4445 {
4446 if (sid.length() > 0) {
4447 getStreamWriter().appendAttribute(CSWC::CSW_ATTRIBUTE_SID, sid);
4448 }
4449 getStreamWriter().appendValues(axis.x, axis.y, axis.z, angle);
4450 }
4451 };
4452
4453 String PhysXExporter::mDefaultPhysicsModelId = "collada_physics_model";
4454 String PhysXExporter::mDefaultPhysicsSceneId = "collada_physics_scene";
4455 String PhysXExporter::mDefaultInstancePhysicsModelSid = "instancePhysicsModel";
4456 String PhysXExporter::mPhysXProfile = "PhysX_3.x";
4457 String PhysXExporter::mXMLNS = "http://www.collada.org/2016/08/COLLADAPhysX3Schema";
4458 String PhysXExporter::mSchemaLocation = "http://www.collada.org/2016/08/COLLADAPhysX3Schema.xsd";
4459
PhysXExporter(StreamWriter & streamWriter,DocumentExporter & documentExporter)4460 PhysXExporter::PhysXExporter(StreamWriter& streamWriter, DocumentExporter& documentExporter)
4461 : mStreamWriter(streamWriter)
4462 , mDocumentExporter(documentExporter)
4463 {}
4464
4465 class RigidBodyParser
4466 {
4467 public:
RigidBodyParser(const SceneElement & meshElement)4468 RigidBodyParser(const SceneElement & meshElement)
4469 : mMeshElement(meshElement)
4470 , mNeedsConvexHullOfMeshElement(false)
4471 {}
4472
operator ()(SceneElement & element)4473 bool operator()(SceneElement & element)
4474 {
4475 if (element.getType() == SceneElement::PHYSX_RIGID_BODY)
4476 {
4477 std::vector<MObject> shapes;
4478 PhysXExporter::GetRigidBodyShapes(element.getNode(), shapes);
4479
4480 for (size_t i = 0; i < shapes.size(); ++i)
4481 {
4482 const MObject & shape = shapes[i];
4483 int dummy = 0;
4484 MString shapeType;
4485 DagHelper::getPlugValue(shape, ATTR_SHAPE_TYPE, dummy, shapeType);
4486 if (shapeType == SHAPE_TYPE_CONVEX_HULL)
4487 {
4488 MObject connectedMesh;
4489 PhysXShape::GetConnectedInMesh(shape, connectedMesh);
4490
4491 if (mMeshElement.getNode() == connectedMesh ||
4492 mMeshElement.getNode() == shape)
4493 {
4494 mNeedsConvexHullOfMeshElement = true;
4495 mShape = shape;
4496 return false;
4497 }
4498 }
4499 }
4500 }
4501 return true;
4502 }
4503
needsConvexHullOfMeshElement() const4504 bool needsConvexHullOfMeshElement() const
4505 {
4506 return mNeedsConvexHullOfMeshElement;
4507 }
4508
getShape() const4509 const MObject& getShape() const
4510 {
4511 return mShape;
4512 }
4513
4514 private:
4515 const SceneElement & mMeshElement;
4516 bool mNeedsConvexHullOfMeshElement;
4517 MObject mShape;
4518 };
4519
needsConvexHullOf(const SceneElement & meshElement,MObject & shape)4520 bool PhysXExporter::needsConvexHullOf(const SceneElement & meshElement, MObject& shape)
4521 {
4522 if (!ExportOptions::exportPhysics())
4523 return false;
4524
4525 RigidBodyParser parser(meshElement);
4526 parseSceneElements(parser);
4527 shape = parser.getShape();
4528 return parser.needsConvexHullOfMeshElement();
4529 }
4530
ExtractPhysXPluginVersionNumbers(const MString & mversion,int & major,int & minor,int & a,int & b)4531 bool ExtractPhysXPluginVersionNumbers(
4532 const MString & mversion,
4533 int & major,
4534 int & minor,
4535 int & a,
4536 int & b)
4537 {
4538 String version = mversion.asChar();
4539
4540 size_t p1 = version.find('(');
4541 if (p1 == String::npos) return false;
4542 ++p1;
4543 if (p1 >= version.length()) return false;
4544
4545 size_t p2 = version.find(')', p1);
4546 if (p2 == String::npos) return false;
4547
4548 MString mnumbers = version.substr(p1, p2 - p1).c_str();
4549 MStringArray numbers;
4550 mnumbers.split('.', numbers);
4551 if (numbers.length() != 4) return false;
4552
4553 std::stringstream s;
4554 s << numbers[0] << ' ' << numbers[1] << ' ' << numbers[2] << ' ' << numbers[3];
4555 s >> major >> minor >> a >> b;
4556
4557 return true;
4558 }
4559
CheckPhysXPluginVersion()4560 bool PhysXExporter::CheckPhysXPluginVersion()
4561 {
4562 MObject pluginObject = MFnPlugin::findPlugin("physx");
4563
4564 if (pluginObject.isNull()) {
4565 return false;
4566 }
4567
4568 MFnPlugin fnPlugin(pluginObject);
4569
4570 MStatus status;
4571 MString mversion = fnPlugin.version(&status);
4572 if (!status) return false;
4573
4574 int requ_major = 0;
4575 int requ_minor = 0;
4576 int requ_a = 0;
4577 int requ_b = 0;
4578
4579 int curr_major = 0;
4580 int curr_minor = 0;
4581 int curr_a = 0;
4582 int curr_b = 0;
4583
4584 if (!ExtractPhysXPluginVersionNumbers(GetRequiredPhysXPluginVersion(), requ_major, requ_minor, requ_a, requ_b)) {
4585 return false;
4586 }
4587
4588 if (!ExtractPhysXPluginVersionNumbers(GetInstalledPhysXPluginVersion(), curr_major, curr_minor, curr_a, curr_b)) {
4589 return false;
4590 }
4591
4592 if (curr_major > requ_major) return false;
4593 if (curr_major < requ_major) return false;
4594 if (curr_minor > requ_minor) return true;
4595 if (curr_minor < requ_minor) return false;
4596 if (curr_a > requ_a) return true;
4597 if (curr_a < requ_a) return false;
4598 if (curr_b >= requ_b) return true;
4599 if (curr_b < requ_b) return false;
4600
4601 return true;
4602 }
4603
GetRequiredPhysXPluginVersion()4604 MString PhysXExporter::GetRequiredPhysXPluginVersion()
4605 {
4606 return MString("PhysxForMaya (3.3.10708.21402) , compiled 7/8/2015 9:40:44 PM");
4607 }
4608
GetInstalledPhysXPluginVersion()4609 MString PhysXExporter::GetInstalledPhysXPluginVersion()
4610 {
4611 static MString na = "N/A";
4612
4613 MObject pluginObject = MFnPlugin::findPlugin("physx");
4614 if (pluginObject.isNull()) {
4615 return na;
4616 }
4617
4618 MFnPlugin fnPlugin(pluginObject);
4619
4620 MStatus status;
4621 MString version = fnPlugin.version(&status);
4622 if (!status) return na;
4623
4624 return version;
4625 }
4626
4627 class AutoDeleteFile
4628 {
4629 public:
AutoDeleteFile(const String & filePath)4630 AutoDeleteFile(const String& filePath)
4631 : mFilePath(filePath)
4632 {}
4633
~AutoDeleteFile()4634 ~AutoDeleteFile()
4635 {
4636 if (!mFilePath.empty()) {
4637 COLLADABU::Utils::deleteFile(mFilePath);
4638 }
4639 }
4640
4641 private:
4642 String mFilePath;
4643 };
4644
4645 class AutoXmlFreeDoc
4646 {
4647 public:
AutoXmlFreeDoc(xmlDocPtr xml)4648 AutoXmlFreeDoc(xmlDocPtr xml)
4649 : mXml(xml)
4650 {}
4651
~AutoXmlFreeDoc()4652 ~AutoXmlFreeDoc()
4653 {
4654 if (mXml) {
4655 xmlFreeDoc(mXml);
4656 }
4657 }
4658
4659 private:
4660 xmlDocPtr mXml;
4661 };
4662
4663 class AutoRestorePhysXExportOptions
4664 {
4665 public:
AutoRestorePhysXExportOptions()4666 AutoRestorePhysXExportOptions()
4667 : mError(false)
4668 {
4669 mOptions.push_back(Option("apexClothingExport_APBs", Integer));
4670 mOptions.push_back(Option("validatePhysXSceneBeforeExport", Integer));
4671 mOptions.push_back(Option("PhysXExport_useFolderName", Integer));
4672 mOptions.push_back(Option("apexExport_RemoveNamespaceForJoint", Integer));
4673 mOptions.push_back(Option("apexClothingExport_VisibleOnly", Integer));
4674 mOptions.push_back(Option("PhysXExport_UseJointLongName", Integer));
4675 mOptions.push_back(Option("PhysXExport_exportPxProjFile", Integer));
4676 mOptions.push_back(Option("PhysXExport_exportPhysX", Integer));
4677 mOptions.push_back(Option("PhysXExport_outputUnit", String));
4678 mOptions.push_back(Option("PhysXExport_customScaling", Integer));
4679 mOptions.push_back(Option("PhysXExport_outputScale", Double));
4680
4681 for (size_t i = 0; i < mOptions.size(); ++i) {
4682 switch (mOptions[i].type)
4683 {
4684 case Integer:
4685 {
4686 int oldValue = 0;
4687 MStatus status = MGlobal::executeCommand("optionVar -q \"" + mOptions[i].name + "\"", oldValue);
4688 if (!status) mError |= true;
4689 MString oldValueStr("");
4690 oldValueStr += oldValue;
4691 mOldValues.push_back(oldValueStr);
4692 break;
4693 }
4694 case Double:
4695 {
4696 double oldValue = 0.0;
4697 MStatus status = MGlobal::executeCommand("optionVar -q \"" + mOptions[i].name + "\"", oldValue);
4698 if (!status) mError |= true;
4699 MString oldValueStr("");
4700 oldValueStr += oldValue;
4701 mOldValues.push_back(oldValueStr);
4702 break;
4703 }
4704 case String:
4705 {
4706 MString oldValue;
4707 MStatus status = MGlobal::executeCommand("optionVar -q \"" + mOptions[i].name + "\"", oldValue);
4708 if (!status) mError |= true;
4709 mOldValues.push_back(oldValue);
4710 break;
4711 }
4712 }
4713 }
4714 }
4715
~AutoRestorePhysXExportOptions()4716 ~AutoRestorePhysXExportOptions()
4717 {
4718 for (size_t i = 0; i < mOptions.size(); ++i) {
4719 MString command = "optionVar -";
4720 switch (mOptions[i].type)
4721 {
4722 case Integer: command += "i"; break;
4723 case Double: command += "f"; break;
4724 case String: command += "s"; break;
4725 }
4726 command += "v \"" + mOptions[i].name + "\" ";
4727 if (mOptions[i].type == String)
4728 command += "\"";
4729 command += mOldValues[i];
4730 if (mOptions[i].type == String)
4731 command += "\"";
4732 MGlobal::executeCommand(command);
4733 }
4734 }
4735
error() const4736 bool error() const
4737 {
4738 return mError;
4739 }
4740
4741 private:
4742 enum OptionType
4743 {
4744 Integer,
4745 Double,
4746 String
4747 };
4748
4749 struct Option
4750 {
OptionCOLLADAMaya::AutoRestorePhysXExportOptions::Option4751 Option(const MString& name_, OptionType type_)
4752 : name(name_)
4753 , type(type_)
4754 {}
4755
4756 MString name;
4757 OptionType type;
4758 };
4759 std::vector<Option> mOptions;
4760 std::vector<MString> mOldValues;
4761 bool mError;
4762 };
4763
4764 class PhysicsExportPrePass
4765 {
4766 public:
PhysicsExportPrePass(PhysXExporter & exporter)4767 PhysicsExportPrePass(PhysXExporter & exporter)
4768 : mExporter(exporter)
4769 {}
4770
operator ()(SceneElement & e)4771 bool operator()(SceneElement& e)
4772 {
4773 const MObject & object = e.getNode();
4774
4775 switch (e.getType())
4776 {
4777 case SceneElement::PHYSX_RIGID_BODY:
4778 {
4779 MObject target = PhysXExporter::GetRigidBodyTarget(e.getNode());
4780 MFnDagNode targetNode(target);
4781 MString targetName = targetNode.fullPathName();
4782
4783 mExporter.mTargetToRigidBodyMap[target] = object;
4784
4785 if (const PhysXXML::PxRigidBody* pxRigidBody = mExporter.mPhysXDoc->findRigidBody(targetName.asChar()))
4786 {
4787 mExporter.mRigidBodyToPxRigidBodyMap[object] = pxRigidBody;
4788 mExporter.mPxRigidBodyToRigidBodyMap[pxRigidBody] = object;
4789
4790 if (pxRigidBody->shapes.shapes.size() > 0)
4791 {
4792 if (const PhysXXML::PxMaterial* pxMaterial = mExporter.mPhysXDoc->findMaterial(pxRigidBody->shapes.shapes[0].materials.materialRef.materialRef))
4793 {
4794 mExporter.mRigidBodyToPxMaterialMap[object] = pxMaterial;
4795 }
4796 }
4797 }
4798 }
4799 break;
4800 case SceneElement::PHYSX_SHAPE:
4801 {
4802 MFnDagNode shapeNode(e.getNode());
4803 MString shapeName = shapeNode.fullPathName();
4804 if (const PhysXXML::PxShape* pxShape = mExporter.mPhysXDoc->findShape(shapeName.asChar())) {
4805 mExporter.mShapeToPxShapeMap[object] = pxShape;
4806 mExporter.mPxShapeToShapeMap[pxShape] = object;
4807 }
4808 }
4809 break;
4810 case SceneElement::PHYSX_RIGID_CONSTRAINT:
4811 {
4812 MFnDagNode constraintNode(e.getNode());
4813 MString constraintName = constraintNode.fullPathName();
4814 if (const PhysXXML::PxD6Joint* joint = mExporter.mPhysXDoc->findD6Joint(constraintName.asChar())) {
4815 mExporter.mConstraintToPxD6JointMap[object] = joint;
4816 mExporter.mPxD6JointToConstraintMap[joint] = object;
4817 }
4818 }
4819 break;
4820 case SceneElement::PHYSX_RIGID_SOLVER:
4821 {
4822 mExporter.mRigidSolver = e.getNode();
4823 }
4824 break;
4825 default:
4826 break;
4827 }
4828 return true;
4829 }
4830
4831 private:
4832 PhysXExporter & mExporter;
4833 };
4834
generatePhysXXML()4835 bool PhysXExporter::generatePhysXXML()
4836 {
4837 MStatus status;
4838
4839 // Backup export options
4840 AutoRestorePhysXExportOptions autoRestorePhysXExportOptions;
4841
4842 // Set export options
4843 status = MGlobal::executeCommand("optionVar -iv \"apexClothingExport_APBs\" 2");
4844 if (!status) return false;
4845 status = MGlobal::executeCommand("optionVar -iv \"validatePhysXSceneBeforeExport\" 0");
4846 if (!status) return false;
4847 status = MGlobal::executeCommand("optionVar -iv \"PhysXExport_useFolderName\" 0");
4848 if (!status) return false;
4849 status = MGlobal::executeCommand("optionVar -iv \"apexExport_RemoveNamespaceForJoint\" 0");
4850 if (!status) return false;
4851 status = MGlobal::executeCommand("optionVar -iv \"apexClothingExport_VisibleOnly\" 0");
4852 if (!status) return false;
4853 status = MGlobal::executeCommand("optionVar -iv \"PhysXExport_UseJointLongName\" 1");
4854 if (!status) return false;
4855 status = MGlobal::executeCommand("optionVar -iv \"PhysXExport_exportPxProjFile\" 0");
4856 if (!status) return false;
4857 status = MGlobal::executeCommand("optionVar -iv \"PhysXExport_exportPhysX\" 1");
4858 if (!status) return false;
4859 status = MGlobal::executeCommand("optionVar -sv \"PhysXExport_outputUnit\" \"meter\"");
4860 if (!status) return false;
4861 status = MGlobal::executeCommand("optionVar -iv \"PhysXExport_customScaling\" true");
4862 if (!status) return false;
4863 status = MGlobal::executeCommand("optionVar -fv \"PhysXExport_outputScale\" 1.0");
4864 if (!status) return false;
4865
4866 String filePath = mDocumentExporter.getFilename();
4867 std::stringstream exportCommand;
4868 exportCommand << "file -force -options \"none=0;\" -type \"PhysX\" -pr";
4869 if (mDocumentExporter.getSceneGraph()->getExportSelectedOnly()) {
4870 exportCommand << " -es";
4871 }
4872 else {
4873 exportCommand << " -ea";
4874 }
4875
4876 // Generate temp file name
4877 size_t extPos = filePath.find_last_of('.');
4878 String filePathNoExt = filePath.substr(0, extPos);
4879 String tempFilePath = filePathNoExt + ".xml";
4880 std::ifstream tempFile(tempFilePath.c_str());
4881 int index = 0;
4882 while (tempFile.is_open()) {
4883 std::stringstream s;
4884 s << index++;
4885 tempFilePath = filePathNoExt + s.str() + ".xml";
4886 tempFile.close();
4887 tempFile.open(tempFilePath.c_str());
4888 }
4889
4890 // Set .pxproj as extension but plugin will export a .xml file
4891 String pxProjPath = tempFilePath;
4892 extPos = pxProjPath.find_last_of('.');
4893 pxProjPath.replace(extPos, pxProjPath.length() - extPos, ".PxProj");
4894
4895 exportCommand << " \"" << pxProjPath << "\";";
4896 status = MGlobal::executeCommand(exportCommand.str().c_str());
4897 if (!status) return false;
4898
4899 // delete .xml file when we are done with it.
4900 AutoDeleteFile autoDeleteFile(tempFilePath);
4901
4902 // Read .xml file
4903
4904 // Is this necessary?
4905 LIBXML_TEST_VERSION;
4906
4907 std::ifstream file(tempFilePath.c_str());
4908 if (!file.is_open()) {
4909 return false;
4910 }
4911
4912 std::stringstream fileContentStream;
4913 fileContentStream << file.rdbuf();
4914 std::string fileContent(fileContentStream.str());
4915
4916 int length = static_cast<int>(fileContent.length());
4917 xmlDocPtr xml = xmlReadMemory(fileContent.c_str(), length, "noname.xml", NULL, 0);
4918 if (xml == NULL) {
4919 return false;
4920 }
4921
4922 AutoXmlFreeDoc autoXmlFreeDoc(xml);
4923
4924 // Init our PhysX xml tree
4925 mPhysXDoc = xml;
4926
4927 // Check for duplicated names
4928 if (!mPhysXDoc->validate()) {
4929 MGlobal::displayError("Error while exporting PhysX scene: duplicated names found.");
4930 return false;
4931 }
4932
4933 xmlCleanupParser();
4934
4935 // Initialize physics exporter internal data
4936 PhysicsExportPrePass prepass(*this);
4937 parseSceneElements(prepass);
4938
4939 return true;
4940 }
4941
exportPhysicsLibraries()4942 bool PhysXExporter::exportPhysicsLibraries()
4943 {
4944 // Export to .xml format first using PhysX plugin exporter.
4945 // Produced file contains information not accessible with Maya API.
4946 if (!mPhysXDoc) {
4947 MGlobal::displayError("Can't generate PhysX XML data. PhysX will not be exported.");
4948 return false;
4949 }
4950
4951 bool hasPhysicsScene = false;
4952
4953 if (!ExportOptions::exportPhysics()) {
4954 return hasPhysicsScene;
4955 }
4956
4957 if (sceneHas(SceneElement::PHYSX_RIGID_BODY, Local) ||
4958 sceneHas(SceneElement::PHYSX_RIGID_CONSTRAINT, Local)) {
4959 {
4960 LibraryPhysicsModels(*this);
4961 }
4962 {
4963 LibraryPhysicsScenes(*this);
4964 }
4965 hasPhysicsScene = true;
4966 }
4967
4968 return hasPhysicsScene;
4969 }
4970
getStreamWriter()4971 StreamWriter& PhysXExporter::getStreamWriter()
4972 {
4973 return mStreamWriter;
4974 }
4975
getDocumentExporter()4976 DocumentExporter& PhysXExporter::getDocumentExporter()
4977 {
4978 return mDocumentExporter;
4979 }
4980
exportTranslationWithoutConversion(const MVector & translation,const String & sid)4981 void PhysXExporter::exportTranslationWithoutConversion(const MVector & translation, const String & sid)
4982 {
4983 if (!(COLLADABU::Math::Utils::equalsZero(translation.x, mDocumentExporter.getTolerance()) &&
4984 COLLADABU::Math::Utils::equalsZero(translation.y, mDocumentExporter.getTolerance()) &&
4985 COLLADABU::Math::Utils::equalsZero(translation.z, mDocumentExporter.getTolerance())))
4986 {
4987 Translate(*this, translation, sid);
4988 }
4989 }
4990
exportTranslation(const MVector & translation,const String & sid)4991 void PhysXExporter::exportTranslation(const MVector & translation, const String & sid)
4992 {
4993 if (!(COLLADABU::Math::Utils::equalsZero(translation.x, mDocumentExporter.getTolerance()) &&
4994 COLLADABU::Math::Utils::equalsZero(translation.y, mDocumentExporter.getTolerance()) &&
4995 COLLADABU::Math::Utils::equalsZero(translation.z, mDocumentExporter.getTolerance())))
4996 {
4997 // Convert from Maya internal unit (cm) to export unit
4998 MVector convertedTranslation;
4999 convertedTranslation.x = MDistance::internalToUI(translation.x);
5000 convertedTranslation.y = MDistance::internalToUI(translation.y);
5001 convertedTranslation.z = MDistance::internalToUI(translation.z);
5002
5003 Translate(*this, convertedTranslation, sid);
5004 }
5005 }
5006
exportRotation(const MEulerRotation & rotation,const String & sid)5007 void PhysXExporter::exportRotation(const MEulerRotation & rotation, const String & sid)
5008 {
5009 RotateHelper rotateHelper(rotation);
5010 const std::vector<std::vector<double> >& rotationMatrix = rotateHelper.getRotationMatrix();
5011 const std::vector<String>& rotationParameters = rotateHelper.getRotationParameters();
5012
5013 // Go through the axes for the rotations.
5014 for (uint i = 0; i < 3; ++i)
5015 {
5016 if (!COLLADABU::Math::Utils::equalsZero(rotationMatrix[i][3], mDocumentExporter.getTolerance()))
5017 {
5018 exportRotate(MVector(
5019 COLLADABU::Math::Utils::equalsZero(rotationMatrix[i][0], mDocumentExporter.getTolerance()) ? 0.0 : rotationMatrix[i][0],
5020 COLLADABU::Math::Utils::equalsZero(rotationMatrix[i][1], mDocumentExporter.getTolerance()) ? 0.0 : rotationMatrix[i][1],
5021 COLLADABU::Math::Utils::equalsZero(rotationMatrix[i][2], mDocumentExporter.getTolerance()) ? 0.0 : rotationMatrix[i][2]),
5022 COLLADABU::Math::Utils::equalsZero(rotationMatrix[i][3], mDocumentExporter.getTolerance()) ? 0.0 : rotationMatrix[i][3],
5023 sid + rotationParameters[i]
5024 );
5025 }
5026 }
5027 }
5028
exportAttributes(const MObject & object,const std::set<MString,MStringComp> & attributes)5029 void PhysXExporter::exportAttributes(const MObject & object, const std::set<MString, MStringComp> & attributes)
5030 {
5031 AttributeExporter attributeExporter(*this, attributes);
5032 MFnDependencyNode fnDependencyNode(object);
5033 AttributeParser::parseAttributes(fnDependencyNode, attributeExporter);
5034 }
5035
5036 namespace local
5037 {
5038 class ExtraAttributeExporter : public AttributeParser
5039 {
5040 public:
ExtraAttributeExporter(COLLADASW::StreamWriter & streamWriter,const MObject & obj)5041 ExtraAttributeExporter(COLLADASW::StreamWriter& streamWriter, const MObject & obj)
5042 : mStreamWriter(streamWriter)
5043 , mObject(obj)
5044 {}
5045
5046 private:
5047 COLLADASW::StreamWriter & mStreamWriter;
5048 MObject mObject;
5049
5050 protected:
onBeforePlug(MPlug & plug)5051 virtual bool onBeforePlug(MPlug & plug) override
5052 {
5053 MStatus status;
5054
5055 MObject attr = plug.attribute(&status);
5056 if (!status) return false;
5057
5058 MFnAttribute fnAttr(attr, &status);
5059 if (!status) return false;
5060
5061 MString attrName = fnAttr.name(&status);
5062 if (!status) return false;
5063
5064 bool isDynamic = fnAttr.isDynamic(&status);
5065 if (!status) return false;
5066
5067 if (!isDynamic)
5068 return false;
5069
5070 bool isHidden = fnAttr.isHidden(&status);
5071 if (!status) return false;
5072
5073 if (isHidden)
5074 return false;
5075
5076 return true;
5077 }
5078
5079 template<typename ValueType>
exportExtraAttribute(const String & name,const String & type,const ValueType & value)5080 void exportExtraAttribute(const String & name, const String & type, const ValueType & value)
5081 {
5082 mStreamWriter.openElement(CSWC::CSW_ELEMENT_PARAM);
5083 mStreamWriter.appendAttribute(CSWC::CSW_ATTRIBUTE_NAME, name);
5084 mStreamWriter.appendAttribute(CSWC::CSW_ATTRIBUTE_TYPE, type);
5085 mStreamWriter.appendValues(value);
5086 mStreamWriter.closeElement();
5087 }
5088
5089 template<typename ValueType>
exportExtraAttribute(const String & name,const String & type,const ValueType & value0,const ValueType & value1)5090 void exportExtraAttribute(const String & name, const String & type, const ValueType & value0, const ValueType & value1)
5091 {
5092 mStreamWriter.openElement(CSWC::CSW_ELEMENT_PARAM);
5093 mStreamWriter.appendAttribute(CSWC::CSW_ATTRIBUTE_NAME, name);
5094 mStreamWriter.appendAttribute(CSWC::CSW_ATTRIBUTE_TYPE, type);
5095 mStreamWriter.appendValues(value0, value1);
5096 mStreamWriter.closeElement();
5097 }
5098
5099 template<typename ValueType>
exportExtraAttribute(const String & name,const String & type,const ValueType & value0,const ValueType & value1,const ValueType & value2)5100 void exportExtraAttribute(const String & name, const String & type, const ValueType & value0, const ValueType & value1, const ValueType & value2)
5101 {
5102 mStreamWriter.openElement(CSWC::CSW_ELEMENT_PARAM);
5103 mStreamWriter.appendAttribute(CSWC::CSW_ATTRIBUTE_NAME, name);
5104 mStreamWriter.appendAttribute(CSWC::CSW_ATTRIBUTE_TYPE, type);
5105 mStreamWriter.appendValues(value0, value1, value2);
5106 mStreamWriter.closeElement();
5107 }
5108
5109 template<typename ValueType>
exportExtraAttribute(const String & name,const String & type,const ValueType & value0,const ValueType & value1,const ValueType & value2,const ValueType & value3)5110 void exportExtraAttribute(const String & name, const String & type, const ValueType & value0, const ValueType & value1, const ValueType & value2, const ValueType & value3)
5111 {
5112 mStreamWriter.openElement(CSWC::CSW_ELEMENT_PARAM);
5113 mStreamWriter.appendAttribute(CSWC::CSW_ATTRIBUTE_NAME, name);
5114 mStreamWriter.appendAttribute(CSWC::CSW_ATTRIBUTE_TYPE, type);
5115 mStreamWriter.appendValues(value0, value1, value2, value3);
5116 mStreamWriter.closeElement();
5117 }
5118
onBoolean(MPlug & plug,const MString & name,bool value)5119 virtual void onBoolean(MPlug & plug, const MString & name, bool value) override
5120 {
5121 exportExtraAttribute(name.asChar(), CSWC::CSW_VALUE_TYPE_BOOL, value);
5122 }
5123
onInteger(MPlug & plug,const MString & name,int value)5124 virtual void onInteger(MPlug & plug, const MString & name, int value) override
5125 {
5126 exportExtraAttribute(name.asChar(), CSWC::CSW_VALUE_TYPE_INT, value);
5127 }
5128
onInteger2(MPlug & plug,const MString & name,int value[2])5129 virtual void onInteger2(MPlug & plug, const MString & name, int value[2]) override
5130 {
5131 exportExtraAttribute(name.asChar(), CSWC::CSW_VALUE_TYPE_INT2, value[0], value[1]);
5132 }
5133
onInteger3(MPlug & plug,const MString & name,int value[3])5134 virtual void onInteger3(MPlug & plug, const MString & name, int value[3]) override
5135 {
5136 exportExtraAttribute(name.asChar(), CSWC::CSW_VALUE_TYPE_INT3, value[0], value[1], value[2]);
5137 }
5138
onFloat(MPlug & plug,const MString & name,float value)5139 virtual void onFloat(MPlug & plug, const MString & name, float value) override
5140 {
5141 exportExtraAttribute(name.asChar(), CSWC::CSW_VALUE_TYPE_FLOAT, value);
5142 }
5143
onFloat2(MPlug & plug,const MString & name,float value[2])5144 virtual void onFloat2(MPlug & plug, const MString & name, float value[2]) override
5145 {
5146 exportExtraAttribute(name.asChar(), CSWC::CSW_VALUE_TYPE_FLOAT2, value[0], value[1]);
5147 }
5148
onFloat3(MPlug & plug,const MString & name,float value[3])5149 virtual void onFloat3(MPlug & plug, const MString & name, float value[3]) override
5150 {
5151 exportExtraAttribute(name.asChar(), CSWC::CSW_VALUE_TYPE_FLOAT3, value[0], value[1], value[2]);
5152 }
5153
onDouble(MPlug & plug,const MString & name,double value)5154 virtual void onDouble(MPlug & plug, const MString & name, double value) override
5155 {
5156 exportExtraAttribute(name.asChar(), CSWC::CSW_VALUE_TYPE_DOUBLE, value);
5157 }
5158
onDouble2(MPlug & plug,const MString & name,double value[2])5159 virtual void onDouble2(MPlug & plug, const MString & name, double value[2]) override
5160 {
5161 exportExtraAttribute(name.asChar(), CSWC::CSW_VALUE_TYPE_DOUBLE2, value[0], value[1]);
5162 }
5163
onDouble3(MPlug & plug,const MString & name,double value[3])5164 virtual void onDouble3(MPlug & plug, const MString & name, double value[3]) override
5165 {
5166 exportExtraAttribute(name.asChar(), CSWC::CSW_VALUE_TYPE_DOUBLE3, value[0], value[1], value[2]);
5167 }
5168
onDouble4(MPlug & plug,const MString & name,double value[4])5169 virtual void onDouble4(MPlug & plug, const MString & name, double value[4]) override
5170 {
5171 exportExtraAttribute(name.asChar(), CSWC::CSW_VALUE_TYPE_DOUBLE4, value[0], value[1], value[2], value[3]);
5172 }
5173
onString(MPlug & plug,const MString & name,const MString & value)5174 virtual void onString(MPlug & plug, const MString & name, const MString & value) override
5175 {
5176 exportExtraAttribute(name.asChar(), CSWC::CSW_VALUE_TYPE_STRING, value.asChar());
5177 }
5178
onEnum(MPlug & plug,const MString & name,int enumValue,const MString & enumName)5179 virtual void onEnum(MPlug & plug, const MString & name, int enumValue, const MString & enumName) override
5180 {
5181 // TODO export all possible enum values to be able to re-import them?
5182 exportExtraAttribute(name.asChar(), CSWC::CSW_VALUE_TYPE_STRING, COLLADABU::StringUtils::translateToXML(String(enumName.asChar())));
5183 }
5184 };
5185 }
5186
exportExtraAttributes(const MObject & object)5187 void PhysXExporter::exportExtraAttributes(const MObject & object)
5188 {
5189 if (HasExtraAttributes(object))
5190 {
5191 local::ExtraAttributeExporter extraAttributeExporter(mStreamWriter, object);
5192 MFnDependencyNode node(object);
5193 AttributeParser::parseAttributes(node, extraAttributeExporter);
5194 }
5195 }
5196
exportRotate(const MVector & axis,double angle,const String & sid)5197 void PhysXExporter::exportRotate(const MVector & axis, double angle, const String & sid)
5198 {
5199 Rotate(*this, axis, angle, sid);
5200 }
5201
sceneHas(SceneElement::Type type,PhysXExporter::Filter filter)5202 bool PhysXExporter::sceneHas(SceneElement::Type type, PhysXExporter::Filter filter)
5203 {
5204 SceneGraph& sceneGraph = *mDocumentExporter.getSceneGraph();
5205 SceneElementsList& exportNodesTree = *sceneGraph.getExportNodesTree();
5206
5207 // Parse all/selected DAG nodes
5208 for (size_t i = 0; i < exportNodesTree.size(); ++i)
5209 {
5210 SceneElement& sceneElement = *exportNodesTree[i];
5211 if (ElementHas(sceneElement, type, filter)) {
5212 return true;
5213 }
5214 }
5215 return false;
5216 }
5217
ElementHas(const SceneElement & element,SceneElement::Type type,PhysXExporter::Filter filter)5218 bool PhysXExporter::ElementHas(const SceneElement & element, SceneElement::Type type, PhysXExporter::Filter filter)
5219 {
5220 if (element.getType() == type) {
5221 switch (filter)
5222 {
5223 case All:
5224 return true;
5225 case Local:
5226 return element.getIsLocal();
5227 case Reference:
5228 return !element.getIsLocal();
5229 }
5230 }
5231
5232 // Recursive call for all the child elements
5233 for (uint i = 0; i<element.getChildCount(); ++i)
5234 {
5235 const SceneElement& childElement = *element.getChild(i);
5236 if (ElementHas(childElement, type, filter)) {
5237 return true;
5238 }
5239 }
5240 return false;
5241 }
5242
generateColladaId(const MDagPath & dagPath)5243 String PhysXExporter::generateColladaId(const MDagPath & dagPath)
5244 {
5245 // Get the maya mesh id.
5246 String mayaId = mDocumentExporter.dagPathToColladaId(dagPath);
5247
5248 // Generate a COLLADA id for the new object.
5249 String colladaId = findColladaId(mayaId);
5250
5251 // Check, if the unique id for the current geometry is already generated.
5252 if (!colladaId.empty()) return colladaId;
5253
5254 // Get the node of the current mesh
5255 colladaId = mDocumentExporter.dagPathToColladaName(dagPath);
5256
5257 // Make the id unique and store it in a map.
5258 colladaId = mIdList.addId(colladaId);
5259 mMayaIdToColladaId[mayaId] = colladaId;
5260
5261 return colladaId;
5262 }
5263
generateColladaName(const MDagPath & dagPath)5264 String PhysXExporter::generateColladaName(const MDagPath & dagPath)
5265 {
5266 return mDocumentExporter.dagPathToColladaName(dagPath);
5267 }
5268
GetDefaultPhysicsModelId()5269 const String& PhysXExporter::GetDefaultPhysicsModelId()
5270 {
5271 return mDefaultPhysicsModelId;
5272 }
5273
GetDefaultPhysicsSceneId()5274 const String& PhysXExporter::GetDefaultPhysicsSceneId()
5275 {
5276 return mDefaultPhysicsSceneId;
5277 }
5278
GetDefaultInstancePhysicsModelSid()5279 const String& PhysXExporter::GetDefaultInstancePhysicsModelSid()
5280 {
5281 return mDefaultInstancePhysicsModelSid;
5282 }
5283
GetPhysXProfile()5284 const String & PhysXExporter::GetPhysXProfile()
5285 {
5286 return mPhysXProfile;
5287 }
5288
GetXMLNS()5289 const String& PhysXExporter::GetXMLNS()
5290 {
5291 return mXMLNS;
5292 }
5293
GetXSISchemaLocation()5294 String PhysXExporter::GetXSISchemaLocation()
5295 {
5296 return mXMLNS + " " + mSchemaLocation;
5297 }
5298
5299 namespace local
5300 {
5301 class ExtraAttributeParser : public AttributeParser
5302 {
5303 public:
ExtraAttributeParser(const MObject & obj)5304 ExtraAttributeParser(const MObject & obj)
5305 : mHasExtraAttributes(false)
5306 {}
5307
hasExtraAttributes() const5308 bool hasExtraAttributes() const { return mHasExtraAttributes; }
5309
5310 private:
5311 bool mHasExtraAttributes;
5312
5313 protected:
onBeforePlug(MPlug & plug)5314 virtual bool onBeforePlug(MPlug & plug) override
5315 {
5316 MStatus status;
5317
5318 MObject attr = plug.attribute(&status);
5319 if (!status) return false;
5320
5321 MFnAttribute fnAttr(attr, &status);
5322 if (!status) return false;
5323
5324 MString attrName = fnAttr.name(&status);
5325 if (!status) return false;
5326
5327 bool isDynamic = fnAttr.isDynamic(&status);
5328 if (!status) return false;
5329
5330 if (!isDynamic)
5331 return false;
5332
5333 bool isHidden = fnAttr.isHidden(&status);
5334 if (!status) return false;
5335
5336 if (isHidden)
5337 return false;
5338
5339 mHasExtraAttributes = true;
5340
5341 // No need to continue parsing
5342 return false;
5343 }
5344 };
5345 }
5346
HasExtraAttributes(const MObject & object)5347 bool PhysXExporter::HasExtraAttributes(const MObject & object)
5348 {
5349 local::ExtraAttributeParser parser(object);
5350 MFnDependencyNode node(object);
5351 AttributeParser::parseAttributes(node, parser);
5352 return parser.hasExtraAttributes();
5353 }
5354
CombineModeToCOLLADA(PhysXXML::CombineMode::FlagEnum flag)5355 String PhysXExporter::CombineModeToCOLLADA(PhysXXML::CombineMode::FlagEnum flag)
5356 {
5357 return FlagsToCOLLADA(Flags<PhysXXML::CombineMode::FlagEnum>(flag), PhysXXML::CombineMode::GetFlagToStringMap());
5358 }
5359
ShapeFlagsToCOLLADA(const Flags<PhysXXML::ShapeFlags::FlagEnum> & flags)5360 String PhysXExporter::ShapeFlagsToCOLLADA(const Flags<PhysXXML::ShapeFlags::FlagEnum> & flags)
5361 {
5362 return FlagsToCOLLADA(flags, PhysXXML::ShapeFlags::GetFlagToStringMap());
5363 }
5364
ActorFlagsToCOLLADA(const Flags<PhysXXML::ActorFlags::FlagEnum> & flags)5365 String PhysXExporter::ActorFlagsToCOLLADA(const Flags<PhysXXML::ActorFlags::FlagEnum> & flags)
5366 {
5367 return FlagsToCOLLADA(flags, PhysXXML::ActorFlags::GetFlagToStringMap());
5368 }
5369
RigidBodyFlagsToCOLLADA(const Flags<PhysXXML::RigidBodyFlags::FlagEnum> & flags)5370 String PhysXExporter::RigidBodyFlagsToCOLLADA(const Flags<PhysXXML::RigidBodyFlags::FlagEnum> & flags)
5371 {
5372 return FlagsToCOLLADA(flags, PhysXXML::RigidBodyFlags::GetFlagToStringMap());
5373 }
5374
ConstraintFlagsToCOLLADA(const Flags<PhysXXML::ConstraintFlags::FlagEnum> & flags)5375 String PhysXExporter::ConstraintFlagsToCOLLADA(const Flags<PhysXXML::ConstraintFlags::FlagEnum> & flags)
5376 {
5377 return FlagsToCOLLADA(flags, PhysXXML::ConstraintFlags::GetFlagToStringMap());
5378 }
5379
DriveFlagsToCOLLADA(const Flags<PhysXXML::DriveFlags::FlagEnum> & flags)5380 String PhysXExporter::DriveFlagsToCOLLADA(const Flags<PhysXXML::DriveFlags::FlagEnum> & flags)
5381 {
5382 return FlagsToCOLLADA(flags, PhysXXML::DriveFlags::GetFlagToStringMap());
5383 }
5384
findColladaId(const String & mayaId)5385 const String & PhysXExporter::findColladaId(const String & mayaId)
5386 {
5387 const StringToStringMap::const_iterator it = mMayaIdToColladaId.find(mayaId);
5388 if (it != mMayaIdToColladaId.end()) {
5389 return it->second;
5390 }
5391 return EMPTY_STRING;
5392 }
5393
GetRigidBodyTargetTM(const MObject & rigidBody)5394 MMatrix PhysXExporter::GetRigidBodyTargetTM(const MObject& rigidBody)
5395 {
5396 MObject target = GetRigidBodyTarget(rigidBody);
5397 MDagPath targetDagPath;
5398 MDagPath::getAPathTo(target, targetDagPath);
5399 return targetDagPath.inclusiveMatrix();
5400 }
5401
GetRigidBodyTarget(const MObject & rigidBody)5402 MObject PhysXExporter::GetRigidBodyTarget(const MObject& rigidBody)
5403 {
5404 MObject target;
5405 PhysXExporter::GetPluggedObject(rigidBody, ATTR_TARGET, target);
5406
5407 // If target is null then use rigidBody as target
5408 if (target.isNull())
5409 {
5410 target = rigidBody;
5411 }
5412 return target;
5413 }
5414
GetRigidBodyShapes(const MObject & rigidBody,std::vector<MObject> & shapes)5415 void PhysXExporter::GetRigidBodyShapes(const MObject & rigidBody, std::vector<MObject> & shapes)
5416 {
5417 MFnDependencyNode rigidBodyNode(rigidBody);
5418 MPlug plug = rigidBodyNode.findPlug(ATTR_PHYSICS_SHAPES);
5419 uint numConnectedElements = plug.numConnectedElements();
5420
5421 for (uint i = 0; i < numConnectedElements; ++i)
5422 {
5423 MPlug elementPlug = plug.connectionByPhysicalIndex(i);
5424 MPlugArray connections;
5425 if (elementPlug.connectedTo(connections, true, false))
5426 {
5427 shapes.push_back(connections[0].node());
5428 }
5429 }
5430 }
5431
5432 // in kg
GetRigidBodyMass(const MObject & rigidBody)5433 double PhysXExporter::GetRigidBodyMass(const MObject & rigidBody)
5434 {
5435 int dummy = 0;
5436 MString overrideMassOrDensity;
5437 DagHelper::getPlugValue(rigidBody, ATTR_OVERRIDE_MASS_OR_DENSITY, dummy, overrideMassOrDensity);
5438
5439 double mass = 0.0;
5440 if (overrideMassOrDensity == OVERRIDE_MASS_OR_DENSITY_MASS)
5441 {
5442 // Mass attribute is in kg
5443 DagHelper::getPlugValue(rigidBody, ATTR_MASS, mass);
5444 }
5445 else if (overrideMassOrDensity == OVERRIDE_MASS_OR_DENSITY_DENSITY)
5446 {
5447 // Density attribute is in g/cm3
5448 double density = 0.0;
5449 DagHelper::getPlugValue(rigidBody, ATTR_DENSITY, density);
5450 // Volume in cm3
5451 mass = density * GetRigidBodyVolume(rigidBody);
5452 // Convert g to kg
5453 mass /= 1000.0;
5454 }
5455 else //if (overrideMassOrDensity == OVERRIDE_MASS_OR_DENSITY_DISABLED)
5456 {
5457 std::vector<MObject> shapes;
5458 GetRigidBodyShapes(rigidBody, shapes);
5459 for (size_t i = 0; i < shapes.size(); ++i)
5460 {
5461 mass += GetShapeMass(shapes[i]);
5462 }
5463 }
5464 return mass;
5465 }
5466
5467 // in kg
GetShapeMass(const MObject & shape)5468 double PhysXExporter::GetShapeMass(const MObject & shape)
5469 {
5470 int dummy = 0;
5471 MString useMassOrDensity;
5472 DagHelper::getPlugValue(shape, ATTR_USE_MASS_OR_DENSITY, dummy, useMassOrDensity);
5473
5474 double mass = 0.0;
5475 if (useMassOrDensity == USE_MASS_OR_DENSITY_MASS)
5476 {
5477 // Mass in kg
5478 DagHelper::getPlugValue(shape, ATTR_MASS, mass);
5479 }
5480 else //if (useMassOrDensity == USE_MASS_OR_DENSITY_DENSITY)
5481 {
5482 // Density in g/cm3
5483 double density = 0.0;
5484 DagHelper::getPlugValue(shape, ATTR_DENSITY, density);
5485 mass = density * GetShapeVolume(shape);
5486 // Convert g to kg
5487 mass /= 1000.0;
5488 }
5489
5490 return mass;
5491 }
5492
5493 // cm3
GetRigidBodyVolume(const MObject & rigidBody)5494 double PhysXExporter::GetRigidBodyVolume(const MObject & rigidBody)
5495 {
5496 std::vector<MObject> shapes;
5497 GetRigidBodyShapes(rigidBody, shapes);
5498 double volume = 0.0;
5499 for (size_t i = 0; i < shapes.size(); ++i)
5500 {
5501 volume += GetShapeVolume(shapes[i]);
5502 }
5503 return volume;
5504 }
5505
5506 // cm3
GetShapeVolume(const MObject & shape)5507 double PhysXExporter::GetShapeVolume(const MObject & shape)
5508 {
5509 int dummy = 0;
5510 MString shapeType;
5511 DagHelper::getPlugValue(shape, ATTR_SHAPE_TYPE, dummy, shapeType);
5512
5513 double volume = 0.0;
5514
5515 if (shapeType == SHAPE_TYPE_BOX)
5516 {
5517 MVector size = MVector::zero;
5518 DagHelper::getPlugValue(shape, ATTR_SIZE, size);
5519 volume = size.x * size.y * size.z;
5520 }
5521 else if (shapeType == SHAPE_TYPE_CAPSULE)
5522 {
5523 double radius = 0.0;
5524 double height = 0.0;
5525 DagHelper::getPlugValue(shape, ATTR_RADIUS, radius);
5526 DagHelper::getPlugValue(shape, ATTR_HEIGHT, height);
5527 volume = M_PI * radius * radius * (4.0 / 3.0 * radius + height);
5528 }
5529 else if (
5530 shapeType == SHAPE_TYPE_CLOTH_SPHERES ||
5531 shapeType == SHAPE_TYPE_SPHERE
5532 )
5533 {
5534 double radius = 0.0;
5535 DagHelper::getPlugValue(shape, ATTR_RADIUS, radius);
5536 volume = 4.0 / 3.0 * M_PI * radius * radius * radius;
5537 }
5538 else if (shapeType == SHAPE_TYPE_CONVEX_HULL)
5539 {
5540 // Get convex mesh (not connected mesh)
5541 MObject mesh;
5542 PhysXShape::GetInMesh(shape, mesh);
5543
5544 // Parse triangles
5545 MItMeshPolygon itMeshPolygon(mesh);
5546 for (itMeshPolygon.reset(); !itMeshPolygon.isDone(); itMeshPolygon.next())
5547 {
5548 int numTriangles = 0;
5549 itMeshPolygon.numTriangles(numTriangles);
5550 for (int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex)
5551 {
5552 MPointArray vertexList;
5553 MIntArray vertexIndexList;
5554 itMeshPolygon.getTriangle(triangleIndex, vertexList, vertexIndexList);
5555
5556 MPoint a, b, c;
5557 a = vertexList[0];
5558 b = vertexList[1];
5559 c = vertexList[2];
5560
5561 MVector vab, vbc, vca;
5562 vab = b - a;
5563 vbc = c - b;
5564 vca = a - c;
5565 double ab, bc, ca;
5566 ab = vab.length();
5567 bc = vbc.length();
5568 ca = vca.length();
5569 // Use Heron's formula to calculate triangular pyramid signed volume
5570 // base triangle perimeter
5571 double p = 0.5 * (ab + bc + ca);
5572 // base triangle area
5573 double area = sqrt(p * (p-ab) * (p-bc) * (p-ca));
5574 MVector vac;
5575 vac = c - a;
5576 // triangle plane normal
5577 MVector n = vab ^ vac;
5578 n.normalize();
5579 // triangle plane equation constant
5580 double d = -a.x*n.x - a.y*n.y - a.z*n.z;
5581 // pyramid height
5582 double h = d;
5583 // pyramid volume
5584 double subVolume = 1.0/3.0 * area * h;
5585 subVolume *= -1;
5586 // add to total volume
5587 volume += subVolume;
5588 }
5589 }
5590 }
5591 else
5592 {
5593 MVector bbSize = MVector::zero;
5594 DagHelper::getPlugValue(shape, ATTR_BOUNDING_BOX_SIZE, bbSize);
5595 volume = bbSize.x * bbSize.y * bbSize.z;
5596 }
5597
5598 return volume;
5599 }
5600
GetPluggedObject(const MObject & object,const MString & attribute,MObject & pluggedObject)5601 MStatus PhysXExporter::GetPluggedObject(const MObject & object, const MString & attribute, MObject & pluggedObject)
5602 {
5603 MStatus status;
5604
5605 MFnDependencyNode node(object, &status);
5606 if (!status) return status;
5607
5608 MPlug plug = node.findPlug(attribute, &status);
5609 if (!status) return status;
5610
5611 MPlugArray plugArray;
5612 bool hasConnection = plug.connectedTo(plugArray, true, false, &status);
5613 if (!status) return status;
5614 if (hasConnection)
5615 {
5616 MPlug externalPlug = plugArray[0];
5617 bool externalPlugNull = externalPlug.isNull(&status);
5618 if (!status) return status;
5619 if (!externalPlugNull)
5620 {
5621 pluggedObject = externalPlug.node(&status);
5622 if (!status) return status;
5623 }
5624 }
5625 return MS::kSuccess;
5626 }
5627
getMeshURI(const MObject & mesh,URI & meshURI)5628 MStatus PhysXExporter::getMeshURI(const MObject & mesh, URI & meshURI)
5629 {
5630 MStatus status;
5631
5632 MFnDagNode meshDagNode(mesh, &status);
5633 if (!status) return status;
5634
5635 MDagPath meshDagPath;
5636 status = meshDagNode.getPath(meshDagPath);
5637 if (!status) return status;
5638
5639 String geometryId = mDocumentExporter.getGeometryExporter()->generateColladaMeshId(meshDagPath);
5640 meshURI = getDocumentExporter().getVisualSceneExporter()->getSceneElementURI(meshDagPath, geometryId);
5641
5642 return status;
5643 }
5644 }
5645