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