From e8511e89ffe4088012559871524e3dccbbb09e52 Mon Sep 17 00:00:00 2001 From: aramis_acg Date: Tue, 22 Jul 2008 22:52:16 +0000 Subject: [PATCH] Added "ImproveCacheLocality"-Step; Added Unit tests (3 at the moment); Fixed hp spelling errors. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@68 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- code/Importer.cpp | 10 + code/ImproveCacheLocality.cpp | 370 ++++++++++++ code/ImproveCacheLocality.h | 103 ++++ code/JoinVerticesProcess.cpp | 7 +- code/LimitBoneWeightsProcess.cpp | 87 ++- code/LimitBoneWeightsProcess.h | 6 +- code/RemoveComments.cpp | 35 +- code/TriangulateProcess.cpp | 5 +- code/VertexTriangleAdjacency.cpp | 136 +++++ code/VertexTriangleAdjacency.h | 126 ++++ include/aiMesh.h | 8 +- include/aiPostProcess.h | 10 +- test/unit/ExecuteStepWin32.bat | 28 + test/unit/ExecuteStepWin64.bat | 28 + test/unit/Main.cpp | 35 ++ test/unit/ut3DSLoader.cpp | 0 test/unit/utASELoader.cpp | 0 test/unit/utFixInfacingNormals.cpp | 0 test/unit/utGenNormals.cpp | 0 test/unit/utGenSmoothNormals.cpp | 0 test/unit/utImproveCacheLocality.cpp | 0 test/unit/utJoinVertices.cpp | 0 test/unit/utLimitBoneWeights.cpp | 82 +++ test/unit/utLimitBoneWeights.h | 38 ++ test/unit/utMDLLoader.cpp | 0 test/unit/utMaterialSystem.cpp | 0 test/unit/utOBJLoader.cpp | 0 test/unit/utPretransformVertices.cpp | 0 test/unit/utRemoveComments.cpp | 61 ++ test/unit/utRemoveComments.h | 35 ++ test/unit/utSplitLargeMeshes.cpp | 0 test/unit/utTextureTransform.cpp | 0 test/unit/utVertexTriangleAdjacency.cpp | 193 ++++++ test/unit/utVertexTriangleAdjacency.h | 41 ++ tools/assimp_view/LogDisplay.cpp | 10 +- tools/assimp_view/MessageProc.cpp | 4 + tools/assimp_view/assimp_view.aps | Bin 348828 -> 354312 bytes tools/assimp_view/assimp_view.cpp | 3 +- tools/assimp_view/assimp_view.h | 4 + tools/assimp_view/assimp_view.rc | 12 +- tools/assimp_view/resource.h | 14 +- workspaces/vc8/UnitTest.vcproj | 762 ++++++++++++++++++++++++ workspaces/vc8/assimp.sln | 37 +- workspaces/vc8/assimp.vcproj | 18 +- workspaces/vc8/assimp_view.vcproj | 168 +++--- 45 files changed, 2324 insertions(+), 152 deletions(-) create mode 100644 code/ImproveCacheLocality.cpp create mode 100644 code/ImproveCacheLocality.h create mode 100644 code/VertexTriangleAdjacency.cpp create mode 100644 code/VertexTriangleAdjacency.h create mode 100644 test/unit/ExecuteStepWin32.bat create mode 100644 test/unit/ExecuteStepWin64.bat create mode 100644 test/unit/Main.cpp create mode 100644 test/unit/ut3DSLoader.cpp create mode 100644 test/unit/utASELoader.cpp create mode 100644 test/unit/utFixInfacingNormals.cpp create mode 100644 test/unit/utGenNormals.cpp create mode 100644 test/unit/utGenSmoothNormals.cpp create mode 100644 test/unit/utImproveCacheLocality.cpp create mode 100644 test/unit/utJoinVertices.cpp create mode 100644 test/unit/utLimitBoneWeights.cpp create mode 100644 test/unit/utLimitBoneWeights.h create mode 100644 test/unit/utMDLLoader.cpp create mode 100644 test/unit/utMaterialSystem.cpp create mode 100644 test/unit/utOBJLoader.cpp create mode 100644 test/unit/utPretransformVertices.cpp create mode 100644 test/unit/utRemoveComments.cpp create mode 100644 test/unit/utRemoveComments.h create mode 100644 test/unit/utSplitLargeMeshes.cpp create mode 100644 test/unit/utTextureTransform.cpp create mode 100644 test/unit/utVertexTriangleAdjacency.cpp create mode 100644 test/unit/utVertexTriangleAdjacency.h create mode 100644 workspaces/vc8/UnitTest.vcproj diff --git a/code/Importer.cpp b/code/Importer.cpp index bbdb28e31..b9a9d11f0 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -40,15 +40,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file Implementation of the CPP-API class #Importer */ + +// STL/CSL heades #include #include +// public Assimp API #include "../include/assimp.hpp" #include "../include/aiAssert.h" #include "../include/aiScene.h" #include "../include/aiPostProcess.h" #include "../include/DefaultLogger.h" +// internal headers #include "BaseImporter.h" #include "BaseProcess.h" #include "DefaultIOStream.h" @@ -123,6 +127,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #if (!defined AI_BUILD_NO_VALIDATEDS_PROCESS) # include "ValidateDataStructure.h" #endif +#if (!defined AI_BUILD_NO_IMPROVECACHELOCALITY_PROCESS) +# include "ImproveCacheLocality.h" +#endif using namespace Assimp; @@ -210,6 +217,9 @@ Importer::Importer() : #if (!defined AI_BUILD_NO_LIMITBONEWEIGHTS_PROCESS) mPostProcessingSteps.push_back( new LimitBoneWeightsProcess()); #endif +#if (!defined AI_BUILD_NO_IMPROVECACHELOCALITY_PROCESS) + mPostProcessingSteps.push_back( new ImproveCacheLocalityProcess()); +#endif } // ------------------------------------------------------------------------------------------------ diff --git a/code/ImproveCacheLocality.cpp b/code/ImproveCacheLocality.cpp new file mode 100644 index 000000000..b72f1e453 --- /dev/null +++ b/code/ImproveCacheLocality.cpp @@ -0,0 +1,370 @@ +/* +--------------------------------------------------------------------------- +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. +--------------------------------------------------------------------------- +*/ + +/** @file Implementation of the post processing step to join identical vertices + * for all imported meshes + *
+ * The algorithm is roughly basing on this paper: + * http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf + */ + +// STL headers +#include +#include +#include + +// public ASSIMP headers +#include "../include/DefaultLogger.h" +#include "../include/aiPostProcess.h" +#include "../include/aiMesh.h" +#include "../include/aiScene.h" + +// internal headers +#include "ImproveCacheLocality.h" +#include "VertexTriangleAdjacency.h" + +using namespace Assimp; + +// ------------------------------------------------------------------------------------------------ +// Constructor to be privately used by Importer +ImproveCacheLocalityProcess::ImproveCacheLocalityProcess() +{ + // nothing to do here + configCacheDepth = 12; // hardcoded to 12 at the moment +} + +// ------------------------------------------------------------------------------------------------ +// Destructor, private as well +ImproveCacheLocalityProcess::~ImproveCacheLocalityProcess() +{ + // nothing to do here +} + +// ------------------------------------------------------------------------------------------------ +// Returns whether the processing step is present in the given flag field. +bool ImproveCacheLocalityProcess::IsActive( unsigned int pFlags) const +{ + return (pFlags & aiProcess_ImproveCacheLocality) != 0; +} + +// ------------------------------------------------------------------------------------------------ +// Executes the post processing step on the given imported data. +void ImproveCacheLocalityProcess::Execute( aiScene* pScene) +{ + DefaultLogger::get()->debug("ImproveCacheLocalityProcess begin"); + + for( unsigned int a = 0; a < pScene->mNumMeshes; a++) + { + this->ProcessMesh( pScene->mMeshes[a]); + } + DefaultLogger::get()->debug("ImproveCacheLocalityProcess finished. "); +} + +// ------------------------------------------------------------------------------------------------ +// Improves the cache coherency of a specific mesh +void ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh) +{ + ai_assert(NULL != pMesh); + + // check whether the input data is valid -> + // - there must be vertices and faces (haha) + // - all faces must be triangulated + if (!pMesh->HasFaces() || !pMesh->HasPositions())return; + + // find the input ACMR ... + unsigned int* piFIFOStack = new unsigned int[this->configCacheDepth]; + ::memset(piFIFOStack,0xff,this->configCacheDepth*sizeof(unsigned int)); + unsigned int* piCur = piFIFOStack; + const unsigned int* const piCurEnd = piFIFOStack + this->configCacheDepth; + + // count the number of cache misses + unsigned int iCacheMisses = 0; + + const aiFace* const pcEnd = pMesh->mFaces+pMesh->mNumFaces; + for (const aiFace* pcFace = pMesh->mFaces;pcFace != pcEnd;++pcFace) + { + if (3 != pcFace->mNumIndices) + { + DefaultLogger::get()->error("Unable to improve cache locality of non-triangulated faces"); + delete[] piFIFOStack; + return; + } + + // although it has not been tested, I'm quite sure degenerated triangles + // would crash if the algorithm was applied to them + +#if (defined _DEBUG) + if (pcFace->mIndices[0] == pcFace->mIndices[1] || + pcFace->mIndices[2] == pcFace->mIndices[1] || + pcFace->mIndices[2] == pcFace->mIndices[0]) + { + DefaultLogger::get()->error("ImproveCacheLocalityProcess: There may be no degenerated triangles "); + return; + } +#endif + + for (unsigned int qq = 0; qq < 3;++qq) + { + bool bInCache = false; + for (unsigned int* pp = piFIFOStack;pp < piCurEnd;++pp) + { + if (*pp == pcFace->mIndices[qq]) + { + // the vertex is in cache + bInCache = true; + break; + } + } + if (!bInCache) + { + ++iCacheMisses; + if (piCurEnd == piCur)piCur = piFIFOStack; + *piCur++ = pcFace->mIndices[qq]; + } + } + } + delete[] piFIFOStack; + + float fACMR = (float)iCacheMisses / pMesh->mNumFaces; + char szBuff[16]; + sprintf(szBuff,"%f",fACMR); + DefaultLogger::get()->debug("Input ACMR: " + std::string(szBuff)); + + + // first we need to build a vertex-triangle adjacency list + VertexTriangleAdjacency adj(pMesh->mFaces,pMesh->mNumFaces, pMesh->mNumVertices,true); + + // build a list to store per-vertex caching time stamps + unsigned int* const piCachingStamps = new unsigned int[pMesh->mNumVertices]; + ::memset(piCachingStamps,0x0,pMesh->mNumVertices*sizeof(unsigned int)); + + // allocate an empty output index buffer. We store the output + // indices in one large array. Since the number of triangles + // won't change the input faces can be reused. This is how we save + // thousands of redundant mini allocations for aiFace::mIndices + const unsigned int iIdxCnt = pMesh->mNumFaces*3; + unsigned int* const piIBOutput = new unsigned int[iIdxCnt]; + unsigned int* piCSIter = piIBOutput; + + // allocate the flag array to hold the information + // whether a face has already been emitted or not + std::vector abEmitted(pMesh->mNumFaces,false); + + // dead-end vertex index stack + std::stack sDeadEndVStack; + + // create a copy of the piNumTriPtr buffer + unsigned int* const piNumTriPtr = adj.mLiveTriangles; + const unsigned int* const piNumTriPtrNoModify = new unsigned int[pMesh->mNumVertices]; + ::memcpy(const_cast (piNumTriPtrNoModify),piNumTriPtr, + pMesh->mNumVertices * sizeof(unsigned int)); + + // get the largest number of referenced triangles + // and allocate the "candidate buffer" + unsigned int iMaxRefTris = 0; + { + const unsigned int* piCur = adj.mLiveTriangles; + const unsigned int* const piCurEnd = adj.mLiveTriangles+pMesh->mNumVertices; + for (;piCur != piCurEnd;++piCur) + iMaxRefTris = std::max(iMaxRefTris,*piCur); + } + unsigned int* piCandidates = new unsigned int[iMaxRefTris*3]; + iCacheMisses = 0; + + /** PSEUDOCODE for the algorithm + + A = Build-Adjacency(I) Vertex-triangle adjacency + L = Get-Triangle-Counts(A) Per-vertex live triangle counts + C = Zero(Vertex-Count(I)) Per-vertex caching time stamps + D = Empty-Stack() Dead-end vertex stack + E = False(Triangle-Count(I)) Per triangle emitted flag + O = Empty-Index-Buffer() Empty output buffer + f = 0 Arbitrary starting vertex + s = k+1, i = 1 Time stamp and cursor + while f >= 0 For all valid fanning vertices + N = Empty-Set() 1-ring of next candidates + for each Triangle t in Neighbors(A, f) + if !Emitted(E,t) + for each Vertex v in t + Append(O,v) Output vertex + Push(D,v) Add to dead-end stack + Insert(N,v) Register as candidate + L[v] = L[v]-1 Decrease live triangle count + if s-C[v] > k If not in cache + C[v] = s Set time stamp + s = s+1 Increment time stamp + E[t] = true Flag triangle as emitted + Select next fanning vertex + f = Get-Next-Vertex(I,i,k,N,C,s,L,D) + return O + */ + + int ivdx = 0; + int ics = 1; + int iStampCnt = this->configCacheDepth+1; + while (ivdx >= 0) + { + unsigned int icnt = piNumTriPtrNoModify[ivdx]; + unsigned int* piList = adj.GetAdjacentTriangles(ivdx); + unsigned int* piCurCandidate = piCandidates; + + // get all triangles in the neighborhood + for (unsigned int tri = 0; tri < icnt;++tri) + { + // if they have not yet been emitted, add them to the output IB + const unsigned int fidx = *piList++; + if (!abEmitted[fidx]) + { + // so iterate through all vertices of the current triangle + const aiFace* pcFace = &pMesh->mFaces[ fidx ]; + const unsigned int* const p2 = pcFace->mIndices+3; + for (unsigned int* p = pcFace->mIndices;p != p2;++p) + { + const unsigned int dp = *p; + + // the current vertex won't have any free triangles after this step + if (ivdx != dp) + { + // append the vertex to the dead-end stack + sDeadEndVStack.push(dp); + + // register as candidate for the next step + *piCurCandidate++ = dp; + + // decrease the per-vertex triangle counts + piNumTriPtr[dp]--; + } + + // append the vertex to the output index buffer + *piCSIter++ = dp; + + // if the vertex is not yet in cache, set its cache count + if (iStampCnt-piCachingStamps[dp] > this->configCacheDepth) + { + piCachingStamps[dp] = iStampCnt++; + ++iCacheMisses; + } + } + // flag triangle as emitted + abEmitted[fidx] = true; + } + } + + // the vertex has now no living adjacent triangles anymore + piNumTriPtr[ivdx] = 0; + + // get next fanning vertex + ivdx = -1; + int max_priority = -1; + for (unsigned int* piCur = piCandidates;piCur != piCurCandidate;++piCur) + { + register const unsigned int dp = *piCur; + + // must have live triangles + if (piNumTriPtr[dp] > 0) + { + int priority = 0; + + // will the vertex be in cache, even after fanning occurs? + unsigned int tmp; + if ((tmp = iStampCnt-piCachingStamps[dp]) + 2*piNumTriPtr[dp] <= this->configCacheDepth) + priority = tmp; + // keep best candidate + if (priority > max_priority) + { + max_priority = priority; + ivdx = dp; + } + } + } + // did we reach a dead end? + if (-1 == ivdx) + { + // need to get a non-local vertex for which we have a good + // chance that it is still in the cache ... + while (!sDeadEndVStack.empty()) + { + unsigned int iCachedIdx = sDeadEndVStack.top(); + sDeadEndVStack.pop(); + if (piNumTriPtr[ iCachedIdx ] > 0) + { + ivdx = iCachedIdx; + break; + } + } + + if (-1 == ivdx) + { + // well, there isn't such a vertex. Simply get the next + // vertex in input order and hope it is not too bad ... + while (ics < (int)pMesh->mNumVertices) + { + ++ics; + if (piNumTriPtr[ics] > 0) + { + ivdx = ics; + break; + } + } + } + } + } + + fACMR = (float)iCacheMisses / pMesh->mNumFaces; + sprintf(szBuff,"%f",fACMR); + DefaultLogger::get()->debug("Output ACMR: " + std::string(szBuff)); + + // sort the output index buffer back to the input array + piCSIter = piIBOutput; + + for (aiFace* pcFace = pMesh->mFaces; pcFace != pcEnd;++pcFace) + { + pcFace->mIndices[0] = *piCSIter++; + pcFace->mIndices[1] = *piCSIter++; + pcFace->mIndices[2] = *piCSIter++; + } + + // delete temporary storage + delete[] piCachingStamps; + delete[] piIBOutput; + delete[] piCandidates; + delete[] piNumTriPtrNoModify; +} \ No newline at end of file diff --git a/code/ImproveCacheLocality.h b/code/ImproveCacheLocality.h new file mode 100644 index 000000000..6c2868892 --- /dev/null +++ b/code/ImproveCacheLocality.h @@ -0,0 +1,103 @@ +/* +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. + +---------------------------------------------------------------------- +*/ + +/** @file Defines a post processing step to reorder faces for + better cache locality*/ +#ifndef AI_IMPROVECACHELOCALITY_H_INC +#define AI_IMPROVECACHELOCALITY_H_INC + +#include "BaseProcess.h" +#include "../include/aiTypes.h" + +struct aiMesh; + +namespace Assimp +{ + +// --------------------------------------------------------------------------- +/** The ImproveCacheLocalityProcess reorders all faces for improved vertex + * cache locality. It tries to arrange all faces to fans and to render + * faces which share vertices directly one after the other. + * + * @note This step expects the triagulated input data. + */ +class ImproveCacheLocalityProcess : public BaseProcess +{ + friend class Importer; + +protected: + /** Constructor to be privately used by Importer */ + ImproveCacheLocalityProcess(); + + /** Destructor, private as well */ + ~ImproveCacheLocalityProcess(); + +public: + // ------------------------------------------------------------------- + /** Returns whether the processing step is present in the given flag field. + * @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; + + // ------------------------------------------------------------------- + /** 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); + +protected: + // ------------------------------------------------------------------- + /** Executes the postprocessing step on the given mesh + * @param pMesh The mesh to process. + */ + void ProcessMesh( aiMesh* pMesh); + + + //! Configuration parameter: specifies the size of the cache to + //! optimize the vertex data for. + unsigned int configCacheDepth; +}; + +} // end of namespace Assimp + +#endif // AI_IMPROVECACHELOCALITY_H_INC \ No newline at end of file diff --git a/code/JoinVerticesProcess.cpp b/code/JoinVerticesProcess.cpp index cace725e9..b3c198d3b 100644 --- a/code/JoinVerticesProcess.cpp +++ b/code/JoinVerticesProcess.cpp @@ -44,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include -#include #include "JoinVerticesProcess.h" #include "SpatialSort.h" #include "../include/DefaultLogger.h" @@ -177,7 +176,7 @@ bool JoinVerticesProcess::ProcessMesh( aiMesh* pMesh) if( (uv.mBitangent - v.mBitangent).SquareLength() > squareEpsilon) continue; // manually unrolled because continue wouldn't work as desired in an inner loop - assert( AI_MAX_NUMBER_OF_COLOR_SETS == 4); + ai_assert( AI_MAX_NUMBER_OF_COLOR_SETS == 4); if( GetColorDifference( uv.mColors[0], v.mColors[0]) > squareEpsilon) continue; if( GetColorDifference( uv.mColors[1], v.mColors[1]) > squareEpsilon) @@ -187,7 +186,7 @@ bool JoinVerticesProcess::ProcessMesh( aiMesh* pMesh) if( GetColorDifference( uv.mColors[3], v.mColors[3]) > squareEpsilon) continue; // texture coord matching manually unrolled as well - assert( AI_MAX_NUMBER_OF_TEXTURECOORDS == 4); + ai_assert( AI_MAX_NUMBER_OF_TEXTURECOORDS == 4); if( (uv.mTexCoords[0] - v.mTexCoords[0]).SquareLength() > squareEpsilon) continue; if( (uv.mTexCoords[1] - v.mTexCoords[1]).SquareLength() > squareEpsilon) @@ -303,7 +302,7 @@ bool JoinVerticesProcess::ProcessMesh( aiMesh* pMesh) } // there should be some. At least I think there should be some - assert( newWeights.size() > 0); + ai_assert( newWeights.size() > 0); // kill the old and replace them with the translated weights delete [] bone->mWeights; diff --git a/code/LimitBoneWeightsProcess.cpp b/code/LimitBoneWeightsProcess.cpp index e37b9ad30..84de5b755 100644 --- a/code/LimitBoneWeightsProcess.cpp +++ b/code/LimitBoneWeightsProcess.cpp @@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../include/aiPostProcess.h" #include "../include/aiMesh.h" #include "../include/aiScene.h" +#include "../include/aiAssert.h" #include "../include/DefaultLogger.h" using namespace Assimp; @@ -122,11 +123,14 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh) } // now cut the weight count if it exceeds the maximum + bool bChanged = false; for( WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit) { if( vit->size() <= mMaxWeights) continue; + bChanged = true; + // more than the defined maximum -> first sort by weight in descending order. That's // why we defined the < operator in such a weird way. std::sort( vit->begin(), vit->end()); @@ -142,28 +146,71 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh) it->mWeight /= sum; } - // rebuild the vertex weight array for all bones - typedef std::vector< std::vector< aiVertexWeight > > WeightsPerBone; - WeightsPerBone boneWeights( pMesh->mNumBones); - for( unsigned int a = 0; a < vertexWeights.size(); a++) + if (bChanged) { - const std::vector& vw = vertexWeights[a]; - for( std::vector::const_iterator it = vw.begin(); it != vw.end(); ++it) - boneWeights[it->mBone].push_back( aiVertexWeight( a, it->mWeight)); - } - // and finally copy the vertex weight list over to the mesh's bones - for( unsigned int a = 0; a < pMesh->mNumBones; a++) - { - const std::vector& bw = boneWeights[a]; - aiBone* bone = pMesh->mBones[a]; - // ignore the bone if no vertex weights were removed there - if( bw.size() == bone->mNumWeights) - continue; + // rebuild the vertex weight array for all bones + typedef std::vector< std::vector< aiVertexWeight > > WeightsPerBone; + WeightsPerBone boneWeights( pMesh->mNumBones); + for( unsigned int a = 0; a < vertexWeights.size(); a++) + { + const std::vector& vw = vertexWeights[a]; + for( std::vector::const_iterator it = vw.begin(); it != vw.end(); ++it) + boneWeights[it->mBone].push_back( aiVertexWeight( a, it->mWeight)); + } - // copy the weight list. should always be less weights than before, so we don't need a new allocation - assert( bw.size() < bone->mNumWeights); - bone->mNumWeights = (unsigned int) bw.size(); - memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight)); + // and finally copy the vertex weight list over to the mesh's bones + std::vector abNoNeed(pMesh->mNumBones,false); + bChanged = false; + + for( unsigned int a = 0; a < pMesh->mNumBones; a++) + { + const std::vector& bw = boneWeights[a]; + aiBone* bone = pMesh->mBones[a]; + + // ignore the bone if no vertex weights were removed there + + // FIX (Aramis, 07|22|08) + // NO! we can't ignore it in this case ... it is possible that + // the number of weights did not change, but the weight values did. + + // if( bw.size() == bone->mNumWeights) + // continue; + + // FIX (Aramis, 07|21|08) + // It is possible that all weights of a bone have been removed. + // This would naturally cause an exception in &bw[0]. + if ( bw.empty() ) + { + abNoNeed[a] = bChanged = true; + continue; + } + + // copy the weight list. should always be less weights than before, so we don't need a new allocation + ai_assert( bw.size() <= bone->mNumWeights); + bone->mNumWeights = (unsigned int) bw.size(); + ::memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight)); + } + + if (bChanged) + { + // the number of new bones is smaller than before, so we can + // reuse the old array, too. + aiBone** ppcCur = pMesh->mBones; + aiBone** ppcSrc = ppcCur; + + for (std::vector::const_iterator + iter = abNoNeed.begin(); + iter != abNoNeed.end() ;++iter) + { + if (*iter) + { + delete *ppcSrc; + --pMesh->mNumBones; + } + else *ppcCur++ = *ppcSrc; + ++ppcSrc; + } + } } } diff --git a/code/LimitBoneWeightsProcess.h b/code/LimitBoneWeightsProcess.h index 653acc34a..a373944ff 100644 --- a/code/LimitBoneWeightsProcess.h +++ b/code/LimitBoneWeightsProcess.h @@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BaseProcess.h" struct aiMesh; +class LimitBoneWeightsTest; namespace Assimp { @@ -53,8 +54,8 @@ namespace Assimp // corresponding values in all Assimp ports // ********************************************************** -// Java: PostProcessStep.java, -// PostProcessStep.DEFAULT_BONE_WEIGHT_LIMIT +// Java: ConfigProperty.java, +// ConfigProperty.DEFAULT_BONE_WEIGHT_LIMIT // ********************************************************** #if (!defined AI_LMW_MAX_WEIGHTS) @@ -71,6 +72,7 @@ namespace Assimp class LimitBoneWeightsProcess : public BaseProcess { friend class Importer; + friend class ::LimitBoneWeightsTest; protected: /** Constructor to be privately used by Importer */ diff --git a/code/RemoveComments.cpp b/code/RemoveComments.cpp index 033346924..18f66cd3a 100644 --- a/code/RemoveComments.cpp +++ b/code/RemoveComments.cpp @@ -57,15 +57,14 @@ void CommentRemover::RemoveLineComments(const char* szComment, // validate parameters ai_assert(NULL != szComment && NULL != szBuffer && *szComment); + const size_t len = ::strlen(szComment); + while (*szBuffer) { - if (*szBuffer == *szComment) + if (0 == ::strncmp(szBuffer,szComment,len)) { - if (0 == ::strcmp(szBuffer+1,szComment+1)) - { - while (*szBuffer != '\r' && *szBuffer != '\n' && *szBuffer) - *szBuffer++ = chReplacement; - } + while (*szBuffer != '\r' && *szBuffer != '\n' && *szBuffer) + *szBuffer++ = chReplacement; } ++szBuffer; } @@ -80,28 +79,24 @@ void CommentRemover::RemoveMultiLineComments(const char* szCommentStart, NULL != szBuffer && '\0' != *szCommentStart && '\0' != *szCommentEnd); const size_t len = ::strlen(szCommentEnd); + const size_t len2 = ::strlen(szCommentStart); while (*szBuffer) { - if (*szBuffer == *szCommentStart) + if (0 == ::strncmp(szBuffer,szCommentStart,len2)) { - if (0 == ::strcmp(szBuffer+1,szCommentStart+1)) + while (*szBuffer) { - while (*szBuffer) + + if (0 == ::strncmp(szBuffer,szCommentEnd,len)) { - if (*szBuffer == *szCommentEnd) - { - if (0 == ::strcmp(szBuffer+1,szCommentEnd+1)) - { - for (unsigned int i = 0; i < len;++i) - *szBuffer++ = chReplacement; - goto __continue_outer; // WUHHHAAAAHHAA! - } - } - *szBuffer++ = chReplacement; + for (unsigned int i = 0; i < len;++i) + *szBuffer++ = chReplacement; + goto __continue_outer; // WUHHHAAAAHHAA! } - return; + *szBuffer++ = chReplacement; } + return; } ++szBuffer; __continue_outer: diff --git a/code/TriangulateProcess.cpp b/code/TriangulateProcess.cpp index ee20862df..adcb26de8 100644 --- a/code/TriangulateProcess.cpp +++ b/code/TriangulateProcess.cpp @@ -94,15 +94,16 @@ void TriangulateProcess::Execute( aiScene* pScene) bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) { // check whether we will need to do something ... + bool bNeed = false; for( unsigned int a = 0; a < pMesh->mNumFaces; a++) { const aiFace& face = pMesh->mFaces[a]; if( face.mNumIndices != 3) { - break; + bNeed = true; } - return false; } + if (!bNeed)return false; std::vector newFaces; newFaces.reserve( pMesh->mNumFaces*2); diff --git a/code/VertexTriangleAdjacency.cpp b/code/VertexTriangleAdjacency.cpp new file mode 100644 index 000000000..4a751ccd8 --- /dev/null +++ b/code/VertexTriangleAdjacency.cpp @@ -0,0 +1,136 @@ +/* +--------------------------------------------------------------------------- +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. +--------------------------------------------------------------------------- +*/ + +/** @file Implementation of the VertexTriangleAdjacency helper class + */ + +// public ASSIMP headers +#include "../include/DefaultLogger.h" +#include "../include/aiMesh.h" + +// internal headers +#include "VertexTriangleAdjacency.h" + +using namespace Assimp; + +// ------------------------------------------------------------------------------------------------ +VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces, + unsigned int iNumFaces, + unsigned int iNumVertices /*= 0*/, + bool bComputeNumTriangles /*= false*/) +{ + // compute the number of referenced vertices if it wasn't specified by the caller + const aiFace* const pcFaceEnd = pcFaces + iNumFaces; + if (!iNumVertices) + { + for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) + { + iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]); + iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]); + iNumVertices = std::max(iNumVertices,pcFace->mIndices[2]); + } + } + unsigned int* pi; + + // allocate storage + if (bComputeNumTriangles) + { + pi = this->mLiveTriangles = new unsigned int[iNumVertices+1]; + ::memset(this->mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1)); + this->mOffsetTable = new unsigned int[iNumVertices+2]+1; + } + else + { + pi = this->mOffsetTable = new unsigned int[iNumVertices+2]+1; + ::memset(this->mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1)); + this->mLiveTriangles = NULL; // important, otherwise the d'tor would crash + } + + // get a pointer to the end of the buffer + unsigned int* piEnd = pi+iNumVertices; + *piEnd++ = 0u; + + // first pass: compute the number of faces referencing each vertex + for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) + { + pi[pcFace->mIndices[0]]++; + pi[pcFace->mIndices[1]]++; + pi[pcFace->mIndices[2]]++; + } + + // second pass: compute the final offset table + unsigned int iSum = 0; + unsigned int* piCurOut = this->mOffsetTable; + for (unsigned int* piCur = pi; piCur != piEnd;++piCur,++piCurOut) + { + unsigned int iLastSum = iSum; + iSum += *piCur; + *piCurOut = iLastSum; + } + pi = this->mOffsetTable; + + // third pass: compute the final table + this->mAdjacencyTable = new unsigned int[iSum]; + iSum = 0; + for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace,++iSum) + { + unsigned int idx = pcFace->mIndices[0]; + this->mAdjacencyTable[pi[idx]++] = iSum; + + idx = pcFace->mIndices[1]; + this->mAdjacencyTable[pi[idx]++] = iSum; + + idx = pcFace->mIndices[2]; + this->mAdjacencyTable[pi[idx]++] = iSum; + } + // fourth pass: undo the offset computations made during the third pass + // We could do this in a separate buffer, but this would be TIMES slower. + --this->mOffsetTable; + *this->mOffsetTable = 0u; +} +// ------------------------------------------------------------------------------------------------ +VertexTriangleAdjacency::~VertexTriangleAdjacency() +{ + // delete all allocated storage + delete[] this->mOffsetTable; + delete[] this->mAdjacencyTable; + delete[] this->mLiveTriangles; +} \ No newline at end of file diff --git a/code/VertexTriangleAdjacency.h b/code/VertexTriangleAdjacency.h new file mode 100644 index 000000000..72a604450 --- /dev/null +++ b/code/VertexTriangleAdjacency.h @@ -0,0 +1,126 @@ +/* +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. + +---------------------------------------------------------------------- +*/ + +/** @file Defines a helper class to compute a vertex-triangle adjacency map */ +#ifndef AI_VTADJACENCY_H_INC +#define AI_VTADJACENCY_H_INC + +#include "BaseProcess.h" +#include "../include/aiTypes.h" +#include "../include/aiAssert.h" + +struct aiMesh; + +namespace Assimp +{ + +// --------------------------------------------------------------------------- +/** The VertexTriangleAdjacency class computes a vertex-triangle + * adjacency map from a given index buffer. + * + * @note The input data is expected to be triangulated. + */ +class VertexTriangleAdjacency +{ +public: + + + /** Construction from an existing index buffer + * @param pcFaces Index buffer + * @param iNumFaces Number of faces in the buffer + * @param iNumVertices Number of referenced vertices. This value + * is computed automatically if 0 is specified. + * @param bComputeNumTriangles If you want the class to compute + * a list which contains the number of referenced triangles + * per vertex - pass true. + */ + VertexTriangleAdjacency(aiFace* pcFaces,unsigned int iNumFaces, + unsigned int iNumVertices = 0, + bool bComputeNumTriangles = true); + + + /** Destructor + */ + ~VertexTriangleAdjacency(); + + + /** Get all triangles adjacent to a vertex + * @param iVertIndex Index of the vertex + * @return A pointer to the adjacency list + */ + inline unsigned int* GetAdjacentTriangles(unsigned int iVertIndex) const + { + ai_assert(iVertIndex < iNumVertices); + + const unsigned int ofs = mOffsetTable[iVertIndex]; + return &mAdjacencyTable[ofs]; + } + + + /** Get the number of triangles that are referenced by + * a vertex. This function returns a reference that can be modified + * @param iVertIndex Index of the vertex + * @return Number of referenced triangles + */ + inline unsigned int& GetNumTrianglesPtr(unsigned int iVertIndex) + { + ai_assert(iVertIndex < iNumVertices && NULL != mLiveTriangles); + return mLiveTriangles[iVertIndex]; + } + + +public: + + //! Offset table + unsigned int* mOffsetTable; + + //! Adjacency table + unsigned int* mAdjacencyTable; + + //! Table containing the number of referenced triangles per vertex + unsigned int* mLiveTriangles; + + //! Debug: Number of referenced vertices + unsigned int iNumVertices; + +}; +} + +#endif // !! AI_VTADJACENCY_H_INC \ No newline at end of file diff --git a/include/aiMesh.h b/include/aiMesh.h index 2c16057ab..97d6ebe5e 100644 --- a/include/aiMesh.h +++ b/include/aiMesh.h @@ -391,10 +391,16 @@ struct aiMesh } } - //! Check whether the mesh contains positions. Should always return true + //! Check whether the mesh contains positions. If no special scene flags + //! are set this should always return true inline bool HasPositions() const { return mVertices != NULL; } + //! Check whether the mesh contains faces. If no special scene flags + //! are set this should always return true + inline bool HasFaces() const + { return mFaces != NULL; } + //! Check whether the mesh contains normal vectors inline bool HasNormals() const { return mNormals != NULL; } diff --git a/include/aiPostProcess.h b/include/aiPostProcess.h index 4adff7a26..e5b4b00ae 100644 --- a/include/aiPostProcess.h +++ b/include/aiPostProcess.h @@ -146,7 +146,15 @@ enum aiPostProcessSteps * however, it could be of interest for applications like editors * where stability is more important than loading performance. */ - aiProcess_ValidateDataStructure = 0x400 + aiProcess_ValidateDataStructure = 0x400, + + /** Reorders triangles for vertex cache locality and thus better performance. + * The step tries to improve the ACMR (average post-transform vertex cache + * miss ratio) for all meshes. The step runs in O(n) and is roughly + * basing on the algorithm described in this paper: + * http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf + */ + aiProcess_ImproveCacheLocality = 0x1600 }; // --------------------------------------------------------------------------- diff --git a/test/unit/ExecuteStepWin32.bat b/test/unit/ExecuteStepWin32.bat new file mode 100644 index 000000000..a288ef5e3 --- /dev/null +++ b/test/unit/ExecuteStepWin32.bat @@ -0,0 +1,28 @@ + + + +cd .. +cd .. +cd bin +cd unittest_release_win32 + +color 4e +cls + +@echo off + + +echo ---------------------------------------------------------------------- +echo _ +echo Open Asset Import Library - Unittests +echo _ +echo ---------------------------------------------------------------------- +echo _ +echo _ + +UnitTest.exe + +echo _ +echo ---------------------------------------------------------------------- + +pause \ No newline at end of file diff --git a/test/unit/ExecuteStepWin64.bat b/test/unit/ExecuteStepWin64.bat new file mode 100644 index 000000000..cd7c41f53 --- /dev/null +++ b/test/unit/ExecuteStepWin64.bat @@ -0,0 +1,28 @@ + + + +cd .. +cd .. +cd bin +cd unittest_release_x64 + +color 4e +cls + +@echo off + + +echo ---------------------------------------------------------------------- +echo _ +echo Open Asset Import Library - Unittests +echo _ +echo ---------------------------------------------------------------------- +echo _ +echo _ + +UnitTest.exe + +echo _ +echo ---------------------------------------------------------------------- + +pause \ No newline at end of file diff --git a/test/unit/Main.cpp b/test/unit/Main.cpp new file mode 100644 index 000000000..20b0e6f18 --- /dev/null +++ b/test/unit/Main.cpp @@ -0,0 +1,35 @@ + + +#include +#include +#include +#include +#include +#include + + +int main (int argc, char* argv[]) +{ + // Informiert Test-Listener ueber Testresultate + CPPUNIT_NS :: TestResult testresult; + + // Listener zum Sammeln der Testergebnisse registrieren + CPPUNIT_NS :: TestResultCollector collectedresults; + testresult.addListener (&collectedresults); + + // Listener zur Ausgabe der Ergebnisse einzelner Tests + CPPUNIT_NS :: BriefTestProgressListener progress; + testresult.addListener (&progress); + + // Test-Suite ueber die Registry im Test-Runner einfuegen + CPPUNIT_NS :: TestRunner testrunner; + testrunner.addTest (CPPUNIT_NS :: TestFactoryRegistry :: getRegistry ().makeTest ()); + testrunner.run (testresult); + + // Resultate im Compiler-Format ausgeben + CPPUNIT_NS :: CompilerOutputter compileroutputter (&collectedresults, std::cerr); + compileroutputter.write (); + + // Rueckmeldung, ob Tests erfolgreich waren + return collectedresults.wasSuccessful () ? 0 : 1; +} \ No newline at end of file diff --git a/test/unit/ut3DSLoader.cpp b/test/unit/ut3DSLoader.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/utASELoader.cpp b/test/unit/utASELoader.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/utFixInfacingNormals.cpp b/test/unit/utFixInfacingNormals.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/utGenNormals.cpp b/test/unit/utGenNormals.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/utGenSmoothNormals.cpp b/test/unit/utGenSmoothNormals.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/utImproveCacheLocality.cpp b/test/unit/utImproveCacheLocality.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/utJoinVertices.cpp b/test/unit/utJoinVertices.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/utLimitBoneWeights.cpp b/test/unit/utLimitBoneWeights.cpp new file mode 100644 index 000000000..b1cce97aa --- /dev/null +++ b/test/unit/utLimitBoneWeights.cpp @@ -0,0 +1,82 @@ + +#include "utLimitBoneWeights.h" + + +CPPUNIT_TEST_SUITE_REGISTRATION (LimitBoneWeightsTest); + +void LimitBoneWeightsTest :: setUp (void) +{ + // construct the process + this->piProcess = new LimitBoneWeightsProcess(); + + // now need to create a nice mesh for testing purposes + this->pcMesh = new aiMesh(); + + pcMesh->mNumVertices = 500; + pcMesh->mVertices = new aiVector3D[500]; // uninit. + pcMesh->mNumBones = 30; + pcMesh->mBones = new aiBone*[30]; + unsigned int iCur = 0; + for (unsigned int i = 0; i < 30;++i) + { + aiBone* pc = pcMesh->mBones[i] = new aiBone(); + pc->mNumWeights = 250; + pc->mWeights = new aiVertexWeight[pc->mNumWeights]; + for (unsigned int qq = 0; qq < pc->mNumWeights;++qq) + { + aiVertexWeight& v = pc->mWeights[qq]; + v.mVertexId = iCur++; + if (500 == iCur)iCur = 0; + v.mWeight = 1.0f / 15; // each vertex should occur once in two bones + } + } +} + +void LimitBoneWeightsTest :: tearDown (void) +{ + delete this->pcMesh; + delete this->piProcess; +} + +void LimitBoneWeightsTest :: testProcess(void) +{ + // execute the step on the given data + this->piProcess->ProcessMesh(this->pcMesh); + + // check whether everything is ok ... + typedef std::vector VertexWeightList; + VertexWeightList* asWeights = new VertexWeightList[pcMesh->mNumVertices]; + + for (unsigned int i = 0; i < pcMesh->mNumVertices;++i) + asWeights[i].reserve(4); + + // sort back as per-vertex lists + for (unsigned int i = 0; i < pcMesh->mNumBones;++i) + { + aiBone& pcBone = **(pcMesh->mBones+i); + for (unsigned int q = 0; q < pcBone.mNumWeights;++q) + { + aiVertexWeight weight = pcBone.mWeights[q]; + asWeights[weight.mVertexId].push_back(LimitBoneWeightsProcess::Weight (i,weight.mWeight)); + } + } + + // now validate the size of the lists and check whether all weights sum to 1.0f + for (unsigned int i = 0; i < pcMesh->mNumVertices;++i) + { + CPPUNIT_ASSERT( asWeights[i].size() <= 4 ); + float fSum = 0.0f; + for (VertexWeightList::const_iterator + iter = asWeights[i].begin(); + iter != asWeights[i].end();++iter) + { + fSum += (*iter).mWeight; + } + CPPUNIT_ASSERT( fSum >= 0.95 && fSum <= 1.04); + } + + // delete allocated storage + delete[] asWeights; + + // everything seems to be OK +} \ No newline at end of file diff --git a/test/unit/utLimitBoneWeights.h b/test/unit/utLimitBoneWeights.h new file mode 100644 index 000000000..c662b9b19 --- /dev/null +++ b/test/unit/utLimitBoneWeights.h @@ -0,0 +1,38 @@ +#ifndef TESTLBW_H +#define TESTLBW_H + +#include +#include + +#include +#include +#include +#include + + +using namespace std; +using namespace Assimp; + +class LimitBoneWeightsTest : public CPPUNIT_NS :: TestFixture +{ + CPPUNIT_TEST_SUITE (LimitBoneWeightsTest); + CPPUNIT_TEST (testProcess); + CPPUNIT_TEST_SUITE_END (); + + public: + void setUp (void); + void tearDown (void); + + protected: + + void testProcess (void); + + + private: + + LimitBoneWeightsProcess* piProcess; + aiMesh* pcMesh; + +}; + +#endif diff --git a/test/unit/utMDLLoader.cpp b/test/unit/utMDLLoader.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/utMaterialSystem.cpp b/test/unit/utMaterialSystem.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/utOBJLoader.cpp b/test/unit/utOBJLoader.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/utPretransformVertices.cpp b/test/unit/utPretransformVertices.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/utRemoveComments.cpp b/test/unit/utRemoveComments.cpp new file mode 100644 index 000000000..3f2e509a9 --- /dev/null +++ b/test/unit/utRemoveComments.cpp @@ -0,0 +1,61 @@ + + +#include "utRemoveComments.h" + + +CPPUNIT_TEST_SUITE_REGISTRATION (RemoveCommentsTest); + +void RemoveCommentsTest :: setUp (void) +{ + // nothing to do here +} + +void RemoveCommentsTest :: tearDown (void) +{ + // nothing to do here +} + +void RemoveCommentsTest :: testSingleLineComments (void) +{ + const char* szTest = "int i = 0; \n" + "if (4 == //)\n" + "\ttrue) { // do something here \n" + "\t// hello ... and bye //\n"; + + + char* szTest2 = new char[::strlen(szTest)+1]; + ::strcpy(szTest2,szTest); + + const char* szTestResult = "int i = 0; \n" + "if (4 == \n" + "\ttrue) { \n" + "\t \n"; + + CommentRemover::RemoveLineComments("//",szTest2,' '); + CPPUNIT_ASSERT(0 == ::strcmp(szTest2,szTestResult)); + + delete[] szTest2; +} + +void RemoveCommentsTest :: testMultiLineComments (void) +{ + char* szTest = + "/* comment to be removed */\n" + "valid text /* \n " + " comment across multiple lines */" + " / * Incomplete comment */ /* /* multiple comments */ */"; + + const char* szTestResult = + " \n" + "valid text " + " " + " / * Incomplete comment */ */"; + + char* szTest2 = new char[::strlen(szTest)+1]; + ::strcpy(szTest2,szTest); + + CommentRemover::RemoveMultiLineComments("/*","*/",szTest2,' '); + CPPUNIT_ASSERT(0 == ::strcmp(szTest2,szTestResult)); + + delete[] szTest2; +} \ No newline at end of file diff --git a/test/unit/utRemoveComments.h b/test/unit/utRemoveComments.h new file mode 100644 index 000000000..9ed17e2da --- /dev/null +++ b/test/unit/utRemoveComments.h @@ -0,0 +1,35 @@ +#ifndef REMOVECOMMENTS_H +#define REMOVECOMMENTS_H + +#include +#include + +#include "aiTypes.h" +#include + + +using namespace std; +using namespace Assimp; + +class RemoveCommentsTest : public CPPUNIT_NS :: TestFixture +{ + CPPUNIT_TEST_SUITE (RemoveCommentsTest); + CPPUNIT_TEST (testSingleLineComments); + CPPUNIT_TEST (testMultiLineComments); + CPPUNIT_TEST_SUITE_END (); + + public: + void setUp (void); + void tearDown (void); + + protected: + + void testSingleLineComments (void); + void testMultiLineComments (void); + + + private: + +}; + +#endif diff --git a/test/unit/utSplitLargeMeshes.cpp b/test/unit/utSplitLargeMeshes.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/utTextureTransform.cpp b/test/unit/utTextureTransform.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/utVertexTriangleAdjacency.cpp b/test/unit/utVertexTriangleAdjacency.cpp new file mode 100644 index 000000000..c2428688d --- /dev/null +++ b/test/unit/utVertexTriangleAdjacency.cpp @@ -0,0 +1,193 @@ + + + +#include "utVertexTriangleAdjacency.h" +#include +#include + +CPPUNIT_TEST_SUITE_REGISTRATION (VTAdjacency); + +void VTAdjacency :: setUp (void) +{ + // seed the randomizer + time_t t;time(&t); + srand((unsigned int)t); + + // build a test mesh with randomized input data + // ******************************************************************************* + pMesh = new aiMesh(); + + pMesh->mNumVertices = 500; + pMesh->mNumFaces = 600; + + pMesh->mFaces = new aiFace[600]; + unsigned int iCurrent = 0; + for (unsigned int i = 0; i < 600;++i) + { + aiFace& face = pMesh->mFaces[i]; + face.mNumIndices = 3; + face.mIndices = new unsigned int[3]; + + if (499 == iCurrent)iCurrent = 0; + face.mIndices[0] = iCurrent++; + + + while(face.mIndices[0] == ( face.mIndices[1] = unsigned int(((float)rand()/RAND_MAX)*499))); + while(face.mIndices[0] == ( face.mIndices[2] = unsigned int(((float)rand()/RAND_MAX)*499)) || + face.mIndices[1] == face.mIndices[2]); + } + + + // build a second test mesh - this one is extremely small + // ******************************************************************************* + pMesh2 = new aiMesh(); + + pMesh2->mNumVertices = 5; + pMesh2->mNumFaces = 3; + + pMesh2->mFaces = new aiFace[3]; + pMesh2->mFaces[0].mIndices = new unsigned int[3]; + pMesh2->mFaces[1].mIndices = new unsigned int[3]; + pMesh2->mFaces[2].mIndices = new unsigned int[3]; + + pMesh2->mFaces[0].mIndices[0] = 1; + pMesh2->mFaces[0].mIndices[1] = 3; + pMesh2->mFaces[0].mIndices[2] = 2; + + pMesh2->mFaces[1].mIndices[0] = 0; + pMesh2->mFaces[1].mIndices[1] = 2; + pMesh2->mFaces[1].mIndices[2] = 3; + + pMesh2->mFaces[2].mIndices[0] = 3; + pMesh2->mFaces[2].mIndices[1] = 0; + pMesh2->mFaces[2].mIndices[2] = 4; + + + // build a third test mesh which does not reference all vertices + // ******************************************************************************* + pMesh3 = new aiMesh(); + + pMesh3->mNumVertices = 500; + pMesh3->mNumFaces = 600; + + pMesh3->mFaces = new aiFace[600]; + iCurrent = 0; + for (unsigned int i = 0; i < 600;++i) + { + aiFace& face = pMesh3->mFaces[i]; + face.mNumIndices = 3; + face.mIndices = new unsigned int[3]; + + if (499 == iCurrent)iCurrent = 0; + face.mIndices[0] = iCurrent++; + + if (499 == iCurrent)iCurrent = 0; + face.mIndices[1] = iCurrent++; + + if (499 == iCurrent)iCurrent = 0; + face.mIndices[2] = iCurrent++; + + if (rand() > RAND_MAX/2 && face.mIndices[0]) + { + face.mIndices[0]--; + } + else if (face.mIndices[1]) face.mIndices[1]--; + } +} + +void VTAdjacency :: tearDown (void) +{ + delete pMesh; + pMesh = 0; + + delete pMesh2; + pMesh2 = 0; + + delete pMesh3; + pMesh3 = 0; +} + +void VTAdjacency :: largeRandomDataSet (void) +{ + checkMesh(pMesh); +} + +void VTAdjacency :: smallDataSet (void) +{ + checkMesh(pMesh2); +} + +void VTAdjacency :: unreferencedVerticesSet (void) +{ + checkMesh(pMesh3); +} + +void VTAdjacency :: checkMesh (aiMesh* pMesh) +{ + pAdj = new VertexTriangleAdjacency(pMesh->mFaces,pMesh->mNumFaces,pMesh->mNumVertices,true); + + + unsigned int* const piNum = pAdj->mLiveTriangles; + + // check the primary adjacency table and check whether all faces + // are contained in the list + unsigned int maxOfs = 0; + for (unsigned int i = 0; i < pMesh->mNumFaces;++i) + { + aiFace& face = pMesh->mFaces[i]; + for (unsigned int qq = 0; qq < 3 ;++qq) + { + const unsigned int idx = face.mIndices[qq]; + const unsigned int num = piNum[idx]; + + // go to this offset + const unsigned int ofs = pAdj->mOffsetTable[idx]; + maxOfs = std::max(ofs+num,maxOfs); + unsigned int* pi = &pAdj->mAdjacencyTable[ofs]; + + // and search for us ... + unsigned int tt = 0; + for (; tt < num;++tt,++pi) + { + if (i == *pi) + { + // mask our entry in the table. Finally all entries should be masked + *pi = 0xffffffff; + + // there shouldn't be two entries for the same face + break; + } + } + // assert if *this* vertex has not been found in the table + CPPUNIT_ASSERT(tt < num); + } + } + + // now check whether there are invalid faces + const unsigned int* pi = pAdj->mAdjacencyTable; + for (unsigned int i = 0; i < maxOfs;++i,++pi) + { + CPPUNIT_ASSERT(0xffffffff == *pi); + } + + // check the numTrianglesPerVertex table + for (unsigned int i = 0; i < pMesh->mNumFaces;++i) + { + aiFace& face = pMesh->mFaces[i]; + for (unsigned int qq = 0; qq < 3 ;++qq) + { + const unsigned int idx = face.mIndices[qq]; + + // we should not reach 0 here ... + CPPUNIT_ASSERT( 0 != piNum[idx]); + piNum[idx]--; + } + } + + // check whether we reached 0 in all entries + for (unsigned int i = 0; i < pMesh->mNumVertices;++i) + { + CPPUNIT_ASSERT(!piNum[i]); + } + delete pAdj; +} diff --git a/test/unit/utVertexTriangleAdjacency.h b/test/unit/utVertexTriangleAdjacency.h new file mode 100644 index 000000000..70334f89d --- /dev/null +++ b/test/unit/utVertexTriangleAdjacency.h @@ -0,0 +1,41 @@ +#ifndef VTADJ_H +#define VTADJ_H + +#include +#include + +#include "aiTypes.h" +#include "aiMesh.h" +#include + + +using namespace std; +using namespace Assimp; + +class VTAdjacency : public CPPUNIT_NS :: TestFixture +{ + CPPUNIT_TEST_SUITE (VTAdjacency); + CPPUNIT_TEST (largeRandomDataSet); + CPPUNIT_TEST (smallDataSet); + CPPUNIT_TEST (unreferencedVerticesSet); + CPPUNIT_TEST_SUITE_END (); + + public: + void setUp (void); + void tearDown (void); + + protected: + + void largeRandomDataSet (void); + void smallDataSet (void); + void unreferencedVerticesSet (void); + + void checkMesh(aiMesh* pMesh); + + private: + + VertexTriangleAdjacency* pAdj; + aiMesh* pMesh, *pMesh2, *pMesh3; +}; + +#endif diff --git a/tools/assimp_view/LogDisplay.cpp b/tools/assimp_view/LogDisplay.cpp index d4e48faf0..b56fbf4cc 100644 --- a/tools/assimp_view/LogDisplay.cpp +++ b/tools/assimp_view/LogDisplay.cpp @@ -107,15 +107,18 @@ void CLogDisplay::OnRender() unsigned int iCnt = 0; RECT sRect; - sRect.left = 0; + sRect.left = 10; sRect.top = 10; - + RECT sWndRect; GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sWndRect); sWndRect.right -= sWndRect.left; sWndRect.bottom -= sWndRect.top; sWndRect.left = sWndRect.top = 0; + sRect.right = sWndRect.right - 30; + sRect.bottom = sWndRect.bottom; + // if no asset is loaded draw a "no asset loaded" text in the center if (!g_pcAsset) { @@ -153,9 +156,6 @@ void CLogDisplay::OnRender() -1,&sWndRect,DT_CENTER | DT_VCENTER,D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0xFF)); } - sRect.right = sWndRect.right - 30; - sRect.bottom = sWndRect.bottom; - // update all elements in the queue and render them for (std::list::iterator i = this->asEntries.begin(); diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index 04d0cc55a..df41bd166 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -56,6 +56,8 @@ std::vector g_aPreviousFiles; // history menu item HMENU g_hHistoryMenu = NULL; +float g_fACMR = 3.0f; + #define AI_VIEW_NUM_RECENT_FILES 0x8 #define AI_VIEW_RECENT_FILE_ID(_n_) (5678 + _n_) @@ -2252,9 +2254,11 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, } } + // render the scene CDisplay::Instance().OnRender(); + g_dCurTime = timeGetTime(); g_fElpasedTime = (float)((g_dCurTime - g_dLastTime) * 0.001); g_dLastTime = g_dCurTime; diff --git a/tools/assimp_view/assimp_view.aps b/tools/assimp_view/assimp_view.aps index da92ad50e78d9b25962e5eaa26c77ac442bf2abf..0cbec45248cc9d3dfe4135a64e1678abc147acce 100644 GIT binary patch delta 6318 zcmai2e~cVe9e*>s@3um@_Mq3^&vI?AO`+{|XLs*c3xV0$x!vJrXSTDmy=!S5F@hz? zNh&oO(M2GFiiNT?4^0z;K~o|WDwsoJ(pHR=HaYGODH=53A13t=kzXQ4&HDYm_hxrz z+v=s;H}CU4-|zdr?~nIp-jN@7KeX8W=#VmfXw9(t8Or{26TLc--gEc<19NvUWty&C zLiTkMGE4{?_vqmKCmZR$PGu##Wt{f2yF9vNe#r#wQ4?FQ6r?JUSZ*5~jVNJ9EUqFylbV0ar2Et;>9zv>W(1kP z%%UGFtx%=4vzC2zx@FFa<#Xoj%oL+ZDn(QHW zll|lXnIm_wv*Yyo0YX%@U3`laXWO>XHN#qlXvqm;<*cAw)NPxLLO%`tT%c#&il237 z30vGwyQ?sePVoWT)pI#Zx7|Fl)1!jDvtZgK1V%HGmEUQZGsHJ%eakWIO3ox2iF8xZ zZkiBn3^+T>!A{dFTdosW&Xh}XX4%SD9sZoJSUJv(Ti?Z@aVg~ZrpEzv0LXZzlQTWb$#Za0fMs9z%Oq8Wg~`eMSsWkL z#Q2oxp=&^eQm|f}$O{UUoamzSdAF#Sry(~!>}pSdkw*SNZt%ZnLB^d1&nq#a z5d2a2bwmPD#Yg}{fsxBepqI*l;|9ek1A|IHfuTEwX~SAUJ@kU&F3WHo=<`uXCeJ5n zG3c4Tw+j}@nO5F$Jrfd#_jW;G$Hb%Kl5z25*lxMYBom^?^K6nRY~UI?*vGZEBr9ew z@L(Cty@q!8^JfJt3KJaDor5aVVB@TE1?XtVFHbK*lBR%wYsdv6%W(+MNg)=85eTfz zILtt>;w;l6~!@-zn&~>;lf6c8EJD)!E`u*vW#yIMxaVH6yX z;eaVcEpi0aTq#hfN32aQdsU0<1TWH17U~phma|s0uqFYPZpv0=0doXr=x!lmwLw{j z`gmn?0EsJsmIUto6p;3u`EH9!Zej!NUvlvtkOVmXDp~W0k^T!2up_;k`24i zY6-WoAtjPnaqP~`v^US~ZJ8O8AeoezZ3KG7cRd%jQ$DlwkYK~!08HtLI6JkOUL|rt z3_F$Lly1P*03=xfjRCNY<1OWB1XCr%AYv^RnG%#aAQYG&j!apW62!@1!%u3mU?dEu z5+_GY=iz`PPHGTe5f0nR7yQOb5pQ}e%?G)4;c|JTN}ikd%yM&}in}nz5VsHC!i_1Z z$&`@x;0U4-mvDQaY?4|dV|Kf4Q36dvI1frBnQEkw?au6|=(gqW0=SBJlMW$3Ph&2n z8o2~uxuC&BQT2~)IhaJ4nvhDQ;ke=+;Yh@ zDz@%Pn9s|Ok3`c3NG3Wc74fv;7PBs&J>t!h1?Lbf1^M7m5y^5xMI^n-VvkIQo4<$$ zN2~cPXutzNXfXL3K?D(=K~LgoAZf6{M*!b5O*AqcO+oM+M`a4){$d1KyOQOz!h#@e zLdRuo9sZ$?#(E%NXb*-fJW7P^w&B{YhpID?FbW)P#j~WTn=fm|LGOmAicnM)5@{TW z)QJt*ZDRT05zGqS!%5n&5Oy?42VJfO&+3rAqhi6!3ee>W_?UPh=CG`20rU3} zB+GU6u((DybO@zvvqt;FXG^1N!sjov;NRBh>Yk<%#arhN;4~9FJJ{Frw0AvrWhS&5 zTHw6UO7^}+`w~(SJ26F9Ek(J8U0YJLH=MtaqJs_UbyIZU3Z%*`?;-47DLpB7fgbiu ziVlU+3n{v~Aw86*-8j)?XdqjfrUTbD7ZjAy%t^UF2Ei1RWmY$)ISSS>Crwv1)V-Cb z{al?4Zx8!!n)X4gev+oc(3}P3;&9-eF!PQ%ZRgE=V8VZ(aw0svf`Yj#@Jx8^H%yL8 z`|zaYVx*BzbXH*}vM(Mgx z*W74R@8d1_FIw=oTk!Z8T_4JB8Vhr?mlek75IFbtF}gM!{@xh9S~!}U>6YLWvUZzL zOyWT|iXPe;?&3Tg;b4OWZuD}VKEs(|rsA?MU}jw(^LZlGQeIX36okFe(BasyU4x%a z!Ib6XjEV=}Ydm`4{w^xxBK&YFu3c_2mn5U|tXUSC_l8LrvAArQj+yuLlCZZ?H5kms zkocemMJ2afwz76pAUrmD*n9A1x1o7h;QOs*kS!4WIQbNOiLHVb-vduMVj(e>5Q%i3tout3^?8!~a%G&Qw4&D$Q9Z>to3bKT}AH(~I`$&=80yhs|BHOt5 zfrzF7HBDC3Mo(4L2kNzlPi57|>b1pFE8!jsCGkhdq52CSof=XG20`aPrB0vRPVOYP zN}V8-d}XJ4s9t;Mm0zI>``72-dk4jDhUxe6i4R96zDAvg57i~W33)S@;GJsYF zVpl6s)rT&^(c4r%7U6UeQhEbSRLDLhG!Y1mzgX?huWAh&E;PNM>g2Njv%I|e89G@(_M|~5H{3aJbg?(Qm=jPwK2G|sU3j^dcS>b1e^F7-ek_Kh2H(M zXC9nAqrgvvUu=H%O#Gftua76%?|{OaAGjcttDk1nrt1=T!Tche$auk=SP6qSE+gz_ z?BK2PJza$1t#TD_B^TF`|9LBkSC99=Wp(rBGQ4_B#KT!XgpfS7p_Oyt?bLZ7zXaQG zy&i)fgb&QyZqqLH4*h@~#P@JtaV-F;hT6LkncH8S$CN{!8cr>A~pSnO_ak;|Ix>S!1F9o?09aQa~v5^wY_3t;C zgY7f_VRO*N_NHf=n1k(bmCa#$ l^8ae*uw!Nv!|? delta 1895 zcma)7Z%|ZK6hHUAy)5k3E(S$vNGbJC24}7SZ8cj(uF^t!_``%lDv8g+A_nh`)U zkem#W54t9%N*vQ9&Y0x$8%-8+fj@TZEgl@R@e8*qC;-nHZ{g?19PCHpfQ9_C@p&FE zB*LfyplL1e1k}J5sE3zeDJ1bTW2qh=RY66??}lP6DqfbnWSNgH1~)Idy-}tP-(H>z z@#X+1185}W)Pt#IYl%%E1)uyCAY=ibGvSfr3MZbHrgP$JY0B>m*>!a#tc5B$4PW!O zEskx{G53S?4A`--SZd5&3B`uGXNr1VTzz?ldX1sJIz?R;SN}Rg{gk0DoV;5}k)fVT z?PPi-6^6QP(w1VbYA_J;ROKKFclpTI$(Y={872ubn9Xj<1@0eZUT&)rn(JMl7(?=9VOT)b_KiT zL>*;sJk!zcBlP2sUT}~D-0$?JpfJ|t+GMj@_+WM+zEw}ovPjUGLFs-MuW+e^^6f5( z;~VBbxE?XQf|MnO7fv~@dy!XCk0=IMnqF>r7t@NAw9hS%zO*zkVxmSge2DH<8N+I#X*V9$`ZX28!q9|CRL0eW1$RM8yE`l?CZFZN1u zeiP3;p^DRz{Nu1mI>mq_PaWq+e^a~bu*Bk%BDYSKc#=nN;8G+O_)3H%7XC)OO$n|= zf~PKtqZSNK%V79h5oH*RV4(CzL9DN5UeTLCQmnWt#Opg0l_5E}LgY5E zOeLd45%wmTt9%kWHASS_T%4G@lwX0b@~4RF?nS^ diff --git a/tools/assimp_view/assimp_view.cpp b/tools/assimp_view/assimp_view.cpp index 2ea7a27a6..76e93ec75 100644 --- a/tools/assimp_view/assimp_view.cpp +++ b/tools/assimp_view/assimp_view.cpp @@ -133,7 +133,7 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter) aiProcess_GenSmoothNormals | // generate smooth normal vectors if not existing aiProcess_ConvertToLeftHanded | // convert everything to D3D left handed space aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into submeshes - aiProcess_ValidateDataStructure); // validate the output data structure + aiProcess_ValidateDataStructure | aiProcess_ImproveCacheLocality); // validate the output data structure // get the end time of zje operation, calculate delta t double fEnd = (double)timeGetTime(); @@ -871,6 +871,7 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/) sParams.BackBufferWidth = (UINT)sRect.right; sParams.BackBufferHeight = (UINT)sRect.bottom; sParams.SwapEffect = D3DSWAPEFFECT_DISCARD; + sParams.BackBufferCount = 1; // check whether we can use a D32 depth buffer format if (SUCCEEDED ( g_piD3D->CheckDepthStencilMatch(0,eType, diff --git a/tools/assimp_view/assimp_view.h b/tools/assimp_view/assimp_view.h index 1c8a80a11..605e07072 100644 --- a/tools/assimp_view/assimp_view.h +++ b/tools/assimp_view/assimp_view.h @@ -251,6 +251,10 @@ enum EClickPos // HUD texture // extern unsigned char* g_szImageMask /*= NULL*/; + + + extern float g_fACMR /*= 3.0f*/; + extern IDirect3DQuery9* g_piQuery; }; #endif // !! AV_MAIN_H_INCLUDED \ No newline at end of file diff --git a/tools/assimp_view/assimp_view.rc b/tools/assimp_view/assimp_view.rc index 6cf1c1c09..416c48110 100644 --- a/tools/assimp_view/assimp_view.rc +++ b/tools/assimp_view/assimp_view.rc @@ -56,7 +56,7 @@ BEGIN END IDD_DIALOGMAIN DIALOGEX 0, 0, 594, 384 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES CAPTION "Open Asset Import Library - ModelViewer " MENU IDR_MENU1 @@ -66,10 +66,10 @@ BEGIN CONTROL "MultiSample image",IDC_TOGGLEMS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,173,80,10 CONTROL "Toggle Wireframe",IDC_TOGGLEWIRE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,183,73,10 CONTROL "Disable Materials",IDC_TOGGLEMAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,193,69,10 - LTEXT "Verts:",IDC_NUMVERTS,475,14,47,8 - LTEXT "Faces:\t",IDC_NUMFACES,539,14,27,8 - LTEXT "Mats:",IDC_NUMMATS,540,26,26,8 - LTEXT "FPS:",IDC_FPS,540,51,21,8 + LTEXT "Verts:",IDC_NUMVERTS,475,14,27,8 + LTEXT "Faces:\t",IDC_NUMFACES,539,14,22,8 + LTEXT "Mats:",IDC_NUMMATS,540,26,20,8 + LTEXT "FPS:",IDC_FPS,540,51,20,8 CONTROL "Display Normals",IDC_TOGGLENORMALS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,203,66,10 CONTROL "Toggle AutoRotate",IDC_AUTOROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,257,74,10 CONTROL 130,IDC_STATIC,"Static",SS_BITMAP,0,360,600,25 @@ -79,7 +79,7 @@ BEGIN EDITTEXT IDC_EFPS,562,50,29,12,ES_AUTOHSCROLL | ES_READONLY CONTROL "Rotate light sources",IDC_LIGHTROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,276,74,10 CONTROL "2 directional lights",IDC_3LIGHTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,213,73,10 - LTEXT "Time:",IDC_LOADTIME,475,51,46,8 + LTEXT "Time:",IDC_LOADTIME,475,51,29,8 EDITTEXT IDC_ELOAD,504,50,32,12,ES_AUTOHSCROLL | ES_READONLY CONTROL "Zoom/Rotate",IDC_ZOOM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,267,58,10 CONTROL "Low quality lighting",IDC_LOWQUALITY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,223,74,10 diff --git a/tools/assimp_view/resource.h b/tools/assimp_view/resource.h index fc279e9b2..33d69afca 100644 --- a/tools/assimp_view/resource.h +++ b/tools/assimp_view/resource.h @@ -151,6 +151,14 @@ #define ID_SOLONG_SETSHADINGMODE 32820 #define ID_SETSHADINGMODE_GOURAUD 32821 #define ID_SETSHADINGMODE_PHONG 32822 +#define ID_OPTIMIZE_OPTIMIZEACMR 32823 +#define ID_OPTIMIZE_OPTIMIZEOVERDRAW 32824 +#define ID_OPTIMIZE_OPTIMIZEBOTH 32825 +#define ID_VERTEXCACHELOCALITY_FINDCURRENT 32826 +#define ID_VERTEXCACHELOCALITY_OPTIMIZE 32827 +#define ID_VERTEXCACHELOCALITY_FINDBEST 32828 +#define ID_OPTIMIZE_SCENEGRAPH 32829 +#define ID_SCENEGRAPH_SMALLESTPOSSIBLEGRAPH 32830 #define IDC_STATIC -1 // Next default values for new objects @@ -158,9 +166,9 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NO_MFC 1 -#define _APS_NEXT_RESOURCE_VALUE 158 -#define _APS_NEXT_COMMAND_VALUE 32823 -#define _APS_NEXT_CONTROL_VALUE 1049 +#define _APS_NEXT_RESOURCE_VALUE 159 +#define _APS_NEXT_COMMAND_VALUE 32831 +#define _APS_NEXT_CONTROL_VALUE 1052 #define _APS_NEXT_SYMED_VALUE 110 #endif #endif diff --git a/workspaces/vc8/UnitTest.vcproj b/workspaces/vc8/UnitTest.vcproj new file mode 100644 index 000000000..17646553e --- /dev/null +++ b/workspaces/vc8/UnitTest.vcproj @@ -0,0 +1,762 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/workspaces/vc8/assimp.sln b/workspaces/vc8/assimp.sln index 5b612c09f..fe4a20120 100644 --- a/workspaces/vc8/assimp.sln +++ b/workspaces/vc8/assimp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "assimp_view", "assimp_view.vcproj", "{B17B959B-BB8A-4596-AF0F-A8C8DBBC3C5E}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssimpView", "assimp_view.vcproj", "{B17B959B-BB8A-4596-AF0F-A8C8DBBC3C5E}" ProjectSection(WebsiteProperties) = preProject Debug.AspNetCompiler.Debug = "True" Release.AspNetCompiler.Debug = "False" @@ -10,12 +10,21 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "assimp_view", "assimp_view. {5691E159-2D9B-407F-971F-EA5C592DC524} = {5691E159-2D9B-407F-971F-EA5C592DC524} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "assimp", "assimp.vcproj", "{5691E159-2D9B-407F-971F-EA5C592DC524}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Assimp", "assimp.vcproj", "{5691E159-2D9B-407F-971F-EA5C592DC524}" ProjectSection(WebsiteProperties) = preProject Debug.AspNetCompiler.Debug = "True" Release.AspNetCompiler.Debug = "False" EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTest", "UnitTest.vcproj", "{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {5691E159-2D9B-407F-971F-EA5C592DC524} = {5691E159-2D9B-407F-971F-EA5C592DC524} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_DLL_Java|Win32 = Debug_DLL_Java|Win32 @@ -80,6 +89,30 @@ Global {5691E159-2D9B-407F-971F-EA5C592DC524}.Release|Win32.Build.0 = Release|Win32 {5691E159-2D9B-407F-971F-EA5C592DC524}.Release|x64.ActiveCfg = Release|x64 {5691E159-2D9B-407F-971F-EA5C592DC524}.Release|x64.Build.0 = Release|x64 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL_Java|Win32.ActiveCfg = Debug_DLL|Win32 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL_Java|Win32.Build.0 = Debug_DLL|Win32 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL_Java|x64.ActiveCfg = Debug_DLL|x64 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL_Java|x64.Build.0 = Debug_DLL|x64 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL|Win32.ActiveCfg = Debug_DLL|Win32 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL|Win32.Build.0 = Debug_DLL|Win32 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL|x64.ActiveCfg = Debug_DLL|x64 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL|x64.Build.0 = Debug_DLL|x64 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug|Win32.ActiveCfg = Debug|Win32 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug|Win32.Build.0 = Debug|Win32 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug|x64.ActiveCfg = Debug|x64 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug|x64.Build.0 = Debug|x64 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL_Java|Win32.ActiveCfg = Release_DLL|Win32 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL_Java|Win32.Build.0 = Release_DLL|Win32 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL_Java|x64.ActiveCfg = Release_DLL|x64 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL_Java|x64.Build.0 = Release_DLL|x64 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL|Win32.ActiveCfg = Release_DLL|Win32 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL|Win32.Build.0 = Release_DLL|Win32 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL|x64.ActiveCfg = Release_DLL|x64 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL|x64.Build.0 = Release_DLL|x64 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release|Win32.ActiveCfg = Release|Win32 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release|Win32.Build.0 = Release|Win32 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release|x64.ActiveCfg = Release|x64 + {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/workspaces/vc8/assimp.vcproj b/workspaces/vc8/assimp.vcproj index bf3227b72..d64e8937d 100644 --- a/workspaces/vc8/assimp.vcproj +++ b/workspaces/vc8/assimp.vcproj @@ -2,7 +2,7 @@ @@ -1014,6 +1014,10 @@ RelativePath="..\..\code\GenVertexNormalsProcess.h" > + + @@ -1070,6 +1074,10 @@ RelativePath="..\..\code\ValidateDataStructure.h" > + + @@ -1342,6 +1350,10 @@ RelativePath="..\..\code\Importer.cpp" > + + @@ -1386,6 +1398,10 @@ RelativePath="..\..\code\ValidateDataStructure.cpp" > + + diff --git a/workspaces/vc8/assimp_view.vcproj b/workspaces/vc8/assimp_view.vcproj index 8da1e1fd0..9d24c8955 100644 --- a/workspaces/vc8/assimp_view.vcproj +++ b/workspaces/vc8/assimp_view.vcproj @@ -2,7 +2,7 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + +