diff --git a/code/ImproveCacheLocality.cpp b/code/ImproveCacheLocality.cpp
index 698af7816..a60e3dac1 100644
--- a/code/ImproveCacheLocality.cpp
+++ b/code/ImproveCacheLocality.cpp
@@ -39,12 +39,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-/** @file Implementation of the post processing to improve the
- * cache locality of a mesh.
+/** @file Implementation of the post processing step to improve the cache locality of a mesh.
*
* The algorithm is roughly basing on this paper:
* http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf
- * ... TODO: implement overdraw reduction
+ * .. although overdraw rduction isn't implemented yet ...
*/
#include "AssimpPCH.h"
@@ -79,7 +78,7 @@ bool ImproveCacheLocalityProcess::IsActive( unsigned int pFlags) const
// Setup configuration
void ImproveCacheLocalityProcess::SetupProperties(const Importer* pImp)
{
- // AI_CONFIG_PP_ICL_PTCACHE_SIZE
+ // AI_CONFIG_PP_ICL_PTCACHE_SIZE controls the target cache size for the optimizer
configCacheDepth = pImp->GetPropertyInteger(AI_CONFIG_PP_ICL_PTCACHE_SIZE,PP_ICL_PTCACHE_SIZE);
}
@@ -118,11 +117,12 @@ void ImproveCacheLocalityProcess::Execute( aiScene* pScene)
// Improves the cache coherency of a specific mesh
float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshNum)
{
+ // TODO: rewrite this to use std::vector or boost::shared_array
ai_assert(NULL != pMesh);
- // check whether the input data is valid ->
- // - there must be vertices and faces (haha)
- // - all faces must be triangulated
+ // Check whether the input data is valid
+ // - there must be vertices and faces
+ // - all faces must be triangulated or we can't operate on them
if (!pMesh->HasFaces() || !pMesh->HasPositions())
return 0.f;
@@ -135,32 +135,32 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
const aiFace* const pcEnd = pMesh->mFaces+pMesh->mNumFaces;
// Input ACMR is for logging purposes only
- if (!DefaultLogger::isNullLogger())
- {
+ if (!DefaultLogger::isNullLogger()) {
+
unsigned int* piFIFOStack = new unsigned int[configCacheDepth];
- ::memset(piFIFOStack,0xff,configCacheDepth*sizeof(unsigned int));
+ memset(piFIFOStack,0xff,configCacheDepth*sizeof(unsigned int));
unsigned int* piCur = piFIFOStack;
const unsigned int* const piCurEnd = piFIFOStack + configCacheDepth;
// count the number of cache misses
unsigned int iCacheMisses = 0;
- for (const aiFace* pcFace = pMesh->mFaces;pcFace != pcEnd;++pcFace)
- {
- for (unsigned int qq = 0; qq < 3;++qq)
- {
+ for (const aiFace* pcFace = pMesh->mFaces;pcFace != pcEnd;++pcFace) {
+
+ for (unsigned int qq = 0; qq < 3;++qq) {
bool bInCache = false;
- for (unsigned int* pp = piFIFOStack;pp < piCurEnd;++pp)
- {
+
+ for (unsigned int* pp = piFIFOStack;pp < piCurEnd;++pp) {
if (*pp == pcFace->mIndices[qq]) {
// the vertex is in cache
bInCache = true;
break;
}
}
- if (!bInCache)
- {
+ if (!bInCache) {
++iCacheMisses;
- if (piCurEnd == piCur)piCur = piFIFOStack;
+ if (piCurEnd == piCur) {
+ piCur = piFIFOStack;
+ }
*piCur++ = pcFace->mIndices[qq];
}
}
@@ -171,9 +171,9 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
char szBuff[128]; // should be sufficiently large in every case
// the JoinIdenticalVertices process has not been executed on this
- // mesh, otherwise this value would normally be at least minimally#
+ // mesh, otherwise this value would normally be at least minimally
// smaller than 3.0 ...
- ::sprintf(szBuff,"Mesh %i: Not suitable for vcache optimization",meshNum);
+ sprintf(szBuff,"Mesh %i: Not suitable for vcache optimization",meshNum);
DefaultLogger::get()->warn(szBuff);
return 0.f;
}
@@ -184,12 +184,11 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
// 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));
+ 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
+ // 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;
@@ -204,21 +203,21 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
// 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,
+ 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;
- {
+ // 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)
+ for (;piCur != piCurEnd;++piCur) {
iMaxRefTris = std::max(iMaxRefTris,*piCur);
+ }
}
unsigned int* piCandidates = new unsigned int[iMaxRefTris*3];
unsigned int iCacheMisses = 0;
+ // ...................................................................................
/** PSEUDOCODE for the algorithm
A = Build-Adjacency(I) Vertex-triangle adjacency
@@ -246,33 +245,31 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
f = Get-Next-Vertex(I,i,k,N,C,s,L,D)
return O
*/
+ // ...................................................................................
int ivdx = 0;
int ics = 1;
int iStampCnt = configCacheDepth+1;
- while (ivdx >= 0)
- {
+ 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)
- {
+ 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])
- {
+ 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)
- {
+ for (unsigned int* p = pcFace->mIndices, *p2 = pcFace->mIndices+3;p != p2;++p) {
const unsigned int dp = *p;
// the current vertex won't have any free triangles after this step
- if (ivdx != (int)dp)
- {
+ if (ivdx != (int)dp) {
// append the vertex to the dead-end stack
sDeadEndVStack.push(dp);
@@ -287,8 +284,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
*piCSIter++ = dp;
// if the vertex is not yet in cache, set its cache count
- if (iStampCnt-piCachingStamps[dp] > configCacheDepth)
- {
+ if (iStampCnt-piCachingStamps[dp] > configCacheDepth) {
piCachingStamps[dp] = iStampCnt++;
++iCacheMisses;
}
@@ -304,52 +300,45 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
// get next fanning vertex
ivdx = -1;
int max_priority = -1;
- for (unsigned int* piCur = piCandidates;piCur != piCurCandidate;++piCur)
- {
+ for (unsigned int* piCur = piCandidates;piCur != piCurCandidate;++piCur) {
register const unsigned int dp = *piCur;
// must have live triangles
- if (piNumTriPtr[dp] > 0)
- {
+ 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] <= configCacheDepth)
+ if ((tmp = iStampCnt-piCachingStamps[dp]) + 2*piNumTriPtr[dp] <= configCacheDepth) {
priority = tmp;
+ }
+
// keep best candidate
- if (priority > max_priority)
- {
+ 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())
- {
+ 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)
- {
+ 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)
- {
+ 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)
- {
+ if (piNumTriPtr[ics] > 0) {
ivdx = ics;
break;
}
@@ -358,8 +347,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
}
}
float fACMR2 = 0.0f;
- if (!DefaultLogger::isNullLogger())
- {
+ if (!DefaultLogger::isNullLogger()) {
fACMR2 = (float)iCacheMisses / pMesh->mNumFaces;
// very intense verbose logging ... prepare for much text if there are many meshes
@@ -375,8 +363,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
}
// sort the output index buffer back to the input array
piCSIter = piIBOutput;
- for (aiFace* pcFace = pMesh->mFaces; pcFace != pcEnd;++pcFace)
- {
+ for (aiFace* pcFace = pMesh->mFaces; pcFace != pcEnd;++pcFace) {
pcFace->mIndices[0] = *piCSIter++;
pcFace->mIndices[1] = *piCSIter++;
pcFace->mIndices[2] = *piCSIter++;
diff --git a/tools/assimp_view/Material.cpp b/tools/assimp_view/Material.cpp
index cde8d38b6..2d9e95d2f 100644
--- a/tools/assimp_view/Material.cpp
+++ b/tools/assimp_view/Material.cpp
@@ -219,9 +219,8 @@ bool CMaterialManager::TryLongerPath(char* szTemp,aiString* p_szString)
int CMaterialManager::FindValidPath(aiString* p_szString)
{
ai_assert(NULL != p_szString);
-
- if ('*' == p_szString->data[0])
- {
+ aiString pcpy = *p_szString;
+ if ('*' == p_szString->data[0]) {
// '*' as first character indicates an embedded file
return 5;
}
@@ -231,10 +230,10 @@ int CMaterialManager::FindValidPath(aiString* p_szString)
if (pFile)fclose(pFile);
else
{
- // check whether we can use the directory of
- // the asset as relative base
- char szTemp[MAX_PATH*2];
+ // check whether we can use the directory of the asset as relative base
+ char szTemp[MAX_PATH*2], tmp2[MAX_PATH*2];
strcpy(szTemp, g_szFileName);
+ strcpy(tmp2,szTemp);
char* szData = p_szString->data;
if (*szData == '\\' || *szData == '/')++szData;
@@ -249,6 +248,7 @@ int CMaterialManager::FindValidPath(aiString* p_szString)
*szEnd = 0;
strcat(szEnd,szData);
+
pFile = fopen(szTemp,"rb");
if (!pFile)
{
@@ -281,6 +281,24 @@ int CMaterialManager::FindValidPath(aiString* p_szString)
{
if(TryLongerPath(szTemp, p_szString))return 1;
}
+
+ // patch by mark sibly to look for textures files in the asset's base directory.
+ const char *path=pcpy.data;
+ const char *p=strrchr( path,'/' );
+ if( !p ) p=strrchr( path,'\\' );
+ if( p ){
+ char *q=strrchr( tmp2,'/' );
+ if( !q ) q=strrchr( tmp2,'\\' );
+ if( q ){
+ strcpy( q+1,p+1 );
+ if(pFile=fopen( tmp2,"r" ) ){
+ fclose( pFile );
+ strcpy(p_szString->data,tmp2);
+ p_szString->length = strlen(tmp2);
+ return 1;
+ }
+ }
+ }
return 0;
}
}
@@ -292,6 +310,7 @@ int CMaterialManager::FindValidPath(aiString* p_szString)
iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
memcpy(p_szString->data,szTemp,iLen2);
p_szString->length = iLen;
+
}
return 1;
}