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