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/scoped_array.hpp"
|
||||||
# include "../include/BoostWorkaround/boost/format.hpp"
|
# include "../include/BoostWorkaround/boost/format.hpp"
|
||||||
# include "../include/BoostWorkaround/boost/foreach.hpp"
|
# include "../include/BoostWorkaround/boost/foreach.hpp"
|
||||||
|
# include "../include/BoostWorkaround/boost/static_assert.hpp"
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -115,6 +116,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
# include <boost/scoped_array.hpp>
|
# include <boost/scoped_array.hpp>
|
||||||
# include <boost/format.hpp>
|
# include <boost/format.hpp>
|
||||||
# include <boost/foreach.hpp>
|
# include <boost/foreach.hpp>
|
||||||
|
# include <boost/static_assert.hpp>
|
||||||
|
|
||||||
#endif // ! ASSIMP_BUILD_BOOST_WORKAROUND
|
#endif // ! ASSIMP_BUILD_BOOST_WORKAROUND
|
||||||
#endif // !! ASSIMP_PCH_INCLUDED
|
#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
|
#ifndef AI_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
|
||||||
# include "TextureTransform.h"
|
# include "TextureTransform.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef AI_BUILD_NO_FINDINSTANCES_PROCESS
|
||||||
|
# include "FindInstancesProcess.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
using namespace Assimp::Intern;
|
using namespace Assimp::Intern;
|
||||||
|
@ -334,6 +337,14 @@ Importer::Importer()
|
||||||
mPostProcessingSteps.push_back( new ValidateDSProcess());
|
mPostProcessingSteps.push_back( new ValidateDSProcess());
|
||||||
#endif
|
#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)
|
#if (!defined AI_BUILD_NO_FINDDEGENERATES_PROCESS)
|
||||||
mPostProcessingSteps.push_back( new FindDegeneratesProcess());
|
mPostProcessingSteps.push_back( new FindDegeneratesProcess());
|
||||||
|
@ -353,12 +364,6 @@ Importer::Importer()
|
||||||
mPostProcessingSteps.push_back( new TextureTransformStep());
|
mPostProcessingSteps.push_back( new TextureTransformStep());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if (!defined AI_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS)
|
|
||||||
mPostProcessingSteps.push_back( new RemoveRedundantMatsProcess());
|
|
||||||
#endif
|
|
||||||
#if (!defined AI_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
|
#if (!defined AI_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
|
||||||
mPostProcessingSteps.push_back( new PretransformVertices());
|
mPostProcessingSteps.push_back( new PretransformVertices());
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -209,7 +209,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
||||||
if( (uv.mBitangent - v.mBitangent).SquareLength() > squareEpsilon)
|
if( (uv.mBitangent - v.mBitangent).SquareLength() > squareEpsilon)
|
||||||
continue;
|
continue;
|
||||||
// manually unrolled because continue wouldn't work as desired in an inner loop
|
// 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)
|
if( GetColorDifference( uv.mColors[0], v.mColors[0]) > squareEpsilon)
|
||||||
continue;
|
continue;
|
||||||
if( GetColorDifference( uv.mColors[1], v.mColors[1]) > squareEpsilon)
|
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)
|
if( GetColorDifference( uv.mColors[3], v.mColors[3]) > squareEpsilon)
|
||||||
continue;
|
continue;
|
||||||
// texture coord matching manually unrolled as well
|
// 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)
|
if( (uv.mTexCoords[0] - v.mTexCoords[0]).SquareLength() > squareEpsilon)
|
||||||
continue;
|
continue;
|
||||||
if( (uv.mTexCoords[1] - v.mTexCoords[1]).SquareLength() > squareEpsilon)
|
if( (uv.mTexCoords[1] - v.mTexCoords[1]).SquareLength() > squareEpsilon)
|
||||||
|
|
|
@ -95,20 +95,6 @@ protected:
|
||||||
* @param meshIndex Index of the mesh to process
|
* @param meshIndex Index of the mesh to process
|
||||||
*/
|
*/
|
||||||
int ProcessMesh( aiMesh* pMesh, unsigned int meshIndex);
|
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
|
} // end of namespace Assimp
|
||||||
|
|
|
@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "AssimpPCH.h"
|
#include "AssimpPCH.h"
|
||||||
#include "PretransformVertices.h"
|
#include "PretransformVertices.h"
|
||||||
|
#include "ProcessHelper.h"
|
||||||
|
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
|
|
||||||
|
@ -95,32 +95,8 @@ unsigned int GetMeshVFormat(aiMesh* pcMesh)
|
||||||
if (pcMesh->mBones)
|
if (pcMesh->mBones)
|
||||||
return (unsigned int)(unsigned long)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
|
const unsigned int iRet = GetMeshVFormatUnique(pcMesh);
|
||||||
// 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++);
|
|
||||||
|
|
||||||
// store the value for later use
|
// store the value for later use
|
||||||
pcMesh->mBones = (aiBone**)(unsigned long)iRet;
|
pcMesh->mBones = (aiBone**)(unsigned long)iRet;
|
||||||
|
|
|
@ -48,11 +48,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
typedef std::pair< unsigned int,float > PerVertexWeight;
|
// some aliases to make the whole stuff easier to read
|
||||||
typedef std::vector< PerVertexWeight > VertexWeightTable;
|
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)
|
inline float ComputePositionEpsilon(const aiMesh* pMesh)
|
||||||
{
|
{
|
||||||
const float epsilon = 1e-5f;
|
const float epsilon = 1e-5f;
|
||||||
|
@ -71,20 +87,54 @@ inline float ComputePositionEpsilon(const aiMesh* pMesh)
|
||||||
return (maxVec - minVec).Length() * epsilon;
|
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
|
// Compute a per-vertex bone weight table
|
||||||
// NOTE: delete result with operator delete[] ...
|
// please .... delete result with operator delete[] ...
|
||||||
inline VertexWeightTable* ComputeVertexBoneWeightTable(aiMesh* pMesh)
|
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];
|
VertexWeightTable* avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices];
|
||||||
for (unsigned int i = 0; i < pMesh->mNumBones;++i)
|
for (unsigned int i = 0; i < pMesh->mNumBones;++i)
|
||||||
{
|
{
|
||||||
aiBone* bone = pMesh->mBones[i];
|
aiBone* bone = pMesh->mBones[i];
|
||||||
for (unsigned int a = 0; a < bone->mNumWeights;++a)
|
for (unsigned int a = 0; a < bone->mNumWeights;++a) {
|
||||||
{
|
const aiVertexWeight& weight = bone->mWeights[a];
|
||||||
aiVertexWeight& weight = bone->mWeights[a];
|
|
||||||
avPerVertexWeights[weight.mVertexId].push_back(
|
avPerVertexWeights[weight.mVertexId].push_back(
|
||||||
std::pair<unsigned int,float>(i,weight.mWeight));
|
std::pair<unsigned int,float>(i,weight.mWeight));
|
||||||
}
|
}
|
||||||
|
@ -93,7 +143,7 @@ inline VertexWeightTable* ComputeVertexBoneWeightTable(aiMesh* pMesh)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------
|
||||||
// Get a string for a given aiTextureType
|
// Get a string for a given aiTextureType
|
||||||
inline const char* TextureTypeToString(aiTextureType in)
|
inline const char* TextureTypeToString(aiTextureType in)
|
||||||
{
|
{
|
||||||
|
@ -120,7 +170,7 @@ inline const char* TextureTypeToString(aiTextureType in)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------
|
||||||
// Get a string for a given aiTextureMapping
|
// Get a string for a given aiTextureMapping
|
||||||
inline const char* MappingTypeToString(aiTextureMapping in)
|
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
|
class ComputeSpatialSortProcess : public BaseProcess
|
||||||
{
|
{
|
||||||
bool IsActive( unsigned int pFlags) const
|
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>* p = new std::vector<_Type>(pScene->mNumMeshes);
|
||||||
std::vector<_Type>::iterator it = p->begin();
|
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];
|
aiMesh* mesh = pScene->mMeshes[i];
|
||||||
_Type& blubb = *it;
|
_Type& blubb = *it;
|
||||||
blubb.first.Fill(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D));
|
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
|
class DestroySpatialSortProcess : public BaseProcess
|
||||||
{
|
{
|
||||||
bool IsActive( unsigned int pFlags) const
|
bool IsActive( unsigned int pFlags) const
|
||||||
|
|
|
@ -38,11 +38,6 @@ public:
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline operator T*()
|
|
||||||
{
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline T* operator-> ()
|
inline T* operator-> ()
|
||||||
{
|
{
|
||||||
return ptr;
|
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.
|
* coordinates and generates a new, transformed, UV channel for it.
|
||||||
* Most applications won't support UV transformations, so you will
|
* Most applications won't support UV transformations, so you will
|
||||||
* probably want to specify this step in every case.
|
* 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_FindInvalidData | // detect invalid model data, such as invalid normal vectors
|
||||||
aiProcess_GenUVCoords | // convert spherical, cylindrical, box and planar mapping to proper UVs
|
aiProcess_GenUVCoords | // convert spherical, cylindrical, box and planar mapping to proper UVs
|
||||||
aiProcess_TransformUVCoords | // preprocess UV transformations (scaling, translation ...)
|
aiProcess_TransformUVCoords | // preprocess UV transformations (scaling, translation ...)
|
||||||
|
aiProcess_FindInstances | // search for instanced meshes and remove them by references to one master
|
||||||
// aiProcess_PreTransformVertices |
|
// aiProcess_PreTransformVertices |
|
||||||
0);
|
0);
|
||||||
|
|
||||||
|
|
|
@ -1254,6 +1254,10 @@
|
||||||
RelativePath="..\..\include\BoostWorkaround\boost\scoped_ptr.hpp"
|
RelativePath="..\..\include\BoostWorkaround\boost\scoped_ptr.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\BoostWorkaround\boost\static_assert.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<Filter
|
<Filter
|
||||||
Name="random"
|
Name="random"
|
||||||
>
|
>
|
||||||
|
@ -2046,6 +2050,14 @@
|
||||||
RelativePath="..\..\code\FindDegenerates.h"
|
RelativePath="..\..\code\FindDegenerates.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\code\FindInstancesProcess.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\code\FindInstancesProcess.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\code\FindInvalidDataProcess.cpp"
|
RelativePath="..\..\code\FindInvalidDataProcess.cpp"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1253,6 +1253,10 @@
|
||||||
RelativePath="..\..\include\BoostWorkaround\boost\scoped_ptr.hpp"
|
RelativePath="..\..\include\BoostWorkaround\boost\scoped_ptr.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\BoostWorkaround\boost\static_assert.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<Filter
|
<Filter
|
||||||
Name="random"
|
Name="random"
|
||||||
>
|
>
|
||||||
|
@ -2045,6 +2049,14 @@
|
||||||
RelativePath="..\..\code\FindDegenerates.h"
|
RelativePath="..\..\code\FindDegenerates.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\code\FindInstancesProcess.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\code\FindInstancesProcess.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\code\FindInvalidDataProcess.cpp"
|
RelativePath="..\..\code\FindInvalidDataProcess.cpp"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in New Issue