OptimizeGraphProcess.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /*
  2. Open Asset Import Library (ASSIMP)
  3. ----------------------------------------------------------------------
  4. Copyright (c) 2006-2008, ASSIMP Development Team
  5. All rights reserved.
  6. Redistribution and use of this software in source and binary forms,
  7. with or without modification, are permitted provided that the
  8. following conditions are met:
  9. * Redistributions of source code must retain the above
  10. copyright notice, this list of conditions and the
  11. following disclaimer.
  12. * Redistributions in binary form must reproduce the above
  13. copyright notice, this list of conditions and the
  14. following disclaimer in the documentation and/or other
  15. materials provided with the distribution.
  16. * Neither the name of the ASSIMP team, nor the names of its
  17. contributors may be used to endorse or promote products
  18. derived from this software without specific prior
  19. written permission of the ASSIMP Development Team.
  20. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. ----------------------------------------------------------------------
  32. */
  33. /** Defines a post processing step to refactor the output node graph to
  34. be more compact */
  35. #ifndef AI_OPTIMIZEGRAPHPROCESS_H_INC
  36. #define AI_OPTIMIZEGRAPHPROCESS_H_INC
  37. #include "BaseProcess.h"
  38. struct aiMesh;
  39. struct aiNode;
  40. struct aiBone;
  41. class OptimizeGraphProcessTest;
  42. namespace Assimp {
  43. // NOTE: If you change these limits, don't forget to change the
  44. // corresponding values in all Assimp ports
  45. // **********************************************************
  46. // Java: ConfigProperty.java,
  47. // ConfigProperty.OG_MAX_HIERARCHY_DEPTH
  48. // ConfigProperty.OG_MIN_NUM_FACES
  49. // ConfigProperty.JOIN_INEQUAL_TRANSFORMS
  50. // **********************************************************
  51. #if (!defined AI_OG_MAX_DEPTH)
  52. # define AI_OG_MAX_DEPTH 0x4
  53. #endif // !! AI_LMW_MAX_WEIGHTS
  54. #if (!defined AI_OG_MIN_NUM_FACES)
  55. # define AI_OG_MIN_NUM_FACES 0xffffffff
  56. #endif // !! AI_LMW_MAX_WEIGHTS
  57. #if (!defined AI_OG_REMOVE_ANIMATIONS)
  58. # define AI_OG_REMOVE_ANIMATIONS false
  59. #endif // !! AI_LMW_MAX_WEIGHTS
  60. #if (!defined AI_OG_JOIN_INEQUAL_TRANSFORMS)
  61. # define AI_OG_JOIN_INEQUAL_TRANSFORMS false
  62. #endif // !! AI_LMW_MAX_WEIGHTS
  63. // ---------------------------------------------------------------------------
  64. struct NodeIndexEntry : public std::pair<unsigned int, unsigned int>
  65. {
  66. // binary operator < for use with std::sort
  67. bool operator< (const NodeIndexEntry& other)
  68. {
  69. return second < other.second;
  70. }
  71. // pointer to the original node
  72. aiNode* pNode;
  73. };
  74. typedef std::vector<NodeIndexEntry> NodeIndexList;
  75. typedef std::pair<aiBone*,unsigned int> BoneSrcIndex;
  76. // ---------------------------------------------------------------------------
  77. struct BoneWithHash : public std::pair<uint32_t,aiString*>
  78. {
  79. std::vector<BoneSrcIndex> pSrcBones;
  80. };
  81. // ---------------------------------------------------------------------------
  82. /** This post processing step reformats the output node graph to be more
  83. * compact. There are several options, e.g. maximum hierachy depth or
  84. * minimum mesh size. Some files store every face as a new mesh, so
  85. * some Assimp steps (such as FixInfacingNormals or SmoothNormals) don't
  86. * work properly on these meshes. This step joins such small meshes and
  87. * nodes. Animations are kept during the step.
  88. * @note Use the PretransformVertices step to remove the node graph
  89. * completely (and all animations, too).
  90. */
  91. class ASSIMP_API OptimizeGraphProcess : public BaseProcess
  92. {
  93. friend class Importer;
  94. friend class ::OptimizeGraphProcessTest;
  95. protected:
  96. /** Constructor to be privately used by Importer */
  97. OptimizeGraphProcess();
  98. /** Destructor, private as well */
  99. ~OptimizeGraphProcess();
  100. typedef std::pair< unsigned int, aiNode* > MeshRefCount;
  101. typedef unsigned int MeshHash;
  102. public:
  103. // -------------------------------------------------------------------
  104. /** Returns whether the processing step is present in the given flag.
  105. * @param pFlags The processing flags the importer was called with.
  106. * A bitwise combination of #aiPostProcessSteps.
  107. * @return true if the process is present in this flag fields,
  108. * false if not.
  109. */
  110. bool IsActive( unsigned int pFlags) const;
  111. // -------------------------------------------------------------------
  112. /** Called prior to ExecuteOnScene().
  113. * The function is a request to the process to update its configuration
  114. * basing on the Importer's configuration property list.
  115. */
  116. void SetupProperties(const Importer* pImp);
  117. // set the configMinNumfaces property
  118. inline void SetMinNumFaces(unsigned int n)
  119. {
  120. configMinNumFaces = n;
  121. }
  122. // set the configRemoveAnimations property
  123. inline void SetRemoveAnimations(bool b)
  124. {
  125. configRemoveAnimations = b;
  126. }
  127. protected:
  128. // -------------------------------------------------------------------
  129. /** Executes the post processing step on the given imported data.
  130. * At the moment a process is not supposed to fail.
  131. * @param pScene The imported data to work at.
  132. */
  133. void Execute( aiScene* pScene);
  134. // -------------------------------------------------------------------
  135. /** Removes animation nodes from the tree.
  136. * @param node Current node
  137. * @param out Receives a list of replacement nodes for *this* node -
  138. * if *this* node should be kept, it must be added to the list.
  139. */
  140. void RemoveAnimationNodes (aiNode* node,std::vector<aiNode*>& out);
  141. // -------------------------------------------------------------------
  142. /** Entry point to the RemoveAnimationNodes algorithm.
  143. * @param node Root node to start with
  144. * @return New root node
  145. */
  146. aiNode* RemoveAnimationNodes (aiNode* node);
  147. // -------------------------------------------------------------------
  148. /** Finds and marks all locked nodes in the tree.
  149. * A node is locked if it is referenced by animations.
  150. * @param node ROot node to start with
  151. * @note A locked node has the MSB set in its mNumChildren member
  152. */
  153. void FindLockedNodes(aiNode* node);
  154. // -------------------------------------------------------------------
  155. /** Searches for locked meshes. A mesh is locked if it is referenced
  156. * by more than one node in the hierarchy.
  157. * @param node Root node to start with
  158. */
  159. void FindLockedMeshes(aiNode* node);
  160. void FindLockedMeshes(aiNode* node, MeshRefCount* pRefCount);
  161. // -------------------------------------------------------------------
  162. /** Unlocks all nodes in the output tree.
  163. * @param node Root node to start with
  164. */
  165. void UnlockNodes(aiNode* node);
  166. // -------------------------------------------------------------------
  167. /** Unlocks all meshes in the output tree.
  168. */
  169. void UnlockMeshes();
  170. // -------------------------------------------------------------------
  171. /** Apply the final optimization algorithm to the tree.
  172. * See the Execute-method for a detailled description of the algorithm.
  173. * @param node Root node to start with
  174. */
  175. void ApplyOptimizations(aiNode* node);
  176. // -------------------------------------------------------------------
  177. /** Binary search for the first element that is >= min.
  178. * @param sortedArray Input array
  179. * @param min Treshold
  180. */
  181. unsigned int BinarySearch(NodeIndexList& sortedArray,
  182. unsigned int min, unsigned int& index, unsigned int iStart);
  183. // -------------------------------------------------------------------
  184. /** Compute stable hashes for all meshes and fill mMeshHashes
  185. * with the results.
  186. */
  187. void ComputeMeshHashes();
  188. // -------------------------------------------------------------------
  189. /** Optimizes the meshes in a single node aftr the joining process.
  190. * @param pNode Node to be optimized. Childs noded won't be processed
  191. * automatically.
  192. */
  193. void ApplyNodeMeshesOptimization(aiNode* pNode);
  194. // -------------------------------------------------------------------
  195. /** Join meshes.
  196. * The output meshes are deleted afterwards.
  197. * @param meshList List of meshes to be joined
  198. * @param out Receives a pointer to the output mesh.
  199. */
  200. void JoinMeshes(std::vector<aiMesh*>& meshList,aiMesh*& out,
  201. unsigned int max);
  202. // -------------------------------------------------------------------
  203. /** Join bones from a collection of meshes.
  204. *
  205. * @param it First mesh to be processed
  206. * @param end Last mesh to be processed
  207. * @param out Valid output mesh to receive the output bone list.
  208. */
  209. void JoinBones(std::vector<aiMesh*>::const_iterator it,
  210. std::vector<aiMesh*>::const_iterator end,
  211. aiMesh* out);
  212. // -------------------------------------------------------------------
  213. /** Build a list of unique bones from a collection of meshes.
  214. *
  215. * @param it First mesh to be processed
  216. * @param end Last mesh to be processed
  217. * @param asBones Receives a list of unique bones
  218. */
  219. void BuildUniqueBoneList(std::vector<aiMesh*>::const_iterator it,
  220. std::vector<aiMesh*>::const_iterator end,
  221. std::list<BoneWithHash>& asBones);
  222. // -------------------------------------------------------------------
  223. /** Build the output mesh list.
  224. */
  225. void BuildOutputMeshList();
  226. // -------------------------------------------------------------------
  227. /** Transform meshes from one coordinate space into another.
  228. * @param quak Input space. All meshes referenced by this node -
  229. * assuming none of them is locked - are transformed in the
  230. * local coordinate space of pNode
  231. * @param pNode Destination coordinate space
  232. */
  233. void TransformMeshes(aiNode* quak,aiNode* pNode);
  234. private:
  235. /** Configuration option: specifies the minimum number of faces
  236. a node should have. The steps tries to join meshes with less
  237. vertices that are on the same hierarchy level.
  238. If this value is set to a very large value (e.g. 0xffffffff)
  239. all meshes on the same hierarchy level are joined - if they
  240. aren't animation nodes and if they have the same world matrices
  241. */
  242. unsigned int configMinNumFaces;
  243. /** Configuration option: specifies whether animations are removed
  244. from the node graph. If animations aren't needed by the caller,
  245. this allows for further optimization.
  246. */
  247. bool configRemoveAnimations;
  248. /** Configuration option: specifies whether nodes with inequal
  249. world matrices are joined if they are on the same hierarchy
  250. level and if it seems to make sense.
  251. */
  252. bool configJoinInequalTransforms;
  253. /** Working data */
  254. aiScene* pScene;
  255. /** List of hash identifiers for all meshes.
  256. The hashes are build from both the meshes vertex format
  257. and the material indices. Bones are not taken into account.
  258. */
  259. std::vector<MeshHash> mMeshHashes;
  260. /** List of output meshes.
  261. */
  262. std::vector<aiMesh*> mOutputMeshes;
  263. };
  264. } // end of namespace Assimp
  265. #endif // AI_LIMITBONEWEIGHTSPROCESS_H_INC