Changed some runtime asserts to boost::static_asserts.
Added FindInstances postprocessing step. Not fully tested yet, but seems to work well. Enabled it for the viewer, too. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@327 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
0c6894f6f9
commit
4b4526953e
|
@ -108,6 +108,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
# include "../include/BoostWorkaround/boost/scoped_array.hpp"
|
||||
# include "../include/BoostWorkaround/boost/format.hpp"
|
||||
# include "../include/BoostWorkaround/boost/foreach.hpp"
|
||||
# include "../include/BoostWorkaround/boost/static_assert.hpp"
|
||||
|
||||
#else
|
||||
|
||||
|
@ -115,6 +116,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
# include <boost/scoped_array.hpp>
|
||||
# include <boost/format.hpp>
|
||||
# include <boost/foreach.hpp>
|
||||
# include <boost/static_assert.hpp>
|
||||
|
||||
#endif // ! ASSIMP_BUILD_BOOST_WORKAROUND
|
||||
#endif // !! ASSIMP_PCH_INCLUDED
|
||||
|
|
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
---------------------------------------------------------------------------
|
||||
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 FindInstancesProcess.cpp
|
||||
* @brief Implementation of the aiProcess_FindInstances postprocessing step
|
||||
*/
|
||||
|
||||
#include "AssimpPCH.h"
|
||||
#include "FindInstancesProcess.h"
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
FindInstancesProcess::FindInstancesProcess()
|
||||
{}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
FindInstancesProcess::~FindInstancesProcess()
|
||||
{}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
bool FindInstancesProcess::IsActive( unsigned int pFlags) const
|
||||
{
|
||||
return 0 != (pFlags & aiProcess_FindInstances);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Compare the bones of two meshes
|
||||
bool CompareBones(const aiMesh* orig, const aiMesh* inst)
|
||||
{
|
||||
for (unsigned int i = 0; i < orig->mNumBones;++i) {
|
||||
aiBone* aha = orig->mBones[i];
|
||||
aiBone* oha = inst->mBones[i];
|
||||
|
||||
if (aha->mNumWeights != oha->mNumWeights ||
|
||||
aha->mOffsetMatrix != oha->mOffsetMatrix ||
|
||||
aha->mNumWeights != oha->mNumWeights) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// compare weight per weight ---
|
||||
for (unsigned int n = 0; n < aha->mNumWeights;++n) {
|
||||
if (aha->mWeights[n].mVertexId != oha->mWeights[n].mVertexId ||
|
||||
(aha->mWeights[n].mWeight - oha->mWeights[n].mWeight) < 10e-3f) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Update mesh indices in the node graph
|
||||
void UpdateMeshIndices(aiNode* node, unsigned int* lookup)
|
||||
{
|
||||
for (unsigned int n = 0; n < node->mNumMeshes;++n)
|
||||
node->mMeshes[n] = lookup[node->mMeshes[n]];
|
||||
|
||||
for (unsigned int n = 0; n < node->mNumChildren;++n)
|
||||
UpdateMeshIndices(node->mChildren[n],lookup);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void FindInstancesProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
DefaultLogger::get()->debug("FindInstancesProcess begin");
|
||||
if (pScene->mNumMeshes) {
|
||||
|
||||
// use a pseudo hash for all meshes in the scene to quickly find
|
||||
// the ones which are possibly equal. This step is executed early
|
||||
// in the pipeline, so we could, depending on the file format,
|
||||
// have several thousand small meshes. That's too much for a brute
|
||||
// everyone-against-everyone check involving up to 25 comparisons
|
||||
// each.
|
||||
boost::scoped_array<uint64_t> hashes (new uint64_t[pScene->mNumMeshes]);
|
||||
boost::scoped_array<unsigned int> remapping (new unsigned int[pScene->mNumMeshes]);
|
||||
|
||||
unsigned int numMeshesOut = 0;
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||
|
||||
aiMesh* inst = pScene->mMeshes[i];
|
||||
hashes[i] = GetMeshHash(inst);
|
||||
|
||||
for (int a = i-1; a > 0; --a) {
|
||||
if (hashes[i] == hashes[a])
|
||||
{
|
||||
aiMesh* orig = pScene->mMeshes[a];
|
||||
if (!orig)
|
||||
continue;
|
||||
|
||||
// check for hash collision .. we needn't check
|
||||
// the vertex format, it *must* match due to the
|
||||
// (brilliant) construction of the hash
|
||||
if (orig->mNumBones != inst->mNumBones ||
|
||||
orig->mNumFaces != inst->mNumFaces ||
|
||||
orig->mNumVertices != inst->mNumVertices ||
|
||||
orig->mMaterialIndex != inst->mMaterialIndex ||
|
||||
orig->mPrimitiveTypes != inst->mPrimitiveTypes)
|
||||
continue;
|
||||
|
||||
// up to now the meshes are equal. find an appropriate
|
||||
// epsilon to compare position differences against
|
||||
float epsilon = ComputePositionEpsilon(inst);
|
||||
epsilon *= epsilon;
|
||||
|
||||
// now compare vertex positions, normals,
|
||||
// tangents and bitangents using this epsilon.
|
||||
if (orig->HasPositions()) {
|
||||
if(!CompareArrays(orig->mVertices,inst->mVertices,orig->mNumVertices,epsilon))
|
||||
continue;
|
||||
}
|
||||
if (orig->HasNormals()) {
|
||||
if(!CompareArrays(orig->mNormals,inst->mNormals,orig->mNumVertices,epsilon))
|
||||
continue;
|
||||
}
|
||||
if (orig->HasTangentsAndBitangents()) {
|
||||
if (!CompareArrays(orig->mTangents,inst->mTangents,orig->mNumVertices,epsilon) ||
|
||||
!CompareArrays(orig->mBitangents,inst->mBitangents,orig->mNumVertices,epsilon))
|
||||
continue;
|
||||
}
|
||||
|
||||
// use a constant epsilon for colors and UV coordinates
|
||||
static const float uvEpsilon = 10e-4f;
|
||||
|
||||
BOOST_STATIC_ASSERT(4 == AI_MAX_NUMBER_OF_COLOR_SETS);
|
||||
|
||||
// as in JIV: manually unrolled as continue wouldn't work as desired in inner loops
|
||||
if (orig->mTextureCoords[0]) {
|
||||
if(!CompareArrays(orig->mTextureCoords[0],inst->mTextureCoords[0],orig->mNumVertices,uvEpsilon))
|
||||
continue;
|
||||
if (orig->mTextureCoords[1]) {
|
||||
if(!CompareArrays(orig->mTextureCoords[1],inst->mTextureCoords[1],orig->mNumVertices,uvEpsilon))
|
||||
continue;
|
||||
if (orig->mTextureCoords[2]) {
|
||||
if(!CompareArrays(orig->mTextureCoords[2],inst->mTextureCoords[2],orig->mNumVertices,uvEpsilon))
|
||||
continue;
|
||||
if (orig->mTextureCoords[3]) {
|
||||
if(!CompareArrays(orig->mTextureCoords[3],inst->mTextureCoords[3],orig->mNumVertices,uvEpsilon))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_STATIC_ASSERT(4 == AI_MAX_NUMBER_OF_COLOR_SETS);
|
||||
|
||||
// and the same nasty stuff for vertex colors ...
|
||||
if (orig->mColors[0]) {
|
||||
if(!CompareArrays(orig->mColors[0],inst->mColors[0],orig->mNumVertices,uvEpsilon))
|
||||
continue;
|
||||
if (orig->mTextureCoords[1]) {
|
||||
if(!CompareArrays(orig->mColors[1],inst->mColors[1],orig->mNumVertices,uvEpsilon))
|
||||
continue;
|
||||
if (orig->mTextureCoords[2]) {
|
||||
if(!CompareArrays(orig->mColors[2],inst->mColors[2],orig->mNumVertices,uvEpsilon))
|
||||
continue;
|
||||
if (orig->mTextureCoords[3]) {
|
||||
if(!CompareArrays(orig->mColors[3],inst->mColors[3],orig->mNumVertices,uvEpsilon))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// It seems to be strange, but we really need to check whether the
|
||||
// bones are identical too. Although it's extremely unprobable
|
||||
// that they're not if control reaches here, but we need to deal
|
||||
// with unprobable cases, too.
|
||||
if (!CompareBones(orig,inst))
|
||||
continue;
|
||||
|
||||
// FIXME: Ignore the faces for the moment ... ok!?
|
||||
|
||||
// We're still here. Or in other words: 'inst' is an instance of 'orig'.
|
||||
// Place a marker in our list that we can easily update mesh indices.
|
||||
remapping[i] = a;
|
||||
|
||||
// Delete the instanced mesh, we don't need it anymore
|
||||
delete inst;
|
||||
pScene->mMeshes[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't find a match for the current mesh: keep it
|
||||
if (pScene->mMeshes[i]) {
|
||||
remapping[i] = numMeshesOut++;
|
||||
}
|
||||
}
|
||||
ai_assert(0 != numMeshesOut);
|
||||
if (numMeshesOut != pScene->mNumMeshes) {
|
||||
|
||||
// Collapse the meshes array by removing all NULL entries
|
||||
for (unsigned int real = 0, i = 0; real < numMeshesOut; ++i) {
|
||||
if (pScene->mMeshes[i])
|
||||
pScene->mMeshes[real++] = pScene->mMeshes[i];
|
||||
}
|
||||
|
||||
// And update the nodegraph with our nice lookup table
|
||||
UpdateMeshIndices(pScene->mRootNode,remapping.get());
|
||||
|
||||
// write to log
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
|
||||
char buffer[512];
|
||||
::sprintf(buffer,"FindInstancesProcess finished. Found %i instances",pScene->mNumMeshes-numMeshesOut);
|
||||
DefaultLogger::get()->info(buffer);
|
||||
}
|
||||
pScene->mNumMeshes = numMeshesOut;
|
||||
}
|
||||
else DefaultLogger::get()->debug("FindInstancesProcess finished. No instanced meshes found");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
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 FindInstancesProcess.h
|
||||
* @brief Declares the aiProcess_FindInstances post-process step
|
||||
*/
|
||||
#ifndef AI_FINDINSTANCES_H_INC
|
||||
#define AI_FINDINSTANCES_H_INC
|
||||
|
||||
#include "BaseProcess.h"
|
||||
#include "ProcessHelper.h"
|
||||
|
||||
class FindInstancesProcessTest;
|
||||
namespace Assimp {
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** @brief Get a pseudo(!)-hash representing a mesh.
|
||||
*
|
||||
* The hash is built from number of vertices, faces, primitive types,
|
||||
* .... but *not* from the real mesh data. It isn't absolutely unique.
|
||||
* @param in Input mesh
|
||||
* @return Hash.
|
||||
*/
|
||||
inline uint64_t GetMeshHash(aiMesh* in)
|
||||
{
|
||||
ai_assert(NULL != in);
|
||||
|
||||
// ... get an unique value representing the vertex format of the mesh
|
||||
const unsigned int fhash = GetMeshVFormatUnique(in);
|
||||
|
||||
// and bake it with number of vertices/faces/bones/matidx/ptypes
|
||||
return ((uint64_t)fhash << 32u) | ((
|
||||
(in->mNumBones << 16u) ^ (in->mNumVertices) ^
|
||||
(in->mNumFaces<<4u) ^ (in->mMaterialIndex<<15) ^
|
||||
(in->mPrimitiveTypes<<28)) & 0xffffffff );
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** @brief Perform a component-wise comparison of two arrays
|
||||
*
|
||||
* @param first First array
|
||||
* @param second Second aray
|
||||
* @param size Size of both arrays
|
||||
* @param e Epsilon
|
||||
* @return true if the arrays are identical
|
||||
*/
|
||||
inline bool CompareArrays(const aiVector3D* first, const aiVector3D* second,
|
||||
unsigned int size, float e)
|
||||
{
|
||||
for (const aiVector3D* end = first+size; first != end; ++first,++second) {
|
||||
if ( (*first - *second).SquareLength() >= e)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// and the same for colors ...
|
||||
inline bool CompareArrays(const aiColor4D* first, const aiColor4D* second,
|
||||
unsigned int size, float e)
|
||||
{
|
||||
for (const aiColor4D* end = first+size; first != end; ++first,++second) {
|
||||
if ( GetColorDifference(*first,*second) >= e)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief A post-processing steps to search for instanced meshes
|
||||
*/
|
||||
class ASSIMP_API FindInstancesProcess : public BaseProcess
|
||||
{
|
||||
friend class Importer;
|
||||
friend class ::FindInstancesProcessTest;
|
||||
|
||||
protected:
|
||||
/** Constructor to be privately used by Importer */
|
||||
FindInstancesProcess();
|
||||
|
||||
/** Destructor, private as well */
|
||||
~FindInstancesProcess();
|
||||
|
||||
public:
|
||||
// -------------------------------------------------------------------
|
||||
// Check whether step is active in given flags combination
|
||||
bool IsActive( unsigned int pFlags) const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Execute step on a given scene
|
||||
void Execute( aiScene* pScene);
|
||||
|
||||
private:
|
||||
|
||||
}; // ! end class FindInstancesProcess
|
||||
} // ! end namespace Assimp
|
||||
|
||||
#endif // !! AI_FINDINSTANCES_H_INC
|
|
@ -196,6 +196,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef AI_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
|
||||
# include "TextureTransform.h"
|
||||
#endif
|
||||
#ifndef AI_BUILD_NO_FINDINSTANCES_PROCESS
|
||||
# include "FindInstancesProcess.h"
|
||||
#endif
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Intern;
|
||||
|
@ -334,6 +337,14 @@ Importer::Importer()
|
|||
mPostProcessingSteps.push_back( new ValidateDSProcess());
|
||||
#endif
|
||||
|
||||
#if (!defined AI_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS)
|
||||
mPostProcessingSteps.push_back( new RemoveRedundantMatsProcess());
|
||||
#endif
|
||||
|
||||
#if (!defined AI_BUILD_NO_FINDINSTANCES_PROCESS)
|
||||
mPostProcessingSteps.push_back( new FindInstancesProcess());
|
||||
#endif
|
||||
|
||||
|
||||
#if (!defined AI_BUILD_NO_FINDDEGENERATES_PROCESS)
|
||||
mPostProcessingSteps.push_back( new FindDegeneratesProcess());
|
||||
|
@ -353,12 +364,6 @@ Importer::Importer()
|
|||
mPostProcessingSteps.push_back( new TextureTransformStep());
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#if (!defined AI_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS)
|
||||
mPostProcessingSteps.push_back( new RemoveRedundantMatsProcess());
|
||||
#endif
|
||||
#if (!defined AI_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
|
||||
mPostProcessingSteps.push_back( new PretransformVertices());
|
||||
#endif
|
||||
|
|
|
@ -209,7 +209,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
|||
if( (uv.mBitangent - v.mBitangent).SquareLength() > squareEpsilon)
|
||||
continue;
|
||||
// manually unrolled because continue wouldn't work as desired in an inner loop
|
||||
ai_assert( AI_MAX_NUMBER_OF_COLOR_SETS == 4);
|
||||
BOOST_STATIC_ASSERT(4 == AI_MAX_NUMBER_OF_COLOR_SETS);
|
||||
if( GetColorDifference( uv.mColors[0], v.mColors[0]) > squareEpsilon)
|
||||
continue;
|
||||
if( GetColorDifference( uv.mColors[1], v.mColors[1]) > squareEpsilon)
|
||||
|
@ -219,7 +219,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
|||
if( GetColorDifference( uv.mColors[3], v.mColors[3]) > squareEpsilon)
|
||||
continue;
|
||||
// texture coord matching manually unrolled as well
|
||||
ai_assert( AI_MAX_NUMBER_OF_TEXTURECOORDS == 4);
|
||||
BOOST_STATIC_ASSERT(4 == AI_MAX_NUMBER_OF_TEXTURECOORDS);
|
||||
if( (uv.mTexCoords[0] - v.mTexCoords[0]).SquareLength() > squareEpsilon)
|
||||
continue;
|
||||
if( (uv.mTexCoords[1] - v.mTexCoords[1]).SquareLength() > squareEpsilon)
|
||||
|
|
|
@ -95,20 +95,6 @@ protected:
|
|||
* @param meshIndex Index of the mesh to process
|
||||
*/
|
||||
int ProcessMesh( aiMesh* pMesh, unsigned int meshIndex);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Little helper function to calculate the quadratic difference
|
||||
* of two colours.
|
||||
* @param pColor1 First color
|
||||
* @param pColor2 second color
|
||||
* @return Quadratic color difference
|
||||
*/
|
||||
float GetColorDifference( const aiColor4D& pColor1, const aiColor4D& pColor2) const
|
||||
{
|
||||
aiColor4D c( pColor1.r - pColor2.r, pColor1.g - pColor2.g,
|
||||
pColor1.b - pColor2.b, pColor1.a - pColor2.a);
|
||||
return c.r*c.r + c.g*c.g + c.b*c.b + c.a*c.a;
|
||||
}
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
|
|
@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "AssimpPCH.h"
|
||||
#include "PretransformVertices.h"
|
||||
|
||||
#include "ProcessHelper.h"
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
|
@ -95,32 +95,8 @@ unsigned int GetMeshVFormat(aiMesh* pcMesh)
|
|||
if (pcMesh->mBones)
|
||||
return (unsigned int)(unsigned long)pcMesh->mBones;
|
||||
|
||||
ai_assert(NULL != pcMesh->mVertices);
|
||||
|
||||
// FIX: the hash may never be 0. Otherwise a comparison against
|
||||
// nullptr could be successful
|
||||
unsigned int iRet = 1;
|
||||
|
||||
// normals
|
||||
if (pcMesh->HasNormals())iRet |= 0x2;
|
||||
// tangents and bitangents
|
||||
if (pcMesh->HasTangentsAndBitangents())iRet |= 0x4;
|
||||
|
||||
// texture coordinates
|
||||
unsigned int p = 0;
|
||||
ai_assert(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS);
|
||||
while (pcMesh->HasTextureCoords(p))
|
||||
{
|
||||
iRet |= (0x100 << p);
|
||||
if (3 == pcMesh->mNumUVComponents[p])
|
||||
iRet |= (0x10000 << p);
|
||||
|
||||
++p;
|
||||
}
|
||||
// vertex colors
|
||||
p = 0;
|
||||
ai_assert(8 >= AI_MAX_NUMBER_OF_COLOR_SETS);
|
||||
while (pcMesh->HasVertexColors(p))iRet |= (0x1000000 << p++);
|
||||
const unsigned int iRet = GetMeshVFormatUnique(pcMesh);
|
||||
|
||||
// store the value for later use
|
||||
pcMesh->mBones = (aiBone**)(unsigned long)iRet;
|
||||
|
|
|
@ -48,11 +48,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
namespace Assimp {
|
||||
|
||||
typedef std::pair< unsigned int,float > PerVertexWeight;
|
||||
typedef std::vector< PerVertexWeight > VertexWeightTable;
|
||||
// some aliases to make the whole stuff easier to read
|
||||
typedef std::pair < unsigned int,float > PerVertexWeight;
|
||||
typedef std::vector < PerVertexWeight > VertexWeightTable;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// compute a good epsilon value for position comparisons
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Little helper function to calculate the quadratic difference
|
||||
* of two colours.
|
||||
* @param pColor1 First color
|
||||
* @param pColor2 second color
|
||||
* @return Quadratic color difference
|
||||
*/
|
||||
inline float GetColorDifference( const aiColor4D& pColor1, const aiColor4D& pColor2)
|
||||
{
|
||||
const aiColor4D c (pColor1.r - pColor2.r, pColor1.g - pColor2.g,
|
||||
pColor1.b - pColor2.b, pColor1.a - pColor2.a);
|
||||
|
||||
return c.r*c.r + c.g*c.g + c.b*c.b + c.a*c.a;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Compute a good epsilon value for position comparisons on a mesh
|
||||
inline float ComputePositionEpsilon(const aiMesh* pMesh)
|
||||
{
|
||||
const float epsilon = 1e-5f;
|
||||
|
@ -71,20 +87,54 @@ inline float ComputePositionEpsilon(const aiMesh* pMesh)
|
|||
return (maxVec - minVec).Length() * epsilon;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------------------
|
||||
// Compute an unique value for the vertex format of a mesh
|
||||
inline unsigned int GetMeshVFormatUnique(aiMesh* pcMesh)
|
||||
{
|
||||
ai_assert(NULL != pcMesh);
|
||||
|
||||
// FIX: the hash may never be 0. Otherwise a comparison against
|
||||
// nullptr could be successful
|
||||
unsigned int iRet = 1;
|
||||
|
||||
// normals
|
||||
if (pcMesh->HasNormals())iRet |= 0x2;
|
||||
// tangents and bitangents
|
||||
if (pcMesh->HasTangentsAndBitangents())iRet |= 0x4;
|
||||
|
||||
BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_COLOR_SETS);
|
||||
BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS);
|
||||
|
||||
// texture coordinates
|
||||
unsigned int p = 0;
|
||||
while (pcMesh->HasTextureCoords(p))
|
||||
{
|
||||
iRet |= (0x100 << p);
|
||||
if (3 == pcMesh->mNumUVComponents[p])
|
||||
iRet |= (0x10000 << p);
|
||||
|
||||
++p;
|
||||
}
|
||||
// vertex colors
|
||||
p = 0;
|
||||
while (pcMesh->HasVertexColors(p))iRet |= (0x1000000 << p++);
|
||||
return iRet;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Compute a per-vertex bone weight table
|
||||
// NOTE: delete result with operator delete[] ...
|
||||
// please .... delete result with operator delete[] ...
|
||||
inline VertexWeightTable* ComputeVertexBoneWeightTable(aiMesh* pMesh)
|
||||
{
|
||||
if (!pMesh || !pMesh->mNumVertices || !pMesh->mNumBones) return NULL;
|
||||
if (!pMesh || !pMesh->mNumVertices || !pMesh->mNumBones)
|
||||
return NULL;
|
||||
|
||||
VertexWeightTable* avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices];
|
||||
for (unsigned int i = 0; i < pMesh->mNumBones;++i)
|
||||
{
|
||||
aiBone* bone = pMesh->mBones[i];
|
||||
for (unsigned int a = 0; a < bone->mNumWeights;++a)
|
||||
{
|
||||
aiVertexWeight& weight = bone->mWeights[a];
|
||||
for (unsigned int a = 0; a < bone->mNumWeights;++a) {
|
||||
const aiVertexWeight& weight = bone->mWeights[a];
|
||||
avPerVertexWeights[weight.mVertexId].push_back(
|
||||
std::pair<unsigned int,float>(i,weight.mWeight));
|
||||
}
|
||||
|
@ -93,7 +143,7 @@ inline VertexWeightTable* ComputeVertexBoneWeightTable(aiMesh* pMesh)
|
|||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------------------
|
||||
// Get a string for a given aiTextureType
|
||||
inline const char* TextureTypeToString(aiTextureType in)
|
||||
{
|
||||
|
@ -120,7 +170,7 @@ inline const char* TextureTypeToString(aiTextureType in)
|
|||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------------------
|
||||
// Get a string for a given aiTextureMapping
|
||||
inline const char* MappingTypeToString(aiTextureMapping in)
|
||||
{
|
||||
|
@ -143,7 +193,9 @@ inline const char* MappingTypeToString(aiTextureMapping in)
|
|||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------------------
|
||||
// Utility postprocess step to share the spatial sort tree between
|
||||
// all steps which use it to speedup its computations.
|
||||
class ComputeSpatialSortProcess : public BaseProcess
|
||||
{
|
||||
bool IsActive( unsigned int pFlags) const
|
||||
|
@ -159,8 +211,7 @@ class ComputeSpatialSortProcess : public BaseProcess
|
|||
std::vector<_Type>* p = new std::vector<_Type>(pScene->mNumMeshes);
|
||||
std::vector<_Type>::iterator it = p->begin();
|
||||
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i, ++it)
|
||||
{
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i, ++it) {
|
||||
aiMesh* mesh = pScene->mMeshes[i];
|
||||
_Type& blubb = *it;
|
||||
blubb.first.Fill(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D));
|
||||
|
@ -171,7 +222,8 @@ class ComputeSpatialSortProcess : public BaseProcess
|
|||
}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------------------
|
||||
// ... and the same again to cleanup the whole stuff
|
||||
class DestroySpatialSortProcess : public BaseProcess
|
||||
{
|
||||
bool IsActive( unsigned int pFlags) const
|
||||
|
|
|
@ -38,11 +38,6 @@ public:
|
|||
return ptr;
|
||||
}
|
||||
|
||||
inline operator T*()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
inline T* operator-> ()
|
||||
{
|
||||
return ptr;
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
#ifndef AI_BOOST_STATIC_ASSERT_INCLUDED
|
||||
#define AI_BOOST_STATIC_ASSERT_INCLUDED
|
||||
|
||||
#ifndef BOOST_STATIC_ASSERT
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
|
||||
template <bool b> class static_assertion_failure;
|
||||
template <> class static_assertion_failure<true> {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define BOOST_STATIC_ASSERT(eval) \
|
||||
{boost::detail::static_assertion_failure<(eval)> assert_dummy;assert_dummy;}
|
||||
|
||||
#endif
|
||||
#endif // !! AI_BOOST_STATIC_ASSERT_INCLUDED
|
|
@ -243,8 +243,18 @@ enum aiPostProcessSteps
|
|||
* coordinates and generates a new, transformed, UV channel for it.
|
||||
* Most applications won't support UV transformations, so you will
|
||||
* probably want to specify this step in every case.
|
||||
|
||||
* todo ... rewrite doc
|
||||
*/
|
||||
aiProcess_TransformUVCoords = 0x80000
|
||||
aiProcess_TransformUVCoords = 0x80000,
|
||||
|
||||
|
||||
/** This step searches for duplicate meshes and replaces duplicates
|
||||
* with references to the first mesh.
|
||||
*
|
||||
* todo ... add more doc
|
||||
*/
|
||||
aiProcess_FindInstances = 0x100000
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -146,6 +146,7 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter)
|
|||
aiProcess_FindInvalidData | // detect invalid model data, such as invalid normal vectors
|
||||
aiProcess_GenUVCoords | // convert spherical, cylindrical, box and planar mapping to proper UVs
|
||||
aiProcess_TransformUVCoords | // preprocess UV transformations (scaling, translation ...)
|
||||
aiProcess_FindInstances | // search for instanced meshes and remove them by references to one master
|
||||
// aiProcess_PreTransformVertices |
|
||||
0);
|
||||
|
||||
|
|
|
@ -1254,6 +1254,10 @@
|
|||
RelativePath="..\..\include\BoostWorkaround\boost\scoped_ptr.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\BoostWorkaround\boost\static_assert.hpp"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="random"
|
||||
>
|
||||
|
@ -2046,6 +2050,14 @@
|
|||
RelativePath="..\..\code\FindDegenerates.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\FindInstancesProcess.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\FindInstancesProcess.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\FindInvalidDataProcess.cpp"
|
||||
>
|
||||
|
|
|
@ -1253,6 +1253,10 @@
|
|||
RelativePath="..\..\include\BoostWorkaround\boost\scoped_ptr.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\BoostWorkaround\boost\static_assert.hpp"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="random"
|
||||
>
|
||||
|
@ -2045,6 +2049,14 @@
|
|||
RelativePath="..\..\code\FindDegenerates.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\FindInstancesProcess.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\FindInstancesProcess.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\FindInvalidDataProcess.cpp"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue