From 462bb953c26c7a7e2032b56bd9b2f34d46ff7ae2 Mon Sep 17 00:00:00 2001 From: aramis_acg Date: Thu, 15 Jan 2009 21:08:28 +0000 Subject: [PATCH] Removed OptimizeGraph step - actually it isn't really useful, although I got it working very well. Updated credits. VC9 workspace updated by hand (no vc9 ...) so be careful. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@300 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- CREDITS | 3 + code/Importer.cpp | 16 - code/OptimizeGraphProcess.cpp | 636 --------------------------------- code/OptimizeGraphProcess.h | 275 -------------- code/makefile | 1 - code/makefile.mingw | 1 - include/aiPostProcess.h | 16 - test/unit/utOptimizeGraph.cpp | 2 - test/unit/utOptimizeGraph.h | 35 -- workspaces/vc8/UnitTest.vcproj | 8 - workspaces/vc8/assimp.vcproj | 8 - workspaces/vc9/assimp.vcproj | 8 - 12 files changed, 3 insertions(+), 1006 deletions(-) delete mode 100644 code/OptimizeGraphProcess.cpp delete mode 100644 code/OptimizeGraphProcess.h delete mode 100644 test/unit/utOptimizeGraph.cpp delete mode 100644 test/unit/utOptimizeGraph.h diff --git a/CREDITS b/CREDITS index 9a0978a0f..8f734ae18 100644 --- a/CREDITS +++ b/CREDITS @@ -55,3 +55,6 @@ supplied patches for linux and SCons. - T. R. The GUY who performed some of the CSM mocaps. + +- Andy Maloney +Contributed fixes for the documentation and the doxygen markup diff --git a/code/Importer.cpp b/code/Importer.cpp index 50a9d2abf..c6e3d085a 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -181,9 +181,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS # include "RemoveRedundantMaterials.h" #endif -#ifndef AI_BUILD_NO_OPTIMIZEGRAPH_PROCESS -# include "OptimizeGraphProcess.h" -#endif #ifndef AI_BUILD_NO_FINDINVALIDDATA_PROCESS # include "FindInvalidDataProcess.h" #endif @@ -376,10 +373,6 @@ Importer::Importer() mPostProcessingSteps.push_back( new FindInvalidDataProcess()); #endif - -#if (!defined AI_BUILD_NO_OPTIMIZEGRAPH_PROCESS) - mPostProcessingSteps.push_back( new OptimizeGraphProcess()); -#endif #if (!defined AI_BUILD_NO_FIXINFACINGNORMALS_PROCESS) mPostProcessingSteps.push_back( new FixInfacingNormalsProcess()); #endif @@ -564,15 +557,6 @@ bool ValidateFlags(unsigned int pFlags) "aiProcess_GenNormals may not be specified together"); return false; } - - if (pFlags & aiProcess_PreTransformVertices && - pFlags & aiProcess_OptimizeGraph) - { - DefaultLogger::get()->error("aiProcess_PreTransformVertives and " - "aiProcess_OptimizeGraph may not be specified together"); - return false; - } - return true; } #endif // ! DEBUG diff --git a/code/OptimizeGraphProcess.cpp b/code/OptimizeGraphProcess.cpp deleted file mode 100644 index cb25e2581..000000000 --- a/code/OptimizeGraphProcess.cpp +++ /dev/null @@ -1,636 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2008, ASSIMP Development Team -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the ASSIMP team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the ASSIMP Development Team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ - -/** Implementation of the OptimizeGraphProcess post-processing step*/ - -#include "AssimpPCH.h" - -#include "OptimizeGraphProcess.h" -#include "Hash.h" - - -using namespace Assimp; - -// MSB for type unsigned int -#define AI_OG_UINT_MSB (1u<<((sizeof(unsigned int)*8u)-1u)) -#define AI_OG_UINT_MSB_2 (AI_OG_UINT_MSB>>1) - -// check whether a node/a mesh is locked -#define AI_OG_IS_NODE_LOCKED(nd) (nd->mNumChildren & AI_OG_UINT_MSB) -#define AI_OG_IS_MESH_LOCKED(ms) (ms->mNumBones & AI_OG_UINT_MSB) - -// check whether a node has locked meshes in its list -#define AI_OG_HAS_NODE_LOCKED_MESHES(nd) (nd->mNumChildren & AI_OG_UINT_MSB_2) - -// unmask the two upper bits of an unsigned int -#define AI_OG_UNMASK(p) (p & (~(AI_OG_UINT_MSB|AI_OG_UINT_MSB_2))) - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -OptimizeGraphProcess::OptimizeGraphProcess() -{ - configMinNumFaces = AI_OG_MIN_NUM_FACES; - configJoinInequalTransforms = AI_OG_JOIN_INEQUAL_TRANSFORMS; -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -OptimizeGraphProcess::~OptimizeGraphProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool OptimizeGraphProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_OptimizeGraph) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Setup properties of the step -void OptimizeGraphProcess::SetupProperties(const Importer* pImp) -{ - // join nods with inequal transformations? - configJoinInequalTransforms = pImp->GetPropertyInteger(AI_CONFIG_PP_OG_JOIN_INEQUAL_TRANSFORMS, - AI_OG_JOIN_INEQUAL_TRANSFORMS) != 0 ? true : false; - - // minimum face number per node - configMinNumFaces = pImp->GetPropertyInteger(AI_CONFIG_PP_OG_MIN_NUM_FACES, - AI_OG_MIN_NUM_FACES); -} - -// ------------------------------------------------------------------------------------------------ -void OptimizeGraphProcess::FindLockedNodes(aiNode* node) -{ - ai_assert(NULL != node); - - // process animations - for (unsigned int i = 0; i < pScene->mNumAnimations;++i) - { - aiAnimation* pani = pScene->mAnimations[i]; - for (unsigned int a = 0; a < pani->mNumChannels;++a) - { - aiNodeAnim* pba = pani->mChannels[a]; - if (pba->mNodeName == node->mName) - { - // this node is locked, it is referenced by an animation channel - node->mNumChildren |= AI_OG_UINT_MSB; - } - } - } - - // process cameras - for (unsigned int i = 0; i < pScene->mNumCameras;++i) - { - aiCamera* p = pScene->mCameras[i]; - if (p->mName == node->mName) - { - // this node is locked, it is referenced by a camera - node->mNumChildren |= AI_OG_UINT_MSB; - } - } - - // process lights - for (unsigned int i = 0; i < pScene->mNumLights;++i) - { - aiLight* p = pScene->mLights[i]; - if (p->mName == node->mName) - { - // this node is locked, it is referenced by a light - node->mNumChildren |= AI_OG_UINT_MSB; - } - } - - // call all children - for (unsigned int i = 0; i < node->mNumChildren;++i) - FindLockedNodes(node->mChildren[i]); -} - -// ------------------------------------------------------------------------------------------------ -void OptimizeGraphProcess::FindLockedMeshes(aiNode* node, MeshRefCount* pRefCount) -{ - ai_assert(NULL != node && NULL != pRefCount); - for (unsigned int i = 0;i < node->mNumMeshes;++i) - { - unsigned int m = node->mMeshes[i]; - if (pRefCount[m].first) - { - // we have already one reference - lock the first node - // that had a referenced to this mesh too if it has only - // one mesh assigned. If there are multiple meshes, - // the others could still be used for optimizations. - if (pRefCount[m].second) - { - pRefCount[m].second->mNumChildren |= (pRefCount[m].second->mNumMeshes <= 1 - ? AI_OG_UINT_MSB : AI_OG_UINT_MSB_2); - - pRefCount[m].second = NULL; - } - pScene->mMeshes[m]->mNumBones |= AI_OG_UINT_MSB; - - // lock this node - node->mNumChildren |= (node->mNumMeshes <= 1 - ? AI_OG_UINT_MSB : AI_OG_UINT_MSB_2); - } - else pRefCount[m].second = node; - ++pRefCount[m].first; - } - // call all children - for (unsigned int i = 0; i < node->mNumChildren;++i) - FindLockedMeshes(node->mChildren[i],pRefCount); -} - -// ------------------------------------------------------------------------------------------------ -void OptimizeGraphProcess::FindLockedMeshes(aiNode* node) -{ - ai_assert(NULL != node); - MeshRefCount* pRefCount = new MeshRefCount[pScene->mNumMeshes]; - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - pRefCount[i] = MeshRefCount(); - - // execute the algorithm - FindLockedMeshes(node,pRefCount); - - delete[] pRefCount; -} - -// ------------------------------------------------------------------------------------------------ -void OptimizeGraphProcess::UnlockNodes(aiNode* node) -{ - ai_assert(NULL != node); - node->mNumChildren &= ~(AI_OG_UINT_MSB|AI_OG_UINT_MSB_2); - - // call all children - for (unsigned int i = 0; i < node->mNumChildren;++i) - UnlockNodes(node->mChildren[i]); -} - -// ------------------------------------------------------------------------------------------------ -void OptimizeGraphProcess::UnlockMeshes() -{ - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - pScene->mMeshes[i]->mNumBones &= ~AI_OG_UINT_MSB; -} - -// ------------------------------------------------------------------------------------------------ -void OptimizeGraphProcess::ComputeMeshHashes() -{ - mMeshHashes.resize(pScene->mNumMeshes); - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - { - unsigned int iRet = 0; - aiMesh* pcMesh = pScene->mMeshes[i]; - - // normals - if (pcMesh->HasNormals())iRet |= 0x1; - // tangents and bitangents - if (pcMesh->HasTangentsAndBitangents())iRet |= 0x2; - - // texture coordinates - unsigned int p = 0; - ai_assert(4 >= AI_MAX_NUMBER_OF_TEXTURECOORDS); - while (pcMesh->HasTextureCoords(p)) - { - iRet |= (0x100 << p++); - - // NOTE: meshes with numUVComp != 3 && != 2 aren't handled correctly here - ai_assert(pcMesh->mNumUVComponents[p] == 3 || pcMesh->mNumUVComponents[p] == 2); - if (3 == pcMesh->mNumUVComponents[p]) - iRet |= (0x1000 << p++); - } - // vertex colors - p = 0; - ai_assert(4 >= AI_MAX_NUMBER_OF_COLOR_SETS); - while (pcMesh->HasVertexColors(p))iRet |= (0x10000 << p++); - mMeshHashes[i] = iRet; - - // material index -store it in the upper 1 1/2 bytes, so - // are able to encode 2^12 material indices. - - iRet |= (pcMesh->mMaterialIndex << 20u); - } -} - -// ------------------------------------------------------------------------------------------------ -inline unsigned int OptimizeGraphProcess::BinarySearch(NodeIndexList& sortedArray, - unsigned int min, unsigned int& index, unsigned int iStart) -{ - unsigned int first = iStart,last = (unsigned int)sortedArray.size()-1; - while (first <= last) - { - unsigned int mid = (first + last) / 2; - unsigned int id = sortedArray[mid].second; - - if (min > id) - first = mid + 1; - else if (min <= id) - { - last = mid - 1; - if (!mid || min > sortedArray[last].second) - { - index = sortedArray[last].first; - return mid; - } - } - } - return (unsigned int)sortedArray.size(); -} - - -// ------------------------------------------------------------------------------------------------ -void OptimizeGraphProcess::ApplyNodeMeshesOptimization(aiNode* pNode) -{ - ai_assert(NULL != pNode); - - // find all meshes which are compatible and could therefore be joined. - // we can't join meshes that are locked - std::vector apcMeshes(pNode->mNumMeshes); - unsigned int iNumMeshes; - - for (unsigned int m = 0, ttt = 0; m < pNode->mNumMeshes;++m) - { - iNumMeshes = 0; - - unsigned int nm = pNode->mMeshes[m]; - if (0xffffffff == nm || AI_OG_IS_MESH_LOCKED(pScene->mMeshes[nm]))continue; - - for (unsigned int q = m+1; q < pNode->mNumMeshes;++q) - { - register unsigned int nq = pNode->mMeshes[q]; - - // skip locked meshes - if (AI_OG_IS_MESH_LOCKED(pScene->mMeshes[nq]))continue; - - // compare the mesh hashes - if (mMeshHashes[nm] == mMeshHashes[nq]) - { - apcMeshes[iNumMeshes++] = pScene->mMeshes[nq]; - pNode->mMeshes[q] = 0xffffffff; - } - } - aiMesh* out; - if (iNumMeshes > 0) - { - apcMeshes[iNumMeshes++] = pScene->mMeshes[nm]; -// JoinMeshes(apcMeshes,out,iNumMeshes); - } - else out = pScene->mMeshes[nm]; - - pNode->mMeshes[ttt++] = (unsigned int)mOutputMeshes.size(); - mOutputMeshes.push_back(out); - } -} - -// ------------------------------------------------------------------------------------------------ -void OptimizeGraphProcess::TransformMeshes(aiNode* quak,aiNode* pNode) -{ - for (unsigned int pl = 0; pl < quak->mNumMeshes;++pl) - { - aiMesh* mariusIsHot = pScene->mMeshes[quak->mMeshes[pl]]; - aiMatrix4x4 mMatTransform = pNode->mTransformation; - - // transformation: first back to the parent's local space, - // later into the local space of the destination child node - mMatTransform.Inverse(); - mMatTransform = quak->mTransformation * mMatTransform; - - // transform all vertices - for (unsigned int oo =0; oo < mariusIsHot->mNumVertices;++oo) - mariusIsHot->mVertices[oo] = mMatTransform * mariusIsHot->mVertices[oo]; - - // transform all normal vectors - if (mariusIsHot->HasNormals()) - { - mMatTransform.Inverse().Transpose(); - for (unsigned int oo =0; oo < mariusIsHot->mNumVertices;++oo) - mariusIsHot->mNormals[oo] = mMatTransform * mariusIsHot->mNormals[oo]; - } - } -} - -// ------------------------------------------------------------------------------------------------ -void OptimizeGraphProcess::ApplyOptimizations(aiNode* node) -{ - ai_assert(NULL != node); - - unsigned int iJoinedIndex = 0; - - // first: node index; second: number of faces in node - NodeIndexList aiBelowTreshold; - aiBelowTreshold.reserve(node->mNumChildren); - - for (unsigned int i = 0; i < node->mNumChildren;++i) - { - aiNode* pChild = node->mChildren[i]; - if (AI_OG_IS_NODE_LOCKED(pChild) || !pChild->mNumMeshes)continue; - - // find out how many faces this node is referencing - unsigned int iFaceCnt = 0; - for (unsigned int a = 0; a < pChild->mNumMeshes;++a) - iFaceCnt += pScene->mMeshes[pChild->mMeshes[a]]->mNumFaces; - - // are we below the treshold? - if (iFaceCnt < configMinNumFaces) - { - aiBelowTreshold.push_back(NodeIndexEntry()); - NodeIndexEntry& p = aiBelowTreshold.back(); - p.first = i; - p.second = iFaceCnt; - p.pNode = pChild; - } - } - - if (!aiBelowTreshold.empty()) - { - // some typedefs for the data structures we'll need - typedef std::pair JoinListEntry; - std::vector aiJoinList(aiBelowTreshold.size()); - std::vector aiTempList(aiBelowTreshold.size()); - - unsigned int iNumJoins, iNumTemp; - - // sort the list by size - std::sort(aiBelowTreshold.begin(),aiBelowTreshold.end()); - - unsigned int iStart = 0; - for (NodeIndexList::const_iterator it = aiBelowTreshold.begin(),end = aiBelowTreshold.end(); - it != end; /*++it */++iStart) - { - aiNode* pNode = node->mChildren[(*it).first]; - - // get the hash of the mesh - const unsigned int iMeshVFormat = mMeshHashes[pNode->mMeshes[0]]; - - // we search for a node with more faces than this ... find - // the one that fits best and continue until we've reached - // treshold size. - int iDiff = configMinNumFaces-(*it).second; - for (;;) - { - // do a binary search and start the iteration there - unsigned int index; - unsigned int start = BinarySearch(aiBelowTreshold,iDiff,index,iStart); - - if (index == (*it).first)start++; - - if (start >= aiBelowTreshold.size()) - { - // there is no node with enough faces. take the first - start = 0; - } - - // todo: implement algorithm to find the best possible combination ... - iNumTemp = 0; - - while( start < aiBelowTreshold.size()) - { - // check whether the node has akready been processed before - const NodeIndexEntry& entry = aiBelowTreshold[start]; - if (!entry.pNode)continue; - - const aiNode* pip = node->mChildren[entry.first]; - if (configJoinInequalTransforms ) - { - // we need to check whether this node has locked meshes - // in this case we can't add it here - the meshes will - // be transformed from one to another coordinate space - - if (!AI_OG_HAS_NODE_LOCKED_MESHES(pip) || pip->mTransformation == pNode->mTransformation) - aiTempList[iNumTemp++] = start; - } - else if (node->mChildren[entry.first]->mTransformation == pNode->mTransformation) - { - aiTempList[iNumTemp++] = start; - break; - } - ++start; - } - - if (iNumTemp) - { - // search for a node which has a mesh with - // - the same material index - // - the same vertex layout - unsigned int d = iNumJoins = 0; - for (unsigned int m = 0; m < iNumTemp;++m) - { - register unsigned int mn = aiTempList[m]; - aiNode* pip = aiBelowTreshold[mn].pNode; - - for (unsigned int tt = 0; tt < pip->mNumMeshes;++tt) - { - register unsigned int mm = pip->mMeshes[tt]; - - if (mMeshHashes [ mm ] == iMeshVFormat) - { - d = mn; - goto break_out; - } - } - } -break_out: - aiJoinList[iNumJoins++] = JoinListEntry( aiBelowTreshold[d].first, d ); - iDiff -= aiBelowTreshold[d].second; - } - // did we reach the target treshold? - if (iDiff <= 0)break; - } - - // did we found any nodes to be joined with *this* one? - if (iNumJoins) - { - unsigned int iNumTotalChilds = pNode->mNumChildren; - unsigned int iNumTotalMeshes = pNode->mNumMeshes; - std::vector::const_iterator wend = aiJoinList.begin()+iNumJoins; - - // get output array bounds - for (std::vector::const_iterator wit = aiJoinList.begin(); - wit != wend;++wit ) - { - aiNode*& quak = node->mChildren[(*wit).first]; - iNumTotalChilds += AI_OG_UNMASK( quak->mNumChildren ); - iNumTotalMeshes += quak->mNumMeshes; - } - - // build the output child list - if (iNumTotalChilds != pNode->mNumChildren) - { - aiNode** ppc = pNode->mChildren; - delete[] pNode->mChildren; - pNode->mChildren = new aiNode*[iNumTotalChilds]; - ::memcpy(pNode->mChildren,ppc, sizeof(void*)* AI_OG_UNMASK( pNode->mNumChildren )); - - for (std::vector::const_iterator wit = aiJoinList.begin(); - wit != wend;++wit ) - { - aiNode*& quak = node->mChildren[(*wit).first]; - ::memcpy(pNode->mChildren+pNode->mNumChildren, - quak->mChildren, sizeof(void*)*quak->mNumChildren); - - pNode->mNumChildren += AI_OG_UNMASK( quak->mNumChildren ); - } - } - - // build the output mesh list - unsigned int* ppc = pNode->mMeshes; - delete[] pNode->mMeshes; - pNode->mMeshes = new unsigned int[iNumTotalMeshes]; - ::memcpy(pNode->mMeshes,ppc, sizeof(void*)*pNode->mNumMeshes); - - for (std::vector::const_iterator wit = aiJoinList.begin(); - wit != wend;++wit ) - { - aiNode*& quak = node->mChildren[(*wit).first]; - ::memcpy(pNode->mMeshes+pNode->mNumMeshes, - quak->mMeshes, sizeof(unsigned int)*quak->mNumMeshes); - - // if the node has a transformation matrix that is not equal to ours, - // we'll need to transform all vertices of the mesh into our - // local coordinate space. - if (configJoinInequalTransforms && quak->mTransformation != pNode->mTransformation) - TransformMeshes(quak,pNode); - - pNode->mNumMeshes += quak->mNumMeshes; - - // remove the joined nodes from all lists. - aiBelowTreshold[(*wit).second].pNode = NULL; - if ((*wit).second == iStart+1)++iStart; - } - - // now generate an output name for the joined nodes - if (1 == iNumTotalChilds) - { - pNode->mName.length = ::sprintf( pNode->mName.data, "", - iJoinedIndex++,iNumJoins+1); - } - } - - // now optimize the meshes in this node - ApplyNodeMeshesOptimization(pNode); - - // note - this has been optimized away. The search in the binary - // list starts with iStart, which is incremented each iteration - ++it; // = aiBelowTreshold.erase(it); - } - } - - // call all children recursively - for (unsigned int i = 0; i < node->mNumChildren;++i) - ApplyOptimizations(node->mChildren[i]); -} - -// ------------------------------------------------------------------------------------------------ -void OptimizeGraphProcess::BuildOutputMeshList() -{ - // all meshes should have been deleted before if they are - // not contained in the new mesh list - - if (pScene->mNumMeshes < mOutputMeshes.size()) - { - delete[] pScene->mMeshes; - pScene->mMeshes = new aiMesh*[mOutputMeshes.size()]; - } - pScene->mNumMeshes = (unsigned int)mOutputMeshes.size(); - ::memcpy(pScene->mMeshes,&mOutputMeshes[0],pScene->mNumMeshes*sizeof(void*)); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void OptimizeGraphProcess::Execute( aiScene* pScene) -{ - throw new ImportErrorException("This step is disabled in this beta"); - this->pScene = pScene; - /* - - a) the term "mesh node" stands for a node with numMeshes > 0 - b) the term "animation node" stands for a node with numMeshes == 0, - regardless whether the node is referenced by animation channels, - lights or cameras - - Algorithm: - - 1. Compute hashes for all meshes that we're able to check whether - two meshes are compatible. - 3. Find out which nodes may not be moved, so to speak are "locked" - a - locked node will never be joined with neighbors. - - A node lock is indicated by a set MSB in the aiNode::mNumChildren member - 4. Find out which meshes are locked - they are referenced by - more than one node. They will never be joined. Mark all - nodes referencing such a mesh as "locked", too. - - A mesh lock is indicated by a set MSB in the aiMesh::mNumBones member - 5. For each unlocked node count the face numbers of all assigned meshes - - if it is below the pre-defined treshold add the node to a list. - For each node in the list - try to find enough joinable nodes to - have enough faces all together. - Two nodes are joined if: - - none of them is locked - - (optional) their world matrices are identical - - nodes whose meshes share the same material indices are prefered - Two meshes in one node are joined if: - - their material indices are identical - - none of them is locked - - they share the same vertex format - 6. Build the final mesh list - 7. For all meshes and all nodes - remove locks. - - */ - - throw new ImportErrorException("OG step is still undeer development and not yet finished"); - - // STEP 1 - ComputeMeshHashes(); - - // STEP 2 - FindLockedNodes(pScene->mRootNode); - - // STEP 3 - FindLockedMeshes(pScene->mRootNode); - - // STEP 4 - ApplyOptimizations(pScene->mRootNode); - - // STEP 5 - BuildOutputMeshList(); - - // STEP 6 - UnlockNodes(pScene->mRootNode); - UnlockMeshes(); -} diff --git a/code/OptimizeGraphProcess.h b/code/OptimizeGraphProcess.h deleted file mode 100644 index d39441dd1..000000000 --- a/code/OptimizeGraphProcess.h +++ /dev/null @@ -1,275 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2008, ASSIMP Development Team -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the ASSIMP team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the ASSIMP Development Team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ - -/** Defines a post processing step to refactor the output node graph to - be more compact */ -#ifndef AI_OPTIMIZEGRAPHPROCESS_H_INC -#define AI_OPTIMIZEGRAPHPROCESS_H_INC - -#include "BaseProcess.h" - -struct aiMesh; -struct aiNode; -struct aiBone; -class OptimizeGraphProcessTest; - -namespace Assimp { - -// NOTE: If you change these limits, don't forget to change the -// corresponding values in all Assimp ports - -// ********************************************************** -// Java: ConfigProperty.java, -// ConfigProperty.OG_MIN_NUM_FACES -// ConfigProperty.JOIN_INEQUAL_TRANSFORMS -// ********************************************************** - -#if (!defined AI_OG_MAX_DEPTH) -# define AI_OG_MAX_DEPTH 0x4 -#endif // !! AI_LMW_MAX_WEIGHTS - -#if (!defined AI_OG_MIN_NUM_FACES) -# define AI_OG_MIN_NUM_FACES 0xffffffff -#endif // !! AI_LMW_MAX_WEIGHTS - -#if (!defined AI_OG_JOIN_INEQUAL_TRANSFORMS) -# define AI_OG_JOIN_INEQUAL_TRANSFORMS false -#endif // !! AI_LMW_MAX_WEIGHTS - - -// --------------------------------------------------------------------------- -struct NodeIndexEntry : public std::pair -{ - // binary operator < for use with std::sort - bool operator< (const NodeIndexEntry& other) - { - return second < other.second; - } - - // pointer to the original node - aiNode* pNode; -}; -typedef std::vector NodeIndexList; - -// --------------------------------------------------------------------------- -/** This post processing step reformats the output node graph to be more - * compact. There are several options, e.g. maximum hierachy depth or - * minimum mesh size. Some files store every face as a new mesh, so - * some Assimp steps (such as FixInfacingNormals or SmoothNormals) don't - * work properly on these meshes. This step joins such small meshes and - * nodes. Animations are kept during the step. - * @note Use the PretransformVertices step to remove the node graph - * completely (and all animations, too). -*/ -class ASSIMP_API OptimizeGraphProcess : public BaseProcess -{ - friend class Importer; - friend class ::OptimizeGraphProcessTest; - -protected: - /** Constructor to be privately used by Importer */ - OptimizeGraphProcess(); - - /** Destructor, private as well */ - ~OptimizeGraphProcess(); - - - typedef std::pair< unsigned int, aiNode* > MeshRefCount; - typedef unsigned int MeshHash; - -public: - - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag. - * @param pFlags The processing flags the importer was called with. - * A bitwise combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, - * false if not. - */ - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - /** Called prior to ExecuteOnScene(). - * The function is a request to the process to update its configuration - * basing on the Importer's configuration property list. - */ - void SetupProperties(const Importer* pImp); - - - // set the configMinNumfaces property - inline void SetMinNumFaces(unsigned int n) - { - configMinNumFaces = n; - } - - -protected: - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * At the moment a process is not supposed to fail. - * @param pScene The imported data to work at. - */ - void Execute( aiScene* pScene); - - - // ------------------------------------------------------------------- - /** Removes animation nodes from the tree. - * @param node Current node - * @param out Receives a list of replacement nodes for *this* node - - * if *this* node should be kept, it must be added to the list. - */ - void RemoveAnimationNodes (aiNode* node,std::vector& out); - - - // ------------------------------------------------------------------- - /** Finds and marks all locked nodes in the tree. - * A node is locked if it is referenced by animations. - * @param node ROot node to start with - * @note A locked node has the MSB set in its mNumChildren member - */ - void FindLockedNodes(aiNode* node); - - - // ------------------------------------------------------------------- - /** Searches for locked meshes. A mesh is locked if it is referenced - * by more than one node in the hierarchy. - * @param node Root node to start with - */ - void FindLockedMeshes(aiNode* node); - void FindLockedMeshes(aiNode* node, MeshRefCount* pRefCount); - - - // ------------------------------------------------------------------- - /** Unlocks all nodes in the output tree. - * @param node Root node to start with - */ - void UnlockNodes(aiNode* node); - - - // ------------------------------------------------------------------- - /** Unlocks all meshes in the output tree. - */ - void UnlockMeshes(); - - - // ------------------------------------------------------------------- - /** Apply the final optimization algorithm to the tree. - * See the Execute-method for a detailled description of the algorithm. - * @param node Root node to start with - */ - void ApplyOptimizations(aiNode* node); - - - // ------------------------------------------------------------------- - /** Binary search for the first element that is >= min. - * @param sortedArray Input array - * @param min Treshold - */ - unsigned int BinarySearch(NodeIndexList& sortedArray, - unsigned int min, unsigned int& index, unsigned int iStart); - - - // ------------------------------------------------------------------- - /** Compute stable hashes for all meshes and fill mMeshHashes - * with the results. - */ - void ComputeMeshHashes(); - - - // ------------------------------------------------------------------- - /** Optimizes the meshes in a single node aftr the joining process. - * @param pNode Node to be optimized. Childs noded won't be processed - * automatically. - */ - void ApplyNodeMeshesOptimization(aiNode* pNode); - - - - // ------------------------------------------------------------------- - /** Build the output mesh list. - */ - void BuildOutputMeshList(); - - - // ------------------------------------------------------------------- - /** Transform meshes from one coordinate space into another. - * @param quak Input space. All meshes referenced by this node - - * assuming none of them is locked - are transformed in the - * local coordinate space of pNode - * @param pNode Destination coordinate space - */ - void TransformMeshes(aiNode* quak,aiNode* pNode); - -private: - - /** Configuration option: specifies the minimum number of faces - a node should have. The steps tries to join meshes with less - vertices that are on the same hierarchy level. - If this value is set to a very large value (e.g. 0xffffffff) - all meshes on the same hierarchy level are joined - if they - aren't animation nodes and if they have the same world matrices - */ - unsigned int configMinNumFaces; - - - /** Configuration option: specifies whether nodes with inequal - world matrices are joined if they are on the same hierarchy - level and if it seems to make sense. - */ - bool configJoinInequalTransforms; - - /** Working data */ - aiScene* pScene; - - /** List of hash identifiers for all meshes. - The hashes are build from both the meshes vertex format - and the material indices. Bones are not taken into account. - */ - std::vector mMeshHashes; - - /** List of output meshes. - */ - std::vector mOutputMeshes; -}; - -} // end of namespace Assimp - -#endif // AI_LIMITBONEWEIGHTSPROCESS_H_INC diff --git a/code/makefile b/code/makefile index fc45a0ef7..a3f13b7ec 100644 --- a/code/makefile +++ b/code/makefile @@ -39,7 +39,6 @@ SOURCES = AssimpPCH.cpp \ ObjFileImporter.cpp \ ObjFileMtlImporter.cpp \ ObjFileParser.cpp \ - OptimizeGraphProcess.cpp \ PlyLoader.cpp \ PlyParser.cpp \ PretransformVertices.cpp \ diff --git a/code/makefile.mingw b/code/makefile.mingw index 6a167b9de..ec5351412 100644 --- a/code/makefile.mingw +++ b/code/makefile.mingw @@ -39,7 +39,6 @@ SOURCES = AssimpPCH.cpp \ ObjFileImporter.cpp \ ObjFileMtlImporter.cpp \ ObjFileParser.cpp \ - OptimizeGraphProcess.cpp \ PlyLoader.cpp \ PlyParser.cpp \ PretransformVertices.cpp \ diff --git a/include/aiPostProcess.h b/include/aiPostProcess.h index 2d6185f7f..652be73d3 100644 --- a/include/aiPostProcess.h +++ b/include/aiPostProcess.h @@ -195,22 +195,6 @@ enum aiPostProcessSteps */ aiProcess_FixInfacingNormals = 0x2000, - /** This step performs some optimizations on the node graph. - * - * It is incompatible to the PreTransformVertices-Step. Some configuration - * options exist, see aiConfig.h for more details. - * Generally, two actions are available:
- * 1. Remove animation nodes and data from the scene. This allows other - * steps for further optimizations.
- * 2. Combine very small meshes to larger ones. Only if the meshes - * are used by the same node or by nodes on the same hierarchy (with - * equal local transformations). Unlike PreTransformVertices, the - * OptimizeGraph-step doesn't transform vertices from one space - * another (at least with the default configuration).
- * - * It is recommended to have this step run with the default configuration. - */ - aiProcess_OptimizeGraph = 0x4000, /** This step splits meshes with more than one primitive type in * homogeneous submeshes. diff --git a/test/unit/utOptimizeGraph.cpp b/test/unit/utOptimizeGraph.cpp deleted file mode 100644 index 3e9e49b91..000000000 --- a/test/unit/utOptimizeGraph.cpp +++ /dev/null @@ -1,2 +0,0 @@ - -#include "UnitTestPCH.h" \ No newline at end of file diff --git a/test/unit/utOptimizeGraph.h b/test/unit/utOptimizeGraph.h deleted file mode 100644 index 2c92f0b22..000000000 --- a/test/unit/utOptimizeGraph.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef TESTOG_H -#define TESTOG_H - -#include -#include - -#include -#include - - -using namespace std; -using namespace Assimp; - -class OptimizeGraphProcessTest : public CPPUNIT_NS :: TestFixture -{ - CPPUNIT_TEST_SUITE (OptimizeGraphProcessTest); - CPPUNIT_TEST (testProcess); - CPPUNIT_TEST_SUITE_END (); - - public: - void setUp (void); - void tearDown (void); - - protected: - - void testProcess (void); - - - private: - - OptimizeGraphProcess* piProcess; - aiScene* pcMesh; -}; - -#endif diff --git a/workspaces/vc8/UnitTest.vcproj b/workspaces/vc8/UnitTest.vcproj index 01e161126..e195c3752 100644 --- a/workspaces/vc8/UnitTest.vcproj +++ b/workspaces/vc8/UnitTest.vcproj @@ -1387,14 +1387,6 @@ RelativePath="..\..\test\unit\utMaterialSystem.h" > - - - - diff --git a/workspaces/vc8/assimp.vcproj b/workspaces/vc8/assimp.vcproj index 39f44a1d3..bf6c05426 100644 --- a/workspaces/vc8/assimp.vcproj +++ b/workspaces/vc8/assimp.vcproj @@ -2086,14 +2086,6 @@ RelativePath="..\..\code\LimitBoneWeightsProcess.h" > - - - - diff --git a/workspaces/vc9/assimp.vcproj b/workspaces/vc9/assimp.vcproj index e5515f269..96c790b5d 100644 --- a/workspaces/vc9/assimp.vcproj +++ b/workspaces/vc9/assimp.vcproj @@ -2083,14 +2083,6 @@ RelativePath="..\..\code\LimitBoneWeightsProcess.h" > - - - -