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 |
57 | RemoveVCProcess::RemoveVCProcess() : |
58 | configDeleteFlags() |
59 | , mScene() |
60 | {} |
61 | |
62 | // ------------------------------------------------------------------------------------------------ |
63 | // Destructor, private as well |
64 | RemoveVCProcess::~RemoveVCProcess() |
65 | {} |
66 | |
67 | // ------------------------------------------------------------------------------------------------ |
68 | // Returns whether the processing step is present in the given flag field. |
69 | 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> |
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. |
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(in&: pScene->mAnimations,num&: pScene->mNumAnimations); |
159 | } |
160 | |
161 | // handle textures |
162 | if ( configDeleteFlags & aiComponent_TEXTURES) |
163 | { |
164 | bHas = true; |
165 | ArrayDelete(in&: pScene->mTextures,num&: 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(pInput: &clr,pNumValues: 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(pInput: &clr,pNumValues: 1,AI_MATKEY_COLOR_AMBIENT); |
187 | |
188 | aiString s; |
189 | s.Set("Dummy_MaterialsRemoved" ); |
190 | helper->AddProperty(pInput: &s,AI_MATKEY_NAME); |
191 | } |
192 | |
193 | // handle light sources |
194 | if ( configDeleteFlags & aiComponent_LIGHTS) |
195 | { |
196 | bHas = true; |
197 | ArrayDelete(in&: pScene->mLights,num&: pScene->mNumLights); |
198 | } |
199 | |
200 | // handle camneras |
201 | if ( configDeleteFlags & aiComponent_CAMERAS) |
202 | { |
203 | bHas = true; |
204 | ArrayDelete(in&: pScene->mCameras,num&: pScene->mNumCameras); |
205 | } |
206 | |
207 | // handle meshes |
208 | if (configDeleteFlags & aiComponent_MESHES) |
209 | { |
210 | bHas = true; |
211 | ArrayDelete(in&: pScene->mMeshes,num&: pScene->mNumMeshes); |
212 | } |
213 | else |
214 | { |
215 | for( unsigned int a = 0; a < pScene->mNumMeshes; a++) |
216 | { |
217 | if( ProcessMesh( pcMesh: 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 |
243 | void RemoveVCProcess::SetupProperties(const Importer* pImp) |
244 | { |
245 | configDeleteFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS,iErrorReturn: 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. |
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(in&: pMesh->mBones,num&: pMesh->mNumBones); |
334 | ret = true; |
335 | } |
336 | return ret; |
337 | } |
338 | |