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