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 #ifndef __COLLADA_MAYA_PHYSX_EXPORTER_H__
16 #define __COLLADA_MAYA_PHYSX_EXPORTER_H__
17 
18 #include "COLLADAMayaDocumentExporter.h"
19 #include "COLLADAMayaPhysXXML.h"
20 #include "COLLADAMayaSceneElement.h"
21 #include "COLLADAMayaSceneGraph.h"
22 #include "COLLADASWLibraryPhysicsModels.h"
23 
24 template<>
25 class std::less <MObject>
26 {
27 public:
operator()28 	bool operator()(const MObject & l, const MObject & r) const
29 	{
30 		const int* pl = *reinterpret_cast<const int* const*>(&l);
31 		const int* pr = *reinterpret_cast<const int* const*>(&r);
32 		return pl < pr;
33 	}
34 };
35 
36 namespace COLLADAMaya
37 {
38     // Unit for mass: kg
39     // Unit for density: g/cm3
40 
41     class MStringComp
42     {
43     public:
operator()44         bool operator()(const MString & a, const MString & b) const
45         {
46             return strcmp(a.asChar(), b.asChar()) < 0;
47         }
48     };
49 
50     class PhysXShape
51     {
52     public:
53         static void GetType(const MObject & shape, MString & type);
54         static void GetInMesh(const MObject & shape, MObject & mesh);
55         static void GetConnectedInMesh(const MObject & shape, MObject & mesh);
56     };
57 
58 	class PhysXExporter
59     {
60     public:
61         PhysXExporter(COLLADASW::StreamWriter& streamWriter, DocumentExporter& documentExporter);
62 
63         static bool CheckPhysXPluginVersion();
64         static MString GetRequiredPhysXPluginVersion();
65         static MString GetInstalledPhysXPluginVersion();
66 
67         bool generatePhysXXML();
68         bool needsConvexHullOf(const SceneElement & element, MObject & shape);
69         bool exportPhysicsLibraries();
70 
71         COLLADASW::StreamWriter& getStreamWriter();
72         DocumentExporter& getDocumentExporter();
73 
74 		void exportTranslationWithoutConversion(const MVector & translation, const String & sid = "");
75         void exportTranslation(const MVector & translation, const String & sid = "");
76         void exportRotation(const MEulerRotation & rotation, const String & sid = "");
77         void exportAttributes(const MObject & object, const std::set<MString, MStringComp> & attributes);
78         void exportExtraAttributes(const MObject & object);
79 
80 		const MObject & getNodeRigidBody(const MObject& node) const;
81         void getShapeLocalPose(const MObject& shape, MMatrix& localPose) const;
82         bool getShapeVertices(const MObject& shape, std::vector<PhysXXML::Point> & vertices, MString & meshId);
83         bool getShapeTriangles(const MObject& shape, std::vector<PhysXXML::Triangle> & triangles);
84         void getRigidBodyGlobalPose(const MObject& rigidBody, MMatrix& globalPose);
85         const MObject & getRigidSolver() const;
86 
87         MStatus getMeshURI(const MObject & mesh, URI & meshURI);
88 
89         String generateColladaId(const MDagPath & dagPath);
90         String generateColladaName(const MDagPath & dagPath);
91 
92         // Stop parsing if callback returns false
93         template<class T>
parseSceneElements(T & callbackObject)94         void parseSceneElements(T & callbackObject)
95         {
96             SceneGraph& sceneGraph = *mDocumentExporter.getSceneGraph();
97             SceneElementsList& exportNodesTree = *sceneGraph.getExportNodesTree();
98 
99             // Export all/selected DAG nodes
100             for (size_t i = 0; i < exportNodesTree.size(); ++i)
101             {
102                 SceneElement& sceneElement = *exportNodesTree[i];
103                 if (!parseSceneElement(sceneElement, callbackObject))
104                 {
105                     return;
106                 }
107             }
108         }
109 
110         // in kg
111         static double GetRigidBodyMass(const MObject & rigidBody);
112         static double GetShapeMass(const MObject & shape);
113 
114         // in cm3
115         static double GetRigidBodyVolume(const MObject & rigidBody);
116         static double GetShapeVolume(const MObject & shape);
117 
118 		static MMatrix GetRigidBodyTargetTM(const MObject& rigidBody);
119 		static MObject GetRigidBodyTarget(const MObject& rigidBody);
120         static void GetRigidBodyShapes(const MObject & rigidBody, std::vector<MObject> & shapes);
121         static MStatus GetPluggedObject(const MObject & object, const MString & attribute, MObject & pluggedObject);
122 
123         static const String& GetDefaultPhysicsModelId();
124         static const String& GetDefaultPhysicsSceneId();
125         static const String& GetDefaultInstancePhysicsModelSid();
126 		static const String& GetPhysXProfile();
127 		static const String& GetXMLNS();
128 		static String GetXSISchemaLocation();
129 
130 		static bool HasExtraAttributes(const MObject & object);
131 
132 		// Convert PhysX enum to COLLADA string
133 		static String CombineModeToCOLLADA(PhysXXML::CombineMode::FlagEnum flag);
134 		static String ShapeFlagsToCOLLADA(const Flags<PhysXXML::ShapeFlags::FlagEnum> & flags);
135 		static String ActorFlagsToCOLLADA(const Flags<PhysXXML::ActorFlags::FlagEnum> & flags);
136 		static String RigidBodyFlagsToCOLLADA(const Flags<PhysXXML::RigidBodyFlags::FlagEnum> & flags);
137 		static String ConstraintFlagsToCOLLADA(const Flags<PhysXXML::ConstraintFlags::FlagEnum> & flags);
138 		static String DriveFlagsToCOLLADA(const Flags<PhysXXML::DriveFlags::FlagEnum> & flags);
139 
140         enum Filter
141         {
142             All,
143             Local,
144             Reference
145         };
146         bool sceneHas(SceneElement::Type type, Filter filter = All);
147 
148 		const PhysXXML::PxRigidBody* findPxRigidBody(const MObject & rigidBody) const;
149 		const PhysXXML::PxRigidBody* findPxRigidBody(const String & name) const;
150 		const PhysXXML::PxRigidBody* findPxRigidBody(uint64_t id) const;
151 		const PhysXXML::PxMaterial* findPxMaterial(uint64_t ref) const;
152 		const PhysXXML::PxMaterial* findPxMaterial(const PhysXXML::PxRigidBody & rigidBody) const;
153 		const PhysXXML::PxMaterial* findPxMaterial(const MObject & rigidBody) const;
154 		const PhysXXML::PxShape* findPxShape(const MObject & shape) const;
155 		const PhysXXML::PxD6Joint* findPxD6Joint(const MObject & rigidConstraint) const;
156 
157 		const MObject & findMObject(const PhysXXML::PxRigidBody & rigidBody) const;
158 		const MObject & findMObject(const PhysXXML::PxShape & shape) const;
159 		const MObject & findMObject(const PhysXXML::PxD6Joint & joint) const;
160 
161     private:
162         void exportRotate(const MVector & axis, double angle, const String & sid = "");
163 
164         static bool ElementHas(const SceneElement & element, SceneElement::Type type, Filter filter);
165 
166         const String & findColladaId(const String & mayaId);
167 
168         template<class T>
parseSceneElement(SceneElement & element,T & callbackObject)169         bool parseSceneElement(SceneElement& element, T & callbackObject)
170         {
171             if (!callbackObject(element))
172             {
173                 return false;
174             }
175 
176             // Recursive call for all the child elements
177             for (uint i = 0; i<element.getChildCount(); ++i)
178             {
179                 SceneElement& childElement = *element.getChild(i);
180                 if (!parseSceneElement(childElement, callbackObject))
181                 {
182                     return false;
183                 }
184             }
185 
186             return true;
187 		}
188 
189 		template<typename E>
FlagsToCOLLADA(const Flags<E> & flags,const std::map<E,String> & flagToStringMap)190 		static String FlagsToCOLLADA(const Flags<E> & flags, const std::map<E, String> & flagToStringMap)
191 		{
192 			String colladaFlags;
193 			for (int i = 0; i < 32; ++i)
194 			{
195 				E flag = static_cast<E>(1 << i);
196 				if (flags & flag)
197 				{
198 					typename std::map<E, String>::const_iterator it = flagToStringMap.find(flag);
199 					if (!colladaFlags.empty())
200 						colladaFlags += ' ';
201 					colladaFlags += it->second.substr(1);
202 				}
203 			}
204 			return colladaFlags;
205 		}
206 
207     private:
208         COLLADASW::StreamWriter& mStreamWriter;
209         DocumentExporter& mDocumentExporter;
210         COLLADABU::IDList mIdList;
211         StringToStringMap mMayaIdToColladaId;
212         PhysXXML::PhysXDocPtr mPhysXDoc;
213 
214 		std::map<MObject, const PhysXXML::PxMaterial*> mRigidBodyToPxMaterialMap;
215 		std::map<const PhysXXML::PxRigidBody*, MObject> mPxRigidBodyToRigidBodyMap;
216 		std::map<MObject, const PhysXXML::PxRigidBody*> mRigidBodyToPxRigidBodyMap;
217 		std::map<const PhysXXML::PxShape*, MObject> mPxShapeToShapeMap;
218 		std::map<MObject, const PhysXXML::PxShape*> mShapeToPxShapeMap;
219 		std::map<const PhysXXML::PxD6Joint*, MObject> mPxD6JointToConstraintMap;
220 		std::map<MObject, const PhysXXML::PxD6Joint*> mConstraintToPxD6JointMap;
221 		std::map<MObject, MObject> mTargetToRigidBodyMap;
222 		MObject mRigidSolver;
223 
224         static String mDefaultPhysicsModelId;
225         static String mDefaultPhysicsSceneId;
226         static String mDefaultInstancePhysicsModelSid;
227 		static String mPhysXProfile;
228 		static String mXMLNS;
229 		static String mSchemaLocation;
230 
231 		friend class PhysicsExportPrePass;
232     };
233 }
234 
235 #endif //__COLLADA_MAYA_PHYSX_EXPORTER_H__
236