nuclear@0: /* nuclear@0: --------------------------------------------------------------------------- nuclear@0: Open Asset Import Library (assimp) nuclear@0: --------------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2012, assimp team nuclear@0: nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the following nuclear@0: conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: --------------------------------------------------------------------------- nuclear@0: */ nuclear@0: /** @file Implementation of the post processing step to remove nuclear@0: * any parts of the mesh structure from the imported data. nuclear@0: */ nuclear@0: nuclear@0: #include "AssimpPCH.h" nuclear@0: #include "RemoveVCProcess.h" nuclear@0: nuclear@0: using namespace Assimp; nuclear@0: nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Constructor to be privately used by Importer nuclear@0: RemoveVCProcess::RemoveVCProcess() nuclear@0: {} nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Destructor, private as well nuclear@0: RemoveVCProcess::~RemoveVCProcess() nuclear@0: {} nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Returns whether the processing step is present in the given flag field. nuclear@0: bool RemoveVCProcess::IsActive( unsigned int pFlags) const nuclear@0: { nuclear@0: return (pFlags & aiProcess_RemoveComponent) != 0; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Small helper function to delete all elements in a T** aray using delete nuclear@0: template nuclear@0: inline void ArrayDelete(T**& in, unsigned int& num) nuclear@0: { nuclear@0: for (unsigned int i = 0; i < num; ++i) nuclear@0: delete in[i]; nuclear@0: nuclear@0: delete[] in; nuclear@0: in = NULL; nuclear@0: num = 0; nuclear@0: } nuclear@0: nuclear@0: #if 0 nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Updates the node graph - removes all nodes which have the "remove" flag set and the nuclear@0: // "don't remove" flag not set. Nodes with meshes are never deleted. nuclear@0: bool UpdateNodeGraph(aiNode* node,std::list& childsOfParent,bool root) nuclear@0: { nuclear@0: register bool b = false; nuclear@0: nuclear@0: std::list mine; nuclear@0: for (unsigned int i = 0; i < node->mNumChildren;++i) nuclear@0: { nuclear@0: if(UpdateNodeGraph(node->mChildren[i],mine,false)) nuclear@0: b = true; nuclear@0: } nuclear@0: nuclear@0: // somewhat tricky ... mNumMeshes must be originally 0 and MSB2 may not be set, nuclear@0: // so we can do a simple comparison against MSB here nuclear@0: if (!root && AI_RC_UINT_MSB == node->mNumMeshes ) nuclear@0: { nuclear@0: // this node needs to be removed nuclear@0: if(node->mNumChildren) nuclear@0: { nuclear@0: childsOfParent.insert(childsOfParent.end(),mine.begin(),mine.end()); nuclear@0: nuclear@0: // set all children to NULL to make sure they are not deleted when we delete ourself nuclear@0: for (unsigned int i = 0; i < node->mNumChildren;++i) nuclear@0: node->mChildren[i] = NULL; nuclear@0: } nuclear@0: b = true; nuclear@0: delete node; nuclear@0: } nuclear@0: else nuclear@0: { nuclear@0: AI_RC_UNMASK(node->mNumMeshes); nuclear@0: childsOfParent.push_back(node); nuclear@0: nuclear@0: if (b) nuclear@0: { nuclear@0: // reallocate the array of our children here nuclear@0: node->mNumChildren = (unsigned int)mine.size(); nuclear@0: aiNode** const children = new aiNode*[mine.size()]; nuclear@0: aiNode** ptr = children; nuclear@0: nuclear@0: for (std::list::iterator it = mine.begin(), end = mine.end(); nuclear@0: it != end; ++it) nuclear@0: { nuclear@0: *ptr++ = *it; nuclear@0: } nuclear@0: delete[] node->mChildren; nuclear@0: node->mChildren = children; nuclear@0: return false; nuclear@0: } nuclear@0: } nuclear@0: return b; nuclear@0: } nuclear@0: #endif nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Executes the post processing step on the given imported data. nuclear@0: void RemoveVCProcess::Execute( aiScene* pScene) nuclear@0: { nuclear@0: DefaultLogger::get()->debug("RemoveVCProcess begin"); nuclear@0: bool bHas = false; //,bMasked = false; nuclear@0: nuclear@0: mScene = pScene; nuclear@0: nuclear@0: // handle animations nuclear@0: if ( configDeleteFlags & aiComponent_ANIMATIONS) nuclear@0: { nuclear@0: nuclear@0: bHas = true; nuclear@0: ArrayDelete(pScene->mAnimations,pScene->mNumAnimations); nuclear@0: } nuclear@0: nuclear@0: // handle textures nuclear@0: if ( configDeleteFlags & aiComponent_TEXTURES) nuclear@0: { nuclear@0: bHas = true; nuclear@0: ArrayDelete(pScene->mTextures,pScene->mNumTextures); nuclear@0: } nuclear@0: nuclear@0: // handle materials nuclear@0: if ( configDeleteFlags & aiComponent_MATERIALS && pScene->mNumMaterials) nuclear@0: { nuclear@0: bHas = true; nuclear@0: for (unsigned int i = 1;i < pScene->mNumMaterials;++i) nuclear@0: delete pScene->mMaterials[i]; nuclear@0: nuclear@0: pScene->mNumMaterials = 1; nuclear@0: aiMaterial* helper = (aiMaterial*) pScene->mMaterials[0]; nuclear@0: ai_assert(NULL != helper); nuclear@0: helper->Clear(); nuclear@0: nuclear@0: // gray nuclear@0: aiColor3D clr(0.6f,0.6f,0.6f); nuclear@0: helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); nuclear@0: nuclear@0: // add a small ambient color value nuclear@0: clr = aiColor3D(0.05f,0.05f,0.05f); nuclear@0: helper->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT); nuclear@0: nuclear@0: aiString s; nuclear@0: s.Set("Dummy_MaterialsRemoved"); nuclear@0: helper->AddProperty(&s,AI_MATKEY_NAME); nuclear@0: } nuclear@0: nuclear@0: // handle light sources nuclear@0: if ( configDeleteFlags & aiComponent_LIGHTS) nuclear@0: { nuclear@0: bHas = true; nuclear@0: ArrayDelete(pScene->mLights,pScene->mNumLights); nuclear@0: } nuclear@0: nuclear@0: // handle camneras nuclear@0: if ( configDeleteFlags & aiComponent_CAMERAS) nuclear@0: { nuclear@0: bHas = true; nuclear@0: ArrayDelete(pScene->mCameras,pScene->mNumCameras); nuclear@0: } nuclear@0: nuclear@0: // handle meshes nuclear@0: if (configDeleteFlags & aiComponent_MESHES) nuclear@0: { nuclear@0: bHas = true; nuclear@0: ArrayDelete(pScene->mMeshes,pScene->mNumMeshes); nuclear@0: } nuclear@0: else nuclear@0: { nuclear@0: for( unsigned int a = 0; a < pScene->mNumMeshes; a++) nuclear@0: { nuclear@0: if( ProcessMesh( pScene->mMeshes[a])) nuclear@0: bHas = true; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: nuclear@0: // now check whether the result is still a full scene nuclear@0: if (!pScene->mNumMeshes || !pScene->mNumMaterials) nuclear@0: { nuclear@0: pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; nuclear@0: DefaultLogger::get()->debug("Setting AI_SCENE_FLAGS_INCOMPLETE flag"); nuclear@0: nuclear@0: // If we have no meshes anymore we should also clear another flag ... nuclear@0: if (!pScene->mNumMeshes) nuclear@0: pScene->mFlags &= ~AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; nuclear@0: } nuclear@0: nuclear@0: if (bHas)DefaultLogger::get()->info("RemoveVCProcess finished. Data structure cleanup has been done."); nuclear@0: else DefaultLogger::get()->debug("RemoveVCProcess finished. Nothing to be done ..."); nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Setup configuration properties for the step nuclear@0: void RemoveVCProcess::SetupProperties(const Importer* pImp) nuclear@0: { nuclear@0: configDeleteFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS,0x0); nuclear@0: if (!configDeleteFlags) nuclear@0: { nuclear@0: DefaultLogger::get()->warn("RemoveVCProcess: AI_CONFIG_PP_RVC_FLAGS is zero."); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Executes the post processing step on the given imported data. nuclear@0: bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh) nuclear@0: { nuclear@0: bool ret = false; nuclear@0: nuclear@0: // if all materials have been deleted let the material nuclear@0: // index of the mesh point to the created default material nuclear@0: if ( configDeleteFlags & aiComponent_MATERIALS) nuclear@0: pMesh->mMaterialIndex = 0; nuclear@0: nuclear@0: // handle normals nuclear@0: if (configDeleteFlags & aiComponent_NORMALS && pMesh->mNormals) nuclear@0: { nuclear@0: delete[] pMesh->mNormals; nuclear@0: pMesh->mNormals = NULL; nuclear@0: ret = true; nuclear@0: } nuclear@0: nuclear@0: // handle tangents and bitangents nuclear@0: if (configDeleteFlags & aiComponent_TANGENTS_AND_BITANGENTS && pMesh->mTangents) nuclear@0: { nuclear@0: delete[] pMesh->mTangents; nuclear@0: pMesh->mTangents = NULL; nuclear@0: nuclear@0: delete[] pMesh->mBitangents; nuclear@0: pMesh->mBitangents = NULL; nuclear@0: ret = true; nuclear@0: } nuclear@0: nuclear@0: // handle texture coordinates nuclear@0: register bool b = (0 != (configDeleteFlags & aiComponent_TEXCOORDS)); nuclear@0: for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++real) nuclear@0: { nuclear@0: if (!pMesh->mTextureCoords[i])break; nuclear@0: if (configDeleteFlags & aiComponent_TEXCOORDSn(real) || b) nuclear@0: { nuclear@0: delete pMesh->mTextureCoords[i]; nuclear@0: pMesh->mTextureCoords[i] = NULL; nuclear@0: ret = true; nuclear@0: nuclear@0: if (!b) nuclear@0: { nuclear@0: // collapse the rest of the array nuclear@0: for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) nuclear@0: pMesh->mTextureCoords[a-1] = pMesh->mTextureCoords[a]; nuclear@0: nuclear@0: pMesh->mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS-1] = NULL; nuclear@0: continue; nuclear@0: } nuclear@0: } nuclear@0: ++i; nuclear@0: } nuclear@0: nuclear@0: // handle vertex colors nuclear@0: b = (0 != (configDeleteFlags & aiComponent_COLORS)); nuclear@0: for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_COLOR_SETS; ++real) nuclear@0: { nuclear@0: if (!pMesh->mColors[i])break; nuclear@0: if (configDeleteFlags & aiComponent_COLORSn(i) || b) nuclear@0: { nuclear@0: delete pMesh->mColors[i]; nuclear@0: pMesh->mColors[i] = NULL; nuclear@0: ret = true; nuclear@0: nuclear@0: if (!b) nuclear@0: { nuclear@0: // collapse the rest of the array nuclear@0: for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) nuclear@0: pMesh->mColors[a-1] = pMesh->mColors[a]; nuclear@0: nuclear@0: pMesh->mColors[AI_MAX_NUMBER_OF_COLOR_SETS-1] = NULL; nuclear@0: continue; nuclear@0: } nuclear@0: } nuclear@0: ++i; nuclear@0: } nuclear@0: nuclear@0: // handle bones nuclear@0: if (configDeleteFlags & aiComponent_BONEWEIGHTS && pMesh->mBones) nuclear@0: { nuclear@0: ArrayDelete(pMesh->mBones,pMesh->mNumBones); nuclear@0: ret = true; nuclear@0: } nuclear@0: return ret; nuclear@0: }