2
0

RemoveVCProcess.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. /*
  2. ---------------------------------------------------------------------------
  3. Open Asset Import Library (ASSIMP)
  4. ---------------------------------------------------------------------------
  5. Copyright (c) 2006-2008, ASSIMP Development Team
  6. All rights reserved.
  7. Redistribution and use of this software in source and binary forms,
  8. with or without modification, are permitted provided that the following
  9. conditions are met:
  10. * Redistributions of source code must retain the above
  11. copyright notice, this list of conditions and the
  12. following disclaimer.
  13. * Redistributions in binary form must reproduce the above
  14. copyright notice, this list of conditions and the
  15. following disclaimer in the documentation and/or other
  16. materials provided with the distribution.
  17. * Neither the name of the ASSIMP team, nor the names of its
  18. contributors may be used to endorse or promote products
  19. derived from this software without specific prior
  20. written permission of the ASSIMP Development Team.
  21. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. ---------------------------------------------------------------------------
  33. */
  34. /** @file Implementation of the post processing step to remove
  35. * any parts of the mesh structure from the imported data.
  36. */
  37. #include "AssimpPCH.h"
  38. #include "RemoveVCProcess.h"
  39. using namespace Assimp;
  40. // MSB for type unsigned int
  41. #define AI_RC_UINT_MSB (1u<<((sizeof(unsigned int)<<3u)-1u))
  42. #define AI_RC_UINT_MSB_2 (AI_RC_UINT_MSB>>1u)
  43. // unmask the two upper bits of an unsigned int
  44. #define AI_RC_UNMASK(p) (p & (~(AI_RC_UINT_MSB|AI_RC_UINT_MSB_2)))
  45. // ------------------------------------------------------------------------------------------------
  46. // Constructor to be privately used by Importer
  47. RemoveVCProcess::RemoveVCProcess()
  48. {
  49. }
  50. // ------------------------------------------------------------------------------------------------
  51. // Destructor, private as well
  52. RemoveVCProcess::~RemoveVCProcess()
  53. {
  54. // nothing to do here
  55. }
  56. // ------------------------------------------------------------------------------------------------
  57. // Returns whether the processing step is present in the given flag field.
  58. bool RemoveVCProcess::IsActive( unsigned int pFlags) const
  59. {
  60. return (pFlags & aiProcess_RemoveComponent) != 0;
  61. }
  62. // ------------------------------------------------------------------------------------------------
  63. // Small helper function to delete all elements in a T** aray using delete
  64. template <typename T>
  65. inline void ArrayDelete(T**& in, unsigned int num)
  66. {
  67. for (unsigned int i = 0; i < num; ++i)
  68. delete in[i];
  69. delete[] in;
  70. in = NULL;
  71. }
  72. // ------------------------------------------------------------------------------------------------
  73. // Small helper function to set a sepcific bit in the aiNode::mNumMeshes member of all nodes
  74. // that are referenced by the elements of an array (T::mName must be there)
  75. template <typename T>
  76. inline void MaskNodes(aiNode* node,T** in, unsigned int num, unsigned int bit)
  77. {
  78. if (node->mName.length)
  79. {
  80. for (unsigned int i = 0; i < num;++i)
  81. {
  82. T* cur = in[i];
  83. if (cur->mName == node->mName)
  84. {
  85. node->mNumMeshes |= bit;
  86. break;
  87. }
  88. }
  89. }
  90. for (unsigned int i = 0; i < node->mNumChildren;++i)
  91. MaskNodes(node->mChildren[i],in,num,bit);
  92. }
  93. // ------------------------------------------------------------------------------------------------
  94. // Updates the node graph - removes all nodes which have the "remove" flag set and the
  95. // "don't remove" flag not set. Nodes with meshes are never deleted.
  96. bool UpdateNodeGraph(aiNode* node,std::list<aiNode*>& childsOfParent,bool root)
  97. {
  98. register bool b = false;
  99. std::list<aiNode*> mine;
  100. for (unsigned int i = 0; i < node->mNumChildren;++i)
  101. {
  102. if(UpdateNodeGraph(node->mChildren[i],mine,false))
  103. b = true;
  104. }
  105. if (!root && !node->mNumMeshes && AI_RC_UINT_MSB == (node->mNumMeshes & (AI_RC_UINT_MSB | AI_RC_UINT_MSB_2)))
  106. {
  107. // this node needs to be removed
  108. if(node->mNumChildren)
  109. {
  110. childsOfParent.insert(childsOfParent.end(),mine.begin(),mine.end());
  111. // set all children to NULL to make sure they are not deleted when we delete ourself
  112. for (unsigned int i = 0; i < node->mNumChildren;++i)
  113. node->mChildren[i] = NULL;
  114. }
  115. b = true;
  116. delete node;
  117. }
  118. else
  119. {
  120. AI_RC_UNMASK(node->mNumMeshes);
  121. childsOfParent.push_back(node);
  122. if (b)
  123. {
  124. // reallocate the array of our children here
  125. node->mNumChildren = (unsigned int)mine.size();
  126. aiNode** const children = new aiNode*[mine.size()];
  127. aiNode** ptr = children;
  128. for (std::list<aiNode*>::iterator it = mine.begin(), end = mine.end();
  129. it != end; ++it)
  130. {
  131. *ptr++ = *it;
  132. }
  133. delete[] node->mChildren;
  134. node->mChildren = children;
  135. return false;
  136. }
  137. }
  138. return b;
  139. }
  140. // ------------------------------------------------------------------------------------------------
  141. // Executes the post processing step on the given imported data.
  142. void RemoveVCProcess::Execute( aiScene* pScene)
  143. {
  144. DefaultLogger::get()->debug("RemoveVCProcess begin");
  145. bool bHas = false,bMasked = false;
  146. mScene = pScene;
  147. // handle animations
  148. if ( configDeleteFlags & aiComponent_ANIMATIONS)
  149. {
  150. bHas = true;
  151. ArrayDelete(pScene->mAnimations,pScene->mNumAnimations);
  152. }
  153. // handle textures
  154. if ( configDeleteFlags & aiComponent_TEXTURES)
  155. {
  156. bHas = true;
  157. ArrayDelete(pScene->mTextures,pScene->mNumTextures);
  158. }
  159. // handle materials
  160. if ( configDeleteFlags & aiComponent_MATERIALS && pScene->mNumMaterials)
  161. {
  162. bHas = true;
  163. for (unsigned int i = 1;i < pScene->mNumMaterials;++i)
  164. delete pScene->mMaterials[i];
  165. MaterialHelper* helper = (MaterialHelper*) pScene->mMaterials[0];
  166. helper->Clear();
  167. // gray
  168. aiColor3D clr(0.6f,0.6f,0.6f);
  169. helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
  170. // add a small ambient color value
  171. clr = aiColor3D(0.05f,0.05f,0.05f);
  172. helper->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT);
  173. aiString s;
  174. s.Set("Dummy_MaterialsRemoved");
  175. helper->AddProperty(&s,AI_MATKEY_NAME);
  176. }
  177. // handle light sources
  178. if ( configDeleteFlags & aiComponent_LIGHTS)
  179. {
  180. // mask nodes for removal
  181. MaskNodes(pScene->mRootNode,pScene->mLights,pScene->mNumLights,
  182. AI_RC_UINT_MSB);
  183. bHas = bMasked = true;
  184. ArrayDelete(pScene->mLights,pScene->mNumLights);
  185. }
  186. // handle camneras
  187. if ( configDeleteFlags & aiComponent_CAMERAS)
  188. {
  189. // mask nodes for removal
  190. MaskNodes(pScene->mRootNode,pScene->mLights,pScene->mNumLights,
  191. AI_RC_UINT_MSB);
  192. bHas = true;
  193. ArrayDelete(pScene->mCameras,pScene->mNumCameras);
  194. }
  195. // handle meshes
  196. if (configDeleteFlags & aiComponent_MESHES)
  197. {
  198. bHas = true;
  199. ArrayDelete(pScene->mMeshes,pScene->mNumMeshes);
  200. }
  201. else
  202. {
  203. for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
  204. {
  205. if( this->ProcessMesh( pScene->mMeshes[a]))
  206. bHas = true;
  207. }
  208. if (configDeleteFlags & aiComponent_BONEWEIGHTS && bHas)bMasked = true;
  209. }
  210. // now check which scenegraph nodes are unnecessary now
  211. // we use the upper two bits of aiNode::mNumMeshes as
  212. // temporary storage.
  213. // MSB means: REMOVE ME!
  214. // MSB>>1 means: NO, DON'T REMOVE ME (Veto)
  215. if (bMasked)
  216. {
  217. if (pScene->mNumLights)
  218. {
  219. MaskNodes(pScene->mRootNode,pScene->mLights,pScene->mNumLights,
  220. AI_RC_UINT_MSB_2);
  221. }
  222. if (pScene->mNumCameras)
  223. {
  224. MaskNodes(pScene->mRootNode,pScene->mCameras,pScene->mNumCameras,
  225. AI_RC_UINT_MSB_2);
  226. }
  227. if (!(configDeleteFlags & aiComponent_BONEWEIGHTS))
  228. {
  229. for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
  230. {
  231. aiMesh* mesh = pScene->mMeshes[i];
  232. if (mesh->mNumBones)
  233. {
  234. MaskNodes(pScene->mRootNode,mesh->mBones,mesh->mNumBones,
  235. AI_RC_UINT_MSB_2);
  236. }
  237. }
  238. }
  239. std::list<aiNode*> dummy;
  240. UpdateNodeGraph(pScene->mRootNode,dummy, true);
  241. // the root node will never be deleted
  242. }
  243. // now check whether the result is still a full scene
  244. if (!pScene->mNumMeshes || !pScene->mNumMaterials)
  245. {
  246. pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
  247. DefaultLogger::get()->debug("Setting AI_SCENE_FLAGS_INCOMPLETE flag");
  248. }
  249. if (bHas)DefaultLogger::get()->info("RemoveVCProcess finished. Data structure cleanup has been done.");
  250. else DefaultLogger::get()->debug("RemoveVCProcess finished. Nothing to be done ...");
  251. }
  252. // ------------------------------------------------------------------------------------------------
  253. // Setup configuration properties for the step
  254. void RemoveVCProcess::SetupProperties(const Importer* pImp)
  255. {
  256. configDeleteFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS,0x0);
  257. if (!configDeleteFlags)
  258. {
  259. DefaultLogger::get()->warn("RemoveVCProcess: AI_CONFIG_PP_RVC_FLAGS is zero.");
  260. }
  261. }
  262. // ------------------------------------------------------------------------------------------------
  263. // Executes the post processing step on the given imported data.
  264. bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh)
  265. {
  266. bool ret = false;
  267. // if all materials have been deleted let the material
  268. // index of the mesh point to the created default material
  269. if ( configDeleteFlags & aiComponent_MATERIALS)
  270. pMesh->mMaterialIndex = 0;
  271. // handle normals
  272. if (configDeleteFlags & aiComponent_NORMALS && pMesh->mNormals)
  273. {
  274. delete[] pMesh->mNormals;
  275. pMesh->mNormals = NULL;
  276. ret = true;
  277. }
  278. // handle tangents and bitangents
  279. if (configDeleteFlags & aiComponent_TANGENTS_AND_BITANGENTS && pMesh->mTangents)
  280. {
  281. delete[] pMesh->mTangents;
  282. pMesh->mTangents = NULL;
  283. delete[] pMesh->mBitangents;
  284. pMesh->mBitangents = NULL;
  285. ret = true;
  286. }
  287. // handle texture coordinates
  288. register bool b = (0 != (configDeleteFlags & aiComponent_TEXCOORDS));
  289. for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i)
  290. {
  291. if (!pMesh->mTextureCoords[i])break;
  292. if (configDeleteFlags & aiComponent_TEXCOORDSn(i) || b)
  293. {
  294. delete pMesh->mTextureCoords[i];
  295. pMesh->mTextureCoords[i] = NULL;
  296. ret = true;
  297. if (!b)
  298. {
  299. // collapse the rest of the array
  300. unsigned int a;
  301. for (a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a)
  302. {
  303. pMesh->mTextureCoords[a-1] = pMesh->mTextureCoords[a];
  304. }
  305. pMesh->mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS-1] = NULL;
  306. }
  307. }
  308. }
  309. // handle vertex colors
  310. b = (0 != (configDeleteFlags & aiComponent_COLORS));
  311. for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i)
  312. {
  313. if (!pMesh->mColors[i])break;
  314. if (configDeleteFlags & aiComponent_COLORSn(i) || b)
  315. {
  316. delete pMesh->mColors[i];
  317. pMesh->mColors[i] = NULL;
  318. ret = true;
  319. if (!b)
  320. {
  321. // collapse the rest of the array
  322. unsigned int a;
  323. for (a = i+1; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a)
  324. {
  325. pMesh->mColors[a-1] = pMesh->mColors[a];
  326. }
  327. pMesh->mColors[AI_MAX_NUMBER_OF_COLOR_SETS-1] = NULL;
  328. }
  329. }
  330. }
  331. // handle bones
  332. if (configDeleteFlags & aiComponent_BONEWEIGHTS && pMesh->mBones)
  333. {
  334. // mask nodes for removal
  335. MaskNodes(mScene->mRootNode,pMesh->mBones,pMesh->mNumBones,
  336. AI_RC_UINT_MSB);
  337. ArrayDelete(pMesh->mBones,pMesh->mNumBones);
  338. ret = true;
  339. }
  340. return ret;
  341. }