replace NULL and avoid ai_assert with more than 2 tests.
This commit is contained in:
@@ -82,7 +82,7 @@ void ArmaturePopulate::Execute(aiScene *out) {
|
||||
for (std::pair<aiBone *, aiNode *> kvp : bone_stack) {
|
||||
aiBone *bone = kvp.first;
|
||||
aiNode *bone_node = kvp.second;
|
||||
ASSIMP_LOG_DEBUG_F("active node lookup: ", bone->mName.C_Str());
|
||||
ASSIMP_LOG_VERBOSE_DEBUG_F("active node lookup: ", bone->mName.C_Str());
|
||||
// lcl transform grab - done in generate_nodes :)
|
||||
|
||||
// bone->mOffsetMatrix = bone_node->mTransformation;
|
||||
@@ -178,7 +178,7 @@ void ArmaturePopulate::BuildBoneStack(aiNode *,
|
||||
if (node == nullptr) {
|
||||
node_stack.clear();
|
||||
BuildNodeList(root_node, node_stack);
|
||||
ASSIMP_LOG_DEBUG_F("Resetting bone stack: nullptr element ", bone->mName.C_Str());
|
||||
ASSIMP_LOG_VERBOSE_DEBUG_F("Resetting bone stack: nullptr element ", bone->mName.C_Str());
|
||||
|
||||
node = GetNodeFromStack(bone->mName, node_stack);
|
||||
|
||||
@@ -188,7 +188,7 @@ void ArmaturePopulate::BuildBoneStack(aiNode *,
|
||||
}
|
||||
}
|
||||
|
||||
ASSIMP_LOG_DEBUG_F("Successfully added bone[", bone->mName.C_Str(), "] to stack and bone node is: ", node->mName.C_Str());
|
||||
ASSIMP_LOG_VERBOSE_DEBUG_F("Successfully added bone[", bone->mName.C_Str(), "] to stack and bone node is: ", node->mName.C_Str());
|
||||
|
||||
bone_stack.insert(std::pair<aiBone *, aiNode *>(bone, node));
|
||||
}
|
||||
@@ -202,7 +202,7 @@ aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node,
|
||||
std::vector<aiBone *> &bone_list) {
|
||||
while (bone_node) {
|
||||
if (!IsBoneNode(bone_node->mName, bone_list)) {
|
||||
ASSIMP_LOG_DEBUG_F("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str());
|
||||
ASSIMP_LOG_VERBOSE_DEBUG_F("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str());
|
||||
return bone_node;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,4 +109,4 @@ public:
|
||||
} // Namespace Assimp
|
||||
|
||||
|
||||
#endif // SCALE_PROCESS_H_
|
||||
#endif // SCALE_PROCESS_H_
|
||||
|
||||
@@ -55,54 +55,49 @@ using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
CalcTangentsProcess::CalcTangentsProcess()
|
||||
: configMaxAngle( AI_DEG_TO_RAD(45.f) )
|
||||
, configSourceUV( 0 ) {
|
||||
CalcTangentsProcess::CalcTangentsProcess() :
|
||||
configMaxAngle(AI_DEG_TO_RAD(45.f)), configSourceUV(0) {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
CalcTangentsProcess::~CalcTangentsProcess()
|
||||
{
|
||||
CalcTangentsProcess::~CalcTangentsProcess() {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
bool CalcTangentsProcess::IsActive( unsigned int pFlags) const
|
||||
{
|
||||
bool CalcTangentsProcess::IsActive(unsigned int pFlags) const {
|
||||
return (pFlags & aiProcess_CalcTangentSpace) != 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void CalcTangentsProcess::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
ai_assert( NULL != pImp );
|
||||
void CalcTangentsProcess::SetupProperties(const Importer *pImp) {
|
||||
ai_assert(nullptr != pImp);
|
||||
|
||||
// get the current value of the property
|
||||
configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45.f);
|
||||
configMaxAngle = std::max(std::min(configMaxAngle,45.0f),0.0f);
|
||||
configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE, 45.f);
|
||||
configMaxAngle = std::max(std::min(configMaxAngle, 45.0f), 0.0f);
|
||||
configMaxAngle = AI_DEG_TO_RAD(configMaxAngle);
|
||||
|
||||
configSourceUV = pImp->GetPropertyInteger(AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX,0);
|
||||
configSourceUV = pImp->GetPropertyInteger(AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX, 0);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void CalcTangentsProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
ai_assert( NULL != pScene );
|
||||
void CalcTangentsProcess::Execute(aiScene *pScene) {
|
||||
ai_assert(nullptr != pScene);
|
||||
|
||||
ASSIMP_LOG_DEBUG("CalcTangentsProcess begin");
|
||||
|
||||
bool bHas = false;
|
||||
for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) {
|
||||
if(ProcessMesh( pScene->mMeshes[a],a))bHas = true;
|
||||
for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
|
||||
if (ProcessMesh(pScene->mMeshes[a], a)) bHas = true;
|
||||
}
|
||||
|
||||
if ( bHas ) {
|
||||
if (bHas) {
|
||||
ASSIMP_LOG_INFO("CalcTangentsProcess finished. Tangents have been calculated");
|
||||
} else {
|
||||
ASSIMP_LOG_DEBUG("CalcTangentsProcess finished");
|
||||
@@ -111,8 +106,7 @@ void CalcTangentsProcess::Execute( aiScene* pScene)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Calculates tangents and bi-tangents for the given mesh
|
||||
bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
||||
{
|
||||
bool CalcTangentsProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshIndex) {
|
||||
// we assume that the mesh is still in the verbose vertex format where each face has its own set
|
||||
// of vertices and no vertices are shared between faces. Sadly I don't know any quick test to
|
||||
// assert() it here.
|
||||
@@ -124,54 +118,48 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
||||
// If the mesh consists of lines and/or points but not of
|
||||
// triangles or higher-order polygons the normal vectors
|
||||
// are undefined.
|
||||
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
|
||||
{
|
||||
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) {
|
||||
ASSIMP_LOG_INFO("Tangents are undefined for line and point meshes");
|
||||
return false;
|
||||
}
|
||||
|
||||
// what we can check, though, is if the mesh has normals and texture coordinates. That's a requirement
|
||||
if( pMesh->mNormals == NULL)
|
||||
{
|
||||
if (pMesh->mNormals == nullptr) {
|
||||
ASSIMP_LOG_ERROR("Failed to compute tangents; need normals");
|
||||
return false;
|
||||
}
|
||||
if( configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV] )
|
||||
{
|
||||
ASSIMP_LOG_ERROR((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV));
|
||||
if (configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV]) {
|
||||
ASSIMP_LOG_ERROR((Formatter::format("Failed to compute tangents; need UV data in channel"), configSourceUV));
|
||||
return false;
|
||||
}
|
||||
|
||||
const float angleEpsilon = 0.9999f;
|
||||
|
||||
std::vector<bool> vertexDone( pMesh->mNumVertices, false);
|
||||
std::vector<bool> vertexDone(pMesh->mNumVertices, false);
|
||||
const float qnan = get_qnan();
|
||||
|
||||
// create space for the tangents and bitangents
|
||||
pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
|
||||
pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
|
||||
|
||||
const aiVector3D* meshPos = pMesh->mVertices;
|
||||
const aiVector3D* meshNorm = pMesh->mNormals;
|
||||
const aiVector3D* meshTex = pMesh->mTextureCoords[configSourceUV];
|
||||
aiVector3D* meshTang = pMesh->mTangents;
|
||||
aiVector3D* meshBitang = pMesh->mBitangents;
|
||||
const aiVector3D *meshPos = pMesh->mVertices;
|
||||
const aiVector3D *meshNorm = pMesh->mNormals;
|
||||
const aiVector3D *meshTex = pMesh->mTextureCoords[configSourceUV];
|
||||
aiVector3D *meshTang = pMesh->mTangents;
|
||||
aiVector3D *meshBitang = pMesh->mBitangents;
|
||||
|
||||
// calculate the tangent and bitangent for every face
|
||||
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
|
||||
{
|
||||
const aiFace& face = pMesh->mFaces[a];
|
||||
if (face.mNumIndices < 3)
|
||||
{
|
||||
for (unsigned int a = 0; a < pMesh->mNumFaces; a++) {
|
||||
const aiFace &face = pMesh->mFaces[a];
|
||||
if (face.mNumIndices < 3) {
|
||||
// There are less than three indices, thus the tangent vector
|
||||
// is not defined. We are finished with these vertices now,
|
||||
// their tangent vectors are set to qnan.
|
||||
for (unsigned int i = 0; i < face.mNumIndices;++i)
|
||||
{
|
||||
for (unsigned int i = 0; i < face.mNumIndices; ++i) {
|
||||
unsigned int idx = face.mIndices[i];
|
||||
vertexDone [idx] = true;
|
||||
meshTang [idx] = aiVector3D(qnan);
|
||||
meshBitang [idx] = aiVector3D(qnan);
|
||||
vertexDone[idx] = true;
|
||||
meshTang[idx] = aiVector3D(qnan);
|
||||
meshBitang[idx] = aiVector3D(qnan);
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -190,9 +178,11 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
||||
float tx = meshTex[p2].x - meshTex[p0].x, ty = meshTex[p2].y - meshTex[p0].y;
|
||||
float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f;
|
||||
// when t1, t2, t3 in same position in UV space, just use default UV direction.
|
||||
if ( sx * ty == sy * tx ) {
|
||||
sx = 0.0; sy = 1.0;
|
||||
tx = 1.0; ty = 0.0;
|
||||
if (sx * ty == sy * tx) {
|
||||
sx = 0.0;
|
||||
sy = 1.0;
|
||||
tx = 1.0;
|
||||
ty = 0.0;
|
||||
}
|
||||
|
||||
// tangent points in the direction where to positive X axis of the texture coord's would point in model space
|
||||
@@ -206,13 +196,14 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
||||
bitangent.z = (w.z * sx - v.z * tx) * dirCorrection;
|
||||
|
||||
// store for every vertex of that face
|
||||
for( unsigned int b = 0; b < face.mNumIndices; ++b ) {
|
||||
for (unsigned int b = 0; b < face.mNumIndices; ++b) {
|
||||
unsigned int p = face.mIndices[b];
|
||||
|
||||
// project tangent and bitangent into the plane formed by the vertex' normal
|
||||
aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]);
|
||||
aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]);
|
||||
localTangent.NormalizeSafe(); localBitangent.NormalizeSafe();
|
||||
localTangent.NormalizeSafe();
|
||||
localBitangent.NormalizeSafe();
|
||||
|
||||
// reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN.
|
||||
bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z);
|
||||
@@ -228,31 +219,28 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
||||
}
|
||||
|
||||
// and write it into the mesh.
|
||||
meshTang[ p ] = localTangent;
|
||||
meshBitang[ p ] = localBitangent;
|
||||
meshTang[p] = localTangent;
|
||||
meshBitang[p] = localBitangent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// create a helper to quickly find locally close vertices among the vertex array
|
||||
// FIX: check whether we can reuse the SpatialSort of a previous step
|
||||
SpatialSort* vertexFinder = NULL;
|
||||
SpatialSort _vertexFinder;
|
||||
SpatialSort *vertexFinder = nullptr;
|
||||
SpatialSort _vertexFinder;
|
||||
float posEpsilon = 10e-6f;
|
||||
if (shared)
|
||||
{
|
||||
std::vector<std::pair<SpatialSort,float> >* avf;
|
||||
shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
|
||||
if (avf)
|
||||
{
|
||||
std::pair<SpatialSort,float>& blubb = avf->operator [] (meshIndex);
|
||||
if (shared) {
|
||||
std::vector<std::pair<SpatialSort, float>> *avf;
|
||||
shared->GetProperty(AI_SPP_SPATIAL_SORT, avf);
|
||||
if (avf) {
|
||||
std::pair<SpatialSort, float> &blubb = avf->operator[](meshIndex);
|
||||
vertexFinder = &blubb.first;
|
||||
posEpsilon = blubb.second;;
|
||||
posEpsilon = blubb.second;
|
||||
;
|
||||
}
|
||||
}
|
||||
if (!vertexFinder)
|
||||
{
|
||||
_vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
|
||||
if (!vertexFinder) {
|
||||
_vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof(aiVector3D));
|
||||
vertexFinder = &_vertexFinder;
|
||||
posEpsilon = ComputePositionEpsilon(pMesh);
|
||||
}
|
||||
@@ -263,56 +251,52 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
||||
|
||||
// in the second pass we now smooth out all tangents and bitangents at the same local position
|
||||
// if they are not too far off.
|
||||
for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
|
||||
{
|
||||
if( vertexDone[a])
|
||||
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
|
||||
if (vertexDone[a])
|
||||
continue;
|
||||
|
||||
const aiVector3D& origPos = pMesh->mVertices[a];
|
||||
const aiVector3D& origNorm = pMesh->mNormals[a];
|
||||
const aiVector3D& origTang = pMesh->mTangents[a];
|
||||
const aiVector3D& origBitang = pMesh->mBitangents[a];
|
||||
closeVertices.resize( 0 );
|
||||
const aiVector3D &origPos = pMesh->mVertices[a];
|
||||
const aiVector3D &origNorm = pMesh->mNormals[a];
|
||||
const aiVector3D &origTang = pMesh->mTangents[a];
|
||||
const aiVector3D &origBitang = pMesh->mBitangents[a];
|
||||
closeVertices.resize(0);
|
||||
|
||||
// find all vertices close to that position
|
||||
vertexFinder->FindPositions( origPos, posEpsilon, verticesFound);
|
||||
vertexFinder->FindPositions(origPos, posEpsilon, verticesFound);
|
||||
|
||||
closeVertices.reserve (verticesFound.size()+5);
|
||||
closeVertices.push_back( a);
|
||||
closeVertices.reserve(verticesFound.size() + 5);
|
||||
closeVertices.push_back(a);
|
||||
|
||||
// look among them for other vertices sharing the same normal and a close-enough tangent/bitangent
|
||||
for( unsigned int b = 0; b < verticesFound.size(); b++)
|
||||
{
|
||||
for (unsigned int b = 0; b < verticesFound.size(); b++) {
|
||||
unsigned int idx = verticesFound[b];
|
||||
if( vertexDone[idx])
|
||||
if (vertexDone[idx])
|
||||
continue;
|
||||
if( meshNorm[idx] * origNorm < angleEpsilon)
|
||||
if (meshNorm[idx] * origNorm < angleEpsilon)
|
||||
continue;
|
||||
if( meshTang[idx] * origTang < fLimit)
|
||||
if (meshTang[idx] * origTang < fLimit)
|
||||
continue;
|
||||
if( meshBitang[idx] * origBitang < fLimit)
|
||||
if (meshBitang[idx] * origBitang < fLimit)
|
||||
continue;
|
||||
|
||||
// it's similar enough -> add it to the smoothing group
|
||||
closeVertices.push_back( idx);
|
||||
closeVertices.push_back(idx);
|
||||
vertexDone[idx] = true;
|
||||
}
|
||||
|
||||
// smooth the tangents and bitangents of all vertices that were found to be close enough
|
||||
aiVector3D smoothTangent( 0, 0, 0), smoothBitangent( 0, 0, 0);
|
||||
for( unsigned int b = 0; b < closeVertices.size(); ++b)
|
||||
{
|
||||
smoothTangent += meshTang[ closeVertices[b] ];
|
||||
smoothBitangent += meshBitang[ closeVertices[b] ];
|
||||
aiVector3D smoothTangent(0, 0, 0), smoothBitangent(0, 0, 0);
|
||||
for (unsigned int b = 0; b < closeVertices.size(); ++b) {
|
||||
smoothTangent += meshTang[closeVertices[b]];
|
||||
smoothBitangent += meshBitang[closeVertices[b]];
|
||||
}
|
||||
smoothTangent.Normalize();
|
||||
smoothBitangent.Normalize();
|
||||
|
||||
// and write it back into all affected tangents
|
||||
for( unsigned int b = 0; b < closeVertices.size(); ++b)
|
||||
{
|
||||
meshTang[ closeVertices[b] ] = smoothTangent;
|
||||
meshBitang[ closeVertices[b] ] = smoothBitangent;
|
||||
for (unsigned int b = 0; b < closeVertices.size(); ++b) {
|
||||
meshTang[closeVertices[b]] = smoothTangent;
|
||||
meshBitang[closeVertices[b]] = smoothBitangent;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -49,10 +49,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* better location.
|
||||
*/
|
||||
|
||||
|
||||
#include "ConvertToLHProcess.h"
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/postprocess.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
|
||||
using namespace Assimp;
|
||||
@@ -62,8 +61,10 @@ using namespace Assimp;
|
||||
namespace {
|
||||
|
||||
template <typename aiMeshType>
|
||||
void flipUVs(aiMeshType* pMesh) {
|
||||
if (pMesh == nullptr) { return; }
|
||||
void flipUVs(aiMeshType *pMesh) {
|
||||
if (pMesh == nullptr) {
|
||||
return;
|
||||
}
|
||||
// mirror texture y coordinate
|
||||
for (unsigned int tcIdx = 0; tcIdx < AI_MAX_NUMBER_OF_TEXTURECOORDS; tcIdx++) {
|
||||
if (!pMesh->HasTextureCoords(tcIdx)) {
|
||||
@@ -80,8 +81,8 @@ void flipUVs(aiMeshType* pMesh) {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
MakeLeftHandedProcess::MakeLeftHandedProcess()
|
||||
: BaseProcess() {
|
||||
MakeLeftHandedProcess::MakeLeftHandedProcess() :
|
||||
BaseProcess() {
|
||||
// empty
|
||||
}
|
||||
|
||||
@@ -93,40 +94,36 @@ MakeLeftHandedProcess::~MakeLeftHandedProcess() {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
bool MakeLeftHandedProcess::IsActive( unsigned int pFlags) const
|
||||
{
|
||||
bool MakeLeftHandedProcess::IsActive(unsigned int pFlags) const {
|
||||
return 0 != (pFlags & aiProcess_MakeLeftHanded);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void MakeLeftHandedProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
void MakeLeftHandedProcess::Execute(aiScene *pScene) {
|
||||
// Check for an existent root node to proceed
|
||||
ai_assert(pScene->mRootNode != NULL);
|
||||
ai_assert(pScene->mRootNode != nullptr);
|
||||
ASSIMP_LOG_DEBUG("MakeLeftHandedProcess begin");
|
||||
|
||||
// recursively convert all the nodes
|
||||
ProcessNode( pScene->mRootNode, aiMatrix4x4());
|
||||
ProcessNode(pScene->mRootNode, aiMatrix4x4());
|
||||
|
||||
// process the meshes accordingly
|
||||
for ( unsigned int a = 0; a < pScene->mNumMeshes; ++a ) {
|
||||
ProcessMesh( pScene->mMeshes[ a ] );
|
||||
for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
|
||||
ProcessMesh(pScene->mMeshes[a]);
|
||||
}
|
||||
|
||||
// process the materials accordingly
|
||||
for ( unsigned int a = 0; a < pScene->mNumMaterials; ++a ) {
|
||||
ProcessMaterial( pScene->mMaterials[ a ] );
|
||||
for (unsigned int a = 0; a < pScene->mNumMaterials; ++a) {
|
||||
ProcessMaterial(pScene->mMaterials[a]);
|
||||
}
|
||||
|
||||
// transform all animation channels as well
|
||||
for( unsigned int a = 0; a < pScene->mNumAnimations; a++)
|
||||
{
|
||||
aiAnimation* anim = pScene->mAnimations[a];
|
||||
for( unsigned int b = 0; b < anim->mNumChannels; b++)
|
||||
{
|
||||
aiNodeAnim* nodeAnim = anim->mChannels[b];
|
||||
ProcessAnimation( nodeAnim);
|
||||
for (unsigned int a = 0; a < pScene->mNumAnimations; a++) {
|
||||
aiAnimation *anim = pScene->mAnimations[a];
|
||||
for (unsigned int b = 0; b < anim->mNumChannels; b++) {
|
||||
aiNodeAnim *nodeAnim = anim->mChannels[b];
|
||||
ProcessAnimation(nodeAnim);
|
||||
}
|
||||
}
|
||||
ASSIMP_LOG_DEBUG("MakeLeftHandedProcess finished");
|
||||
@@ -134,8 +131,7 @@ void MakeLeftHandedProcess::Execute( aiScene* pScene)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Recursively converts a node, all of its children and all of its meshes
|
||||
void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation)
|
||||
{
|
||||
void MakeLeftHandedProcess::ProcessNode(aiNode *pNode, const aiMatrix4x4 &pParentGlobalRotation) {
|
||||
// mirror all base vectors at the local Z axis
|
||||
pNode->mTransformation.c1 = -pNode->mTransformation.c1;
|
||||
pNode->mTransformation.c2 = -pNode->mTransformation.c2;
|
||||
@@ -150,43 +146,38 @@ void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pPare
|
||||
pNode->mTransformation.d3 = -pNode->mTransformation.d3; // useless, but anyways...
|
||||
|
||||
// continue for all children
|
||||
for( size_t a = 0; a < pNode->mNumChildren; ++a ) {
|
||||
ProcessNode( pNode->mChildren[ a ], pParentGlobalRotation * pNode->mTransformation );
|
||||
for (size_t a = 0; a < pNode->mNumChildren; ++a) {
|
||||
ProcessNode(pNode->mChildren[a], pParentGlobalRotation * pNode->mTransformation);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Converts a single mesh to left handed coordinates.
|
||||
void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) {
|
||||
if ( nullptr == pMesh ) {
|
||||
ASSIMP_LOG_ERROR( "Nullptr to mesh found." );
|
||||
void MakeLeftHandedProcess::ProcessMesh(aiMesh *pMesh) {
|
||||
if (nullptr == pMesh) {
|
||||
ASSIMP_LOG_ERROR("Nullptr to mesh found.");
|
||||
return;
|
||||
}
|
||||
// mirror positions, normals and stuff along the Z axis
|
||||
for( size_t a = 0; a < pMesh->mNumVertices; ++a)
|
||||
{
|
||||
for (size_t a = 0; a < pMesh->mNumVertices; ++a) {
|
||||
pMesh->mVertices[a].z *= -1.0f;
|
||||
if (pMesh->HasNormals()) {
|
||||
pMesh->mNormals[a].z *= -1.0f;
|
||||
}
|
||||
if( pMesh->HasTangentsAndBitangents())
|
||||
{
|
||||
if (pMesh->HasTangentsAndBitangents()) {
|
||||
pMesh->mTangents[a].z *= -1.0f;
|
||||
pMesh->mBitangents[a].z *= -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// mirror anim meshes positions, normals and stuff along the Z axis
|
||||
for (size_t m = 0; m < pMesh->mNumAnimMeshes; ++m)
|
||||
{
|
||||
for (size_t a = 0; a < pMesh->mAnimMeshes[m]->mNumVertices; ++a)
|
||||
{
|
||||
for (size_t m = 0; m < pMesh->mNumAnimMeshes; ++m) {
|
||||
for (size_t a = 0; a < pMesh->mAnimMeshes[m]->mNumVertices; ++a) {
|
||||
pMesh->mAnimMeshes[m]->mVertices[a].z *= -1.0f;
|
||||
if (pMesh->mAnimMeshes[m]->HasNormals()) {
|
||||
pMesh->mAnimMeshes[m]->mNormals[a].z *= -1.0f;
|
||||
}
|
||||
if (pMesh->mAnimMeshes[m]->HasTangentsAndBitangents())
|
||||
{
|
||||
if (pMesh->mAnimMeshes[m]->HasTangentsAndBitangents()) {
|
||||
pMesh->mAnimMeshes[m]->mTangents[a].z *= -1.0f;
|
||||
pMesh->mAnimMeshes[m]->mBitangents[a].z *= -1.0f;
|
||||
}
|
||||
@@ -194,9 +185,8 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) {
|
||||
}
|
||||
|
||||
// mirror offset matrices of all bones
|
||||
for( size_t a = 0; a < pMesh->mNumBones; ++a)
|
||||
{
|
||||
aiBone* bone = pMesh->mBones[a];
|
||||
for (size_t a = 0; a < pMesh->mNumBones; ++a) {
|
||||
aiBone *bone = pMesh->mBones[a];
|
||||
bone->mOffsetMatrix.a3 = -bone->mOffsetMatrix.a3;
|
||||
bone->mOffsetMatrix.b3 = -bone->mOffsetMatrix.b3;
|
||||
bone->mOffsetMatrix.d3 = -bone->mOffsetMatrix.d3;
|
||||
@@ -206,29 +196,28 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) {
|
||||
}
|
||||
|
||||
// mirror bitangents as well as they're derived from the texture coords
|
||||
if( pMesh->HasTangentsAndBitangents())
|
||||
{
|
||||
for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
|
||||
if (pMesh->HasTangentsAndBitangents()) {
|
||||
for (unsigned int a = 0; a < pMesh->mNumVertices; a++)
|
||||
pMesh->mBitangents[a] *= -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Converts a single material to left handed coordinates.
|
||||
void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) {
|
||||
if ( nullptr == _mat ) {
|
||||
ASSIMP_LOG_ERROR( "Nullptr to aiMaterial found." );
|
||||
void MakeLeftHandedProcess::ProcessMaterial(aiMaterial *_mat) {
|
||||
if (nullptr == _mat) {
|
||||
ASSIMP_LOG_ERROR("Nullptr to aiMaterial found.");
|
||||
return;
|
||||
}
|
||||
|
||||
aiMaterial* mat = (aiMaterial*)_mat;
|
||||
for (unsigned int a = 0; a < mat->mNumProperties;++a) {
|
||||
aiMaterialProperty* prop = mat->mProperties[a];
|
||||
aiMaterial *mat = (aiMaterial *)_mat;
|
||||
for (unsigned int a = 0; a < mat->mNumProperties; ++a) {
|
||||
aiMaterialProperty *prop = mat->mProperties[a];
|
||||
|
||||
// Mapping axis for UV mappings?
|
||||
if (!::strcmp( prop->mKey.data, "$tex.mapaxis")) {
|
||||
ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */
|
||||
aiVector3D* pff = (aiVector3D*)prop->mData;
|
||||
if (!::strcmp(prop->mKey.data, "$tex.mapaxis")) {
|
||||
ai_assert(prop->mDataLength >= sizeof(aiVector3D)); // something is wrong with the validation if we end up here
|
||||
aiVector3D *pff = (aiVector3D *)prop->mData;
|
||||
pff->z *= -1.f;
|
||||
}
|
||||
}
|
||||
@@ -236,15 +225,13 @@ void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Converts the given animation to LH coordinates.
|
||||
void MakeLeftHandedProcess::ProcessAnimation( aiNodeAnim* pAnim)
|
||||
{
|
||||
void MakeLeftHandedProcess::ProcessAnimation(aiNodeAnim *pAnim) {
|
||||
// position keys
|
||||
for( unsigned int a = 0; a < pAnim->mNumPositionKeys; a++)
|
||||
for (unsigned int a = 0; a < pAnim->mNumPositionKeys; a++)
|
||||
pAnim->mPositionKeys[a].mValue.z *= -1.0f;
|
||||
|
||||
// rotation keys
|
||||
for( unsigned int a = 0; a < pAnim->mNumRotationKeys; a++)
|
||||
{
|
||||
for (unsigned int a = 0; a < pAnim->mNumRotationKeys; a++) {
|
||||
/* That's the safe version, but the float errors add up. So we try the short version instead
|
||||
aiMatrix3x3 rotmat = pAnim->mRotationKeys[a].mValue.GetMatrix();
|
||||
rotmat.a3 = -rotmat.a3; rotmat.b3 = -rotmat.b3;
|
||||
@@ -258,55 +245,50 @@ void MakeLeftHandedProcess::ProcessAnimation( aiNodeAnim* pAnim)
|
||||
}
|
||||
|
||||
#endif // !! ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS
|
||||
#ifndef ASSIMP_BUILD_NO_FLIPUVS_PROCESS
|
||||
#ifndef ASSIMP_BUILD_NO_FLIPUVS_PROCESS
|
||||
// # FlipUVsProcess
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
FlipUVsProcess::FlipUVsProcess()
|
||||
{}
|
||||
FlipUVsProcess::FlipUVsProcess() {}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
FlipUVsProcess::~FlipUVsProcess()
|
||||
{}
|
||||
FlipUVsProcess::~FlipUVsProcess() {}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
bool FlipUVsProcess::IsActive( unsigned int pFlags) const
|
||||
{
|
||||
bool FlipUVsProcess::IsActive(unsigned int pFlags) const {
|
||||
return 0 != (pFlags & aiProcess_FlipUVs);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void FlipUVsProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
void FlipUVsProcess::Execute(aiScene *pScene) {
|
||||
ASSIMP_LOG_DEBUG("FlipUVsProcess begin");
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i)
|
||||
ProcessMesh(pScene->mMeshes[i]);
|
||||
|
||||
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
|
||||
for (unsigned int i = 0; i < pScene->mNumMaterials; ++i)
|
||||
ProcessMaterial(pScene->mMaterials[i]);
|
||||
ASSIMP_LOG_DEBUG("FlipUVsProcess finished");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Converts a single material
|
||||
void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
|
||||
{
|
||||
aiMaterial* mat = (aiMaterial*)_mat;
|
||||
for (unsigned int a = 0; a < mat->mNumProperties;++a) {
|
||||
aiMaterialProperty* prop = mat->mProperties[a];
|
||||
if( !prop ) {
|
||||
ASSIMP_LOG_DEBUG( "Property is null" );
|
||||
void FlipUVsProcess::ProcessMaterial(aiMaterial *_mat) {
|
||||
aiMaterial *mat = (aiMaterial *)_mat;
|
||||
for (unsigned int a = 0; a < mat->mNumProperties; ++a) {
|
||||
aiMaterialProperty *prop = mat->mProperties[a];
|
||||
if (!prop) {
|
||||
ASSIMP_LOG_VERBOSE_DEBUG("Property is null");
|
||||
continue;
|
||||
}
|
||||
|
||||
// UV transformation key?
|
||||
if (!::strcmp( prop->mKey.data, "$tex.uvtrafo")) {
|
||||
ai_assert( prop->mDataLength >= sizeof(aiUVTransform)); /* something is wrong with the validation if we end up here */
|
||||
aiUVTransform* uv = (aiUVTransform*)prop->mData;
|
||||
if (!::strcmp(prop->mKey.data, "$tex.uvtrafo")) {
|
||||
ai_assert(prop->mDataLength >= sizeof(aiUVTransform)); // something is wrong with the validation if we end up here
|
||||
aiUVTransform *uv = (aiUVTransform *)prop->mData;
|
||||
|
||||
// just flip it, that's everything
|
||||
uv->mTranslation.y *= -1.f;
|
||||
@@ -317,8 +299,7 @@ void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Converts a single mesh
|
||||
void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
|
||||
{
|
||||
void FlipUVsProcess::ProcessMesh(aiMesh *pMesh) {
|
||||
flipUVs(pMesh);
|
||||
for (unsigned int idx = 0; idx < pMesh->mNumAnimMeshes; idx++) {
|
||||
flipUVs(pMesh->mAnimMeshes[idx]);
|
||||
@@ -326,44 +307,38 @@ void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
|
||||
}
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_FLIPUVS_PROCESS
|
||||
#ifndef ASSIMP_BUILD_NO_FLIPWINDING_PROCESS
|
||||
#ifndef ASSIMP_BUILD_NO_FLIPWINDING_PROCESS
|
||||
// # FlipWindingOrderProcess
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
FlipWindingOrderProcess::FlipWindingOrderProcess()
|
||||
{}
|
||||
FlipWindingOrderProcess::FlipWindingOrderProcess() {}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
FlipWindingOrderProcess::~FlipWindingOrderProcess()
|
||||
{}
|
||||
FlipWindingOrderProcess::~FlipWindingOrderProcess() {}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
bool FlipWindingOrderProcess::IsActive( unsigned int pFlags) const
|
||||
{
|
||||
bool FlipWindingOrderProcess::IsActive(unsigned int pFlags) const {
|
||||
return 0 != (pFlags & aiProcess_FlipWindingOrder);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void FlipWindingOrderProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
void FlipWindingOrderProcess::Execute(aiScene *pScene) {
|
||||
ASSIMP_LOG_DEBUG("FlipWindingOrderProcess begin");
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i)
|
||||
ProcessMesh(pScene->mMeshes[i]);
|
||||
ASSIMP_LOG_DEBUG("FlipWindingOrderProcess finished");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Converts a single mesh
|
||||
void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh)
|
||||
{
|
||||
void FlipWindingOrderProcess::ProcessMesh(aiMesh *pMesh) {
|
||||
// invert the order of all faces in this mesh
|
||||
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
|
||||
{
|
||||
aiFace& face = pMesh->mFaces[a];
|
||||
for (unsigned int a = 0; a < pMesh->mNumFaces; a++) {
|
||||
aiFace &face = pMesh->mFaces[a];
|
||||
for (unsigned int b = 0; b < face.mNumIndices / 2; b++) {
|
||||
std::swap(face.mIndices[b], face.mIndices[face.mNumIndices - 1 - b]);
|
||||
}
|
||||
@@ -371,39 +346,34 @@ void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh)
|
||||
|
||||
// invert the order of all components in this mesh anim meshes
|
||||
for (unsigned int m = 0; m < pMesh->mNumAnimMeshes; m++) {
|
||||
aiAnimMesh* animMesh = pMesh->mAnimMeshes[m];
|
||||
aiAnimMesh *animMesh = pMesh->mAnimMeshes[m];
|
||||
unsigned int numVertices = animMesh->mNumVertices;
|
||||
if (animMesh->HasPositions()) {
|
||||
for (unsigned int a = 0; a < numVertices; a++)
|
||||
{
|
||||
for (unsigned int a = 0; a < numVertices; a++) {
|
||||
std::swap(animMesh->mVertices[a], animMesh->mVertices[numVertices - 1 - a]);
|
||||
}
|
||||
}
|
||||
if (animMesh->HasNormals()) {
|
||||
for (unsigned int a = 0; a < numVertices; a++)
|
||||
{
|
||||
for (unsigned int a = 0; a < numVertices; a++) {
|
||||
std::swap(animMesh->mNormals[a], animMesh->mNormals[numVertices - 1 - a]);
|
||||
}
|
||||
}
|
||||
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) {
|
||||
if (animMesh->HasTextureCoords(i)) {
|
||||
for (unsigned int a = 0; a < numVertices; a++)
|
||||
{
|
||||
for (unsigned int a = 0; a < numVertices; a++) {
|
||||
std::swap(animMesh->mTextureCoords[i][a], animMesh->mTextureCoords[i][numVertices - 1 - a]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (animMesh->HasTangentsAndBitangents()) {
|
||||
for (unsigned int a = 0; a < numVertices; a++)
|
||||
{
|
||||
for (unsigned int a = 0; a < numVertices; a++) {
|
||||
std::swap(animMesh->mTangents[a], animMesh->mTangents[numVertices - 1 - a]);
|
||||
std::swap(animMesh->mBitangents[a], animMesh->mBitangents[numVertices - 1 - a]);
|
||||
}
|
||||
}
|
||||
for (unsigned int v = 0; v < AI_MAX_NUMBER_OF_COLOR_SETS; v++) {
|
||||
if (animMesh->HasVertexColors(v)) {
|
||||
for (unsigned int a = 0; a < numVertices; a++)
|
||||
{
|
||||
for (unsigned int a = 0; a < numVertices; a++) {
|
||||
std::swap(animMesh->mColors[v][a], animMesh->mColors[v][numVertices - 1 - a]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,7 +414,8 @@ void DeboneProcess::UpdateNode(aiNode* pNode) const
|
||||
}
|
||||
|
||||
if( pNode->mNumMeshes > 0 ) {
|
||||
delete [] pNode->mMeshes; pNode->mMeshes = NULL;
|
||||
delete[] pNode->mMeshes;
|
||||
pNode->mMeshes = nullptr;
|
||||
}
|
||||
|
||||
pNode->mNumMeshes = static_cast<unsigned int>(newMeshList.size());
|
||||
|
||||
@@ -98,12 +98,14 @@ void DropFaceNormalsProcess::Execute( aiScene* pScene) {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
bool DropFaceNormalsProcess::DropMeshFaceNormals (aiMesh* pMesh) {
|
||||
if (NULL == pMesh->mNormals) {
|
||||
bool DropFaceNormalsProcess::DropMeshFaceNormals (aiMesh* mesh) {
|
||||
ai_assert(nullptr != mesh);
|
||||
|
||||
if (nullptr == mesh->mNormals) {
|
||||
return false;
|
||||
}
|
||||
|
||||
delete[] pMesh->mNormals;
|
||||
pMesh->mNormals = nullptr;
|
||||
delete[] mesh->mNormals;
|
||||
mesh->mNormals = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ evil_jump_outside:
|
||||
if (!mesh->mNumFaces) {
|
||||
//The whole mesh consists of degenerated faces
|
||||
//signal upward, that this mesh should be deleted.
|
||||
ASSIMP_LOG_DEBUG("FindDegeneratesProcess removed a mesh full of degenerated primitives");
|
||||
ASSIMP_LOG_VERBOSE_DEBUG("FindDegeneratesProcess removed a mesh full of degenerated primitives");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ void FindInstancesProcess::Execute( aiScene* pScene)
|
||||
|
||||
// Delete the instanced mesh, we don't need it anymore
|
||||
delete inst;
|
||||
pScene->mMeshes[i] = NULL;
|
||||
pScene->mMeshes[i] = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -256,7 +256,7 @@ void FindInstancesProcess::Execute( aiScene* pScene)
|
||||
ai_assert(0 != numMeshesOut);
|
||||
if (numMeshesOut != pScene->mNumMeshes) {
|
||||
|
||||
// Collapse the meshes array by removing all NULL entries
|
||||
// Collapse the meshes array by removing all nullptr entries
|
||||
for (unsigned int real = 0, i = 0; real < numMeshesOut; ++i) {
|
||||
if (pScene->mMeshes[i])
|
||||
pScene->mMeshes[real++] = pScene->mMeshes[i];
|
||||
|
||||
@@ -45,11 +45,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS
|
||||
|
||||
// internal headers
|
||||
# include "FindInvalidDataProcess.h"
|
||||
# include "ProcessHelper.h"
|
||||
#include "FindInvalidDataProcess.h"
|
||||
#include "ProcessHelper.h"
|
||||
|
||||
# include <assimp/Exceptional.h>
|
||||
# include <assimp/qnan.h>
|
||||
#include <assimp/Exceptional.h>
|
||||
#include <assimp/qnan.h>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
@@ -97,7 +97,7 @@ void UpdateMeshReferences(aiNode *node, const std::vector<unsigned int> &meshMap
|
||||
node->mNumMeshes = out;
|
||||
if (0 == out) {
|
||||
delete[] node->mMeshes;
|
||||
node->mMeshes = NULL;
|
||||
node->mMeshes = nullptr;
|
||||
}
|
||||
}
|
||||
// recursively update all children
|
||||
@@ -124,7 +124,7 @@ void FindInvalidDataProcess::Execute(aiScene *pScene) {
|
||||
if (2 == result) {
|
||||
// remove this mesh
|
||||
delete pScene->mMeshes[a];
|
||||
AI_DEBUG_INVALIDATE_PTR(pScene->mMeshes[a]);
|
||||
pScene->mMeshes[a] = nullptr;
|
||||
|
||||
meshMapping[a] = UINT_MAX;
|
||||
continue;
|
||||
@@ -201,7 +201,7 @@ inline bool ProcessArray(T *&in, unsigned int num, const char *name,
|
||||
if (err) {
|
||||
ASSIMP_LOG_ERROR_F("FindInvalidDataProcess fails on mesh ", name, ": ", err);
|
||||
delete[] in;
|
||||
in = NULL;
|
||||
in = nullptr;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -345,7 +345,7 @@ int FindInvalidDataProcess::ProcessMesh(aiMesh *pMesh) {
|
||||
// delete all subsequent texture coordinate sets.
|
||||
for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
|
||||
delete[] pMesh->mTextureCoords[a];
|
||||
pMesh->mTextureCoords[a] = NULL;
|
||||
pMesh->mTextureCoords[a] = nullptr;
|
||||
pMesh->mNumUVComponents[a] = 0;
|
||||
}
|
||||
|
||||
@@ -391,14 +391,14 @@ int FindInvalidDataProcess::ProcessMesh(aiMesh *pMesh) {
|
||||
// Process mesh tangents
|
||||
if (pMesh->mTangents && ProcessArray(pMesh->mTangents, pMesh->mNumVertices, "tangents", dirtyMask)) {
|
||||
delete[] pMesh->mBitangents;
|
||||
pMesh->mBitangents = NULL;
|
||||
pMesh->mBitangents = nullptr;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// Process mesh bitangents
|
||||
if (pMesh->mBitangents && ProcessArray(pMesh->mBitangents, pMesh->mNumVertices, "bitangents", dirtyMask)) {
|
||||
delete[] pMesh->mTangents;
|
||||
pMesh->mTangents = NULL;
|
||||
pMesh->mTangents = nullptr;
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,41 +45,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* normals for all imported faces.
|
||||
*/
|
||||
|
||||
|
||||
#include "GenFaceNormalsProcess.h"
|
||||
#include <assimp/Exceptional.h>
|
||||
#include <assimp/postprocess.h>
|
||||
#include <assimp/qnan.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/Exceptional.h>
|
||||
#include <assimp/qnan.h>
|
||||
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
GenFaceNormalsProcess::GenFaceNormalsProcess()
|
||||
{
|
||||
GenFaceNormalsProcess::GenFaceNormalsProcess() {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
GenFaceNormalsProcess::~GenFaceNormalsProcess()
|
||||
{
|
||||
GenFaceNormalsProcess::~GenFaceNormalsProcess() {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const {
|
||||
bool GenFaceNormalsProcess::IsActive(unsigned int pFlags) const {
|
||||
force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
|
||||
return (pFlags & aiProcess_GenNormals) != 0;
|
||||
return (pFlags & aiProcess_GenNormals) != 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void GenFaceNormalsProcess::Execute( aiScene* pScene) {
|
||||
void GenFaceNormalsProcess::Execute(aiScene *pScene) {
|
||||
ASSIMP_LOG_DEBUG("GenFaceNormalsProcess begin");
|
||||
|
||||
if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
|
||||
@@ -87,33 +83,35 @@ void GenFaceNormalsProcess::Execute( aiScene* pScene) {
|
||||
}
|
||||
|
||||
bool bHas = false;
|
||||
for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
|
||||
if(this->GenMeshFaceNormals( pScene->mMeshes[a])) {
|
||||
for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
|
||||
if (this->GenMeshFaceNormals(pScene->mMeshes[a])) {
|
||||
bHas = true;
|
||||
}
|
||||
}
|
||||
if (bHas) {
|
||||
if (bHas) {
|
||||
ASSIMP_LOG_INFO("GenFaceNormalsProcess finished. "
|
||||
"Face normals have been calculated");
|
||||
"Face normals have been calculated");
|
||||
} else {
|
||||
ASSIMP_LOG_DEBUG("GenFaceNormalsProcess finished. "
|
||||
"Normals are already there");
|
||||
"Normals are already there");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
|
||||
{
|
||||
if (NULL != pMesh->mNormals) {
|
||||
if (force_) delete[] pMesh->mNormals;
|
||||
else return false;
|
||||
bool GenFaceNormalsProcess::GenMeshFaceNormals(aiMesh *pMesh) {
|
||||
if (nullptr != pMesh->mNormals) {
|
||||
if (force_) {
|
||||
delete[] pMesh->mNormals;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If the mesh consists of lines and/or points but not of
|
||||
// triangles or higher-order polygons the normal vectors
|
||||
// are undefined.
|
||||
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) {
|
||||
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) {
|
||||
ASSIMP_LOG_INFO("Normal vectors are undefined for line and point meshes");
|
||||
return false;
|
||||
}
|
||||
@@ -123,22 +121,22 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
|
||||
const float qnan = get_qnan();
|
||||
|
||||
// iterate through all faces and compute per-face normals but store them per-vertex.
|
||||
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
|
||||
const aiFace& face = pMesh->mFaces[a];
|
||||
if (face.mNumIndices < 3) {
|
||||
for (unsigned int a = 0; a < pMesh->mNumFaces; a++) {
|
||||
const aiFace &face = pMesh->mFaces[a];
|
||||
if (face.mNumIndices < 3) {
|
||||
// either a point or a line -> no well-defined normal vector
|
||||
for (unsigned int i = 0;i < face.mNumIndices;++i) {
|
||||
for (unsigned int i = 0; i < face.mNumIndices; ++i) {
|
||||
pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
|
||||
const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
|
||||
const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
|
||||
const aiVector3D *pV1 = &pMesh->mVertices[face.mIndices[0]];
|
||||
const aiVector3D *pV2 = &pMesh->mVertices[face.mIndices[1]];
|
||||
const aiVector3D *pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices - 1]];
|
||||
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
|
||||
|
||||
for (unsigned int i = 0;i < face.mNumIndices;++i) {
|
||||
for (unsigned int i = 0; i < face.mNumIndices; ++i) {
|
||||
pMesh->mNormals[face.mIndices[i]] = vNor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,8 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* normals for all imported faces.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// internal headers
|
||||
#include "GenVertexNormalsProcess.h"
|
||||
#include "ProcessHelper.h"
|
||||
@@ -57,8 +55,8 @@ using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
GenVertexNormalsProcess::GenVertexNormalsProcess()
|
||||
: configMaxAngle( AI_DEG_TO_RAD( 175.f ) ) {
|
||||
GenVertexNormalsProcess::GenVertexNormalsProcess() :
|
||||
configMaxAngle(AI_DEG_TO_RAD(175.f)) {
|
||||
// empty
|
||||
}
|
||||
|
||||
@@ -70,25 +68,22 @@ GenVertexNormalsProcess::~GenVertexNormalsProcess() {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
|
||||
{
|
||||
bool GenVertexNormalsProcess::IsActive(unsigned int pFlags) const {
|
||||
force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
|
||||
return (pFlags & aiProcess_GenSmoothNormals) != 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void GenVertexNormalsProcess::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
void GenVertexNormalsProcess::SetupProperties(const Importer *pImp) {
|
||||
// Get the current value of the AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE property
|
||||
configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,(ai_real)175.0);
|
||||
configMaxAngle = AI_DEG_TO_RAD(std::max(std::min(configMaxAngle,(ai_real)175.0),(ai_real)0.0));
|
||||
configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, (ai_real)175.0);
|
||||
configMaxAngle = AI_DEG_TO_RAD(std::max(std::min(configMaxAngle, (ai_real)175.0), (ai_real)0.0));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void GenVertexNormalsProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
void GenVertexNormalsProcess::Execute(aiScene *pScene) {
|
||||
ASSIMP_LOG_DEBUG("GenVertexNormalsProcess begin");
|
||||
|
||||
if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
|
||||
@@ -96,34 +91,34 @@ void GenVertexNormalsProcess::Execute( aiScene* pScene)
|
||||
}
|
||||
|
||||
bool bHas = false;
|
||||
for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
|
||||
if(GenMeshVertexNormals( pScene->mMeshes[a],a))
|
||||
for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
|
||||
if (GenMeshVertexNormals(pScene->mMeshes[a], a))
|
||||
bHas = true;
|
||||
}
|
||||
|
||||
if (bHas) {
|
||||
if (bHas) {
|
||||
ASSIMP_LOG_INFO("GenVertexNormalsProcess finished. "
|
||||
"Vertex normals have been calculated");
|
||||
"Vertex normals have been calculated");
|
||||
} else {
|
||||
ASSIMP_LOG_DEBUG("GenVertexNormalsProcess finished. "
|
||||
"Normals are already there");
|
||||
"Normals are already there");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex)
|
||||
{
|
||||
if (NULL != pMesh->mNormals) {
|
||||
if (force_) delete[] pMesh->mNormals;
|
||||
else return false;
|
||||
bool GenVertexNormalsProcess::GenMeshVertexNormals(aiMesh *pMesh, unsigned int meshIndex) {
|
||||
if (nullptr != pMesh->mNormals) {
|
||||
if (force_)
|
||||
delete[] pMesh->mNormals;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the mesh consists of lines and/or points but not of
|
||||
// triangles or higher-order polygons the normal vectors
|
||||
// are undefined.
|
||||
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
|
||||
{
|
||||
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) {
|
||||
ASSIMP_LOG_INFO("Normal vectors are undefined for line and point meshes");
|
||||
return false;
|
||||
}
|
||||
@@ -133,75 +128,71 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
|
||||
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
|
||||
|
||||
// Compute per-face normals but store them per-vertex
|
||||
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
|
||||
{
|
||||
const aiFace& face = pMesh->mFaces[a];
|
||||
if (face.mNumIndices < 3)
|
||||
{
|
||||
for (unsigned int a = 0; a < pMesh->mNumFaces; a++) {
|
||||
const aiFace &face = pMesh->mFaces[a];
|
||||
if (face.mNumIndices < 3) {
|
||||
// either a point or a line -> no normal vector
|
||||
for (unsigned int i = 0;i < face.mNumIndices;++i) {
|
||||
for (unsigned int i = 0; i < face.mNumIndices; ++i) {
|
||||
pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
|
||||
const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
|
||||
const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
|
||||
const aiVector3D *pV1 = &pMesh->mVertices[face.mIndices[0]];
|
||||
const aiVector3D *pV2 = &pMesh->mVertices[face.mIndices[1]];
|
||||
const aiVector3D *pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices - 1]];
|
||||
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
|
||||
|
||||
for (unsigned int i = 0;i < face.mNumIndices;++i) {
|
||||
for (unsigned int i = 0; i < face.mNumIndices; ++i) {
|
||||
pMesh->mNormals[face.mIndices[i]] = vNor;
|
||||
}
|
||||
}
|
||||
|
||||
// Set up a SpatialSort to quickly find all vertices close to a given position
|
||||
// check whether we can reuse the SpatialSort of a previous step.
|
||||
SpatialSort* vertexFinder = NULL;
|
||||
SpatialSort _vertexFinder;
|
||||
ai_real posEpsilon = ai_real( 1e-5 );
|
||||
SpatialSort *vertexFinder = nullptr;
|
||||
SpatialSort _vertexFinder;
|
||||
ai_real posEpsilon = ai_real(1e-5);
|
||||
if (shared) {
|
||||
std::vector<std::pair<SpatialSort,ai_real> >* avf;
|
||||
shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
|
||||
if (avf)
|
||||
{
|
||||
std::pair<SpatialSort,ai_real>& blubb = avf->operator [] (meshIndex);
|
||||
std::vector<std::pair<SpatialSort, ai_real>> *avf;
|
||||
shared->GetProperty(AI_SPP_SPATIAL_SORT, avf);
|
||||
if (avf) {
|
||||
std::pair<SpatialSort, ai_real> &blubb = avf->operator[](meshIndex);
|
||||
vertexFinder = &blubb.first;
|
||||
posEpsilon = blubb.second;
|
||||
}
|
||||
}
|
||||
if (!vertexFinder) {
|
||||
_vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
|
||||
if (!vertexFinder) {
|
||||
_vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof(aiVector3D));
|
||||
vertexFinder = &_vertexFinder;
|
||||
posEpsilon = ComputePositionEpsilon(pMesh);
|
||||
}
|
||||
std::vector<unsigned int> verticesFound;
|
||||
aiVector3D* pcNew = new aiVector3D[pMesh->mNumVertices];
|
||||
aiVector3D *pcNew = new aiVector3D[pMesh->mNumVertices];
|
||||
|
||||
if (configMaxAngle >= AI_DEG_TO_RAD( 175.f )) {
|
||||
if (configMaxAngle >= AI_DEG_TO_RAD(175.f)) {
|
||||
// There is no angle limit. Thus all vertices with positions close
|
||||
// to each other will receive the same vertex normal. This allows us
|
||||
// to optimize the whole algorithm a little bit ...
|
||||
std::vector<bool> abHad(pMesh->mNumVertices,false);
|
||||
for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
|
||||
std::vector<bool> abHad(pMesh->mNumVertices, false);
|
||||
for (unsigned int i = 0; i < pMesh->mNumVertices; ++i) {
|
||||
if (abHad[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get all vertices that share this one ...
|
||||
vertexFinder->FindPositions( pMesh->mVertices[i], posEpsilon, verticesFound);
|
||||
vertexFinder->FindPositions(pMesh->mVertices[i], posEpsilon, verticesFound);
|
||||
|
||||
aiVector3D pcNor;
|
||||
for (unsigned int a = 0; a < verticesFound.size(); ++a) {
|
||||
const aiVector3D& v = pMesh->mNormals[verticesFound[a]];
|
||||
if (is_not_qnan(v.x))pcNor += v;
|
||||
const aiVector3D &v = pMesh->mNormals[verticesFound[a]];
|
||||
if (is_not_qnan(v.x)) pcNor += v;
|
||||
}
|
||||
pcNor.NormalizeSafe();
|
||||
|
||||
// Write the smoothed normal back to all affected normals
|
||||
for (unsigned int a = 0; a < verticesFound.size(); ++a)
|
||||
{
|
||||
for (unsigned int a = 0; a < verticesFound.size(); ++a) {
|
||||
unsigned int vidx = verticesFound[a];
|
||||
pcNew[vidx] = pcNor;
|
||||
abHad[vidx] = true;
|
||||
@@ -210,11 +201,11 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
|
||||
}
|
||||
// Slower code path if a smooth angle is set. There are many ways to achieve
|
||||
// the effect, this one is the most straightforward one.
|
||||
else {
|
||||
else {
|
||||
const ai_real fLimit = std::cos(configMaxAngle);
|
||||
for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
|
||||
for (unsigned int i = 0; i < pMesh->mNumVertices; ++i) {
|
||||
// Get all vertices that share this one ...
|
||||
vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound);
|
||||
vertexFinder->FindPositions(pMesh->mVertices[i], posEpsilon, verticesFound);
|
||||
|
||||
aiVector3D vr = pMesh->mNormals[i];
|
||||
|
||||
|
||||
@@ -355,7 +355,7 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
|
||||
|
||||
// very intense verbose logging ... prepare for much text if there are many meshes
|
||||
if ( DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) {
|
||||
ASSIMP_LOG_DEBUG_F("Mesh %u | ACMR in: ", meshNum, " out: ", fACMR, " | ~", fACMR2, ((fACMR - fACMR2) / fACMR) * 100.f);
|
||||
ASSIMP_LOG_VERBOSE_DEBUG_F("Mesh %u | ACMR in: ", meshNum, " out: ", fACMR, " | ~", fACMR2, ((fACMR - fACMR2) / fACMR) * 100.f);
|
||||
}
|
||||
|
||||
fACMR2 *= pMesh->mNumFaces;
|
||||
|
||||
@@ -266,7 +266,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
||||
std::vector<unsigned int> replaceIndex( pMesh->mNumVertices, 0xffffffff);
|
||||
|
||||
// float posEpsilonSqr;
|
||||
SpatialSort* vertexFinder = NULL;
|
||||
SpatialSort *vertexFinder = nullptr;
|
||||
SpatialSort _vertexFinder;
|
||||
|
||||
typedef std::pair<SpatialSort,float> SpatPair;
|
||||
@@ -373,7 +373,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
||||
}
|
||||
|
||||
if (!DefaultLogger::isNullLogger() && DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) {
|
||||
ASSIMP_LOG_DEBUG_F(
|
||||
ASSIMP_LOG_VERBOSE_DEBUG_F(
|
||||
"Mesh ",meshIndex,
|
||||
" (",
|
||||
(pMesh->mName.length ? pMesh->mName.data : "unnamed"),
|
||||
@@ -408,7 +408,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
||||
std::vector<aiVertexWeight> newWeights;
|
||||
newWeights.reserve( bone->mNumWeights);
|
||||
|
||||
if ( NULL != bone->mWeights ) {
|
||||
if (nullptr != bone->mWeights) {
|
||||
for ( unsigned int b = 0; b < bone->mNumWeights; b++ ) {
|
||||
const aiVertexWeight& ow = bone->mWeights[ b ];
|
||||
// if the vertex is a unique one, translate it
|
||||
@@ -420,7 +420,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ASSIMP_LOG_ERROR( "X-Export: aiBone shall contain weights, but pointer to them is NULL." );
|
||||
ASSIMP_LOG_ERROR( "X-Export: aiBone shall contain weights, but pointer to them is nullptr." );
|
||||
}
|
||||
|
||||
if (newWeights.size() > 0) {
|
||||
|
||||
@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#include "LimitBoneWeightsProcess.h"
|
||||
#include <assimp/SmallVector.h>
|
||||
#include <assimp/StringUtils.h>
|
||||
#include <assimp/postprocess.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
@@ -52,7 +53,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
LimitBoneWeightsProcess::LimitBoneWeightsProcess()
|
||||
@@ -76,10 +76,12 @@ bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void LimitBoneWeightsProcess::Execute( aiScene* pScene) {
|
||||
void LimitBoneWeightsProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess begin");
|
||||
for (unsigned int a = 0; a < pScene->mNumMeshes; ++a ) {
|
||||
ProcessMesh(pScene->mMeshes[a]);
|
||||
|
||||
for (unsigned int m = 0; m < pScene->mNumMeshes; ++m) {
|
||||
ProcessMesh(pScene->mMeshes[m]);
|
||||
}
|
||||
|
||||
ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess end");
|
||||
@@ -95,107 +97,100 @@ void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Unites identical vertices in the given mesh
|
||||
void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
|
||||
void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh)
|
||||
{
|
||||
if( !pMesh->HasBones())
|
||||
if (!pMesh->HasBones())
|
||||
return;
|
||||
|
||||
// collect all bone weights per vertex
|
||||
typedef std::vector< std::vector< Weight > > WeightsPerVertex;
|
||||
WeightsPerVertex vertexWeights( pMesh->mNumVertices);
|
||||
typedef SmallVector<Weight,8> VertexWeightArray;
|
||||
typedef std::vector<VertexWeightArray> WeightsPerVertex;
|
||||
WeightsPerVertex vertexWeights(pMesh->mNumVertices);
|
||||
size_t maxVertexWeights = 0;
|
||||
|
||||
// collect all weights per vertex
|
||||
for( unsigned int a = 0; a < pMesh->mNumBones; a++)
|
||||
for (unsigned int b = 0; b < pMesh->mNumBones; ++b)
|
||||
{
|
||||
const aiBone* bone = pMesh->mBones[a];
|
||||
for( unsigned int b = 0; b < bone->mNumWeights; b++)
|
||||
const aiBone* bone = pMesh->mBones[b];
|
||||
for (unsigned int w = 0; w < bone->mNumWeights; ++w)
|
||||
{
|
||||
const aiVertexWeight& w = bone->mWeights[b];
|
||||
vertexWeights[w.mVertexId].push_back( Weight( a, w.mWeight));
|
||||
const aiVertexWeight& vw = bone->mWeights[w];
|
||||
|
||||
if (vertexWeights.size() <= vw.mVertexId)
|
||||
continue;
|
||||
|
||||
vertexWeights[vw.mVertexId].push_back(Weight(b, vw.mWeight));
|
||||
maxVertexWeights = std::max(maxVertexWeights, vertexWeights[vw.mVertexId].size());
|
||||
}
|
||||
}
|
||||
|
||||
if (maxVertexWeights <= mMaxWeights)
|
||||
return;
|
||||
|
||||
unsigned int removed = 0, old_bones = pMesh->mNumBones;
|
||||
|
||||
// now cut the weight count if it exceeds the maximum
|
||||
bool bChanged = false;
|
||||
for( WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit)
|
||||
for (WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit)
|
||||
{
|
||||
if( vit->size() <= mMaxWeights)
|
||||
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());
|
||||
std::sort(vit->begin(), vit->end());
|
||||
|
||||
// now kill everything beyond the maximum count
|
||||
unsigned int m = static_cast<unsigned int>(vit->size());
|
||||
vit->erase( vit->begin() + mMaxWeights, vit->end());
|
||||
removed += static_cast<unsigned int>(m-vit->size());
|
||||
vit->resize(mMaxWeights);
|
||||
removed += static_cast<unsigned int>(m - vit->size());
|
||||
|
||||
// and renormalize the weights
|
||||
float sum = 0.0f;
|
||||
for( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it ) {
|
||||
for(const Weight* it = vit->begin(); it != vit->end(); ++it) {
|
||||
sum += it->mWeight;
|
||||
}
|
||||
if( 0.0f != sum ) {
|
||||
if (0.0f != sum) {
|
||||
const float invSum = 1.0f / sum;
|
||||
for( std::vector<Weight>::iterator it = vit->begin(); it != vit->end(); ++it ) {
|
||||
for(Weight* it = vit->begin(); it != vit->end(); ++it) {
|
||||
it->mWeight *= invSum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bChanged) {
|
||||
// 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++)
|
||||
// clear weight count for all bone
|
||||
for (unsigned int a = 0; a < pMesh->mNumBones; ++a)
|
||||
{
|
||||
pMesh->mBones[a]->mNumWeights = 0;
|
||||
}
|
||||
|
||||
// rebuild the vertex weight array for all bones
|
||||
for (unsigned int a = 0; a < vertexWeights.size(); ++a)
|
||||
{
|
||||
const VertexWeightArray& vw = vertexWeights[a];
|
||||
for (const Weight* it = vw.begin(); it != vw.end(); ++it)
|
||||
{
|
||||
const std::vector<Weight>& vw = vertexWeights[a];
|
||||
for( std::vector<Weight>::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
|
||||
std::vector<bool> abNoNeed(pMesh->mNumBones,false);
|
||||
bChanged = false;
|
||||
|
||||
for( unsigned int a = 0; a < pMesh->mNumBones; a++)
|
||||
{
|
||||
const std::vector<aiVertexWeight>& bw = boneWeights[a];
|
||||
aiBone* bone = pMesh->mBones[a];
|
||||
|
||||
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 = static_cast<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
|
||||
aiBone** ppcCur = pMesh->mBones;aiBone** ppcSrc = ppcCur;
|
||||
|
||||
for (std::vector<bool>::const_iterator iter = abNoNeed.begin();iter != abNoNeed.end() ;++iter) {
|
||||
if (*iter) {
|
||||
delete *ppcSrc;
|
||||
--pMesh->mNumBones;
|
||||
}
|
||||
else *ppcCur++ = *ppcSrc;
|
||||
++ppcSrc;
|
||||
}
|
||||
}
|
||||
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
ASSIMP_LOG_INFO_F("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones );
|
||||
aiBone* bone = pMesh->mBones[it->mBone];
|
||||
bone->mWeights[bone->mNumWeights++] = aiVertexWeight(a, it->mWeight);
|
||||
}
|
||||
}
|
||||
|
||||
// remove empty bones
|
||||
unsigned int writeBone = 0;
|
||||
|
||||
for (unsigned int readBone = 0; readBone< pMesh->mNumBones; ++readBone)
|
||||
{
|
||||
aiBone* bone = pMesh->mBones[readBone];
|
||||
if (bone->mNumWeights > 0)
|
||||
{
|
||||
pMesh->mBones[writeBone++] = bone;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete bone;
|
||||
}
|
||||
}
|
||||
pMesh->mNumBones = writeBone;
|
||||
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
ASSIMP_LOG_INFO_F("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
/** @file Implementation of the post processing step "MakeVerboseFormat"
|
||||
*/
|
||||
|
||||
|
||||
#include "MakeVerboseFormat.h"
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
@@ -51,26 +50,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
MakeVerboseFormatProcess::MakeVerboseFormatProcess()
|
||||
{
|
||||
MakeVerboseFormatProcess::MakeVerboseFormatProcess() {
|
||||
// nothing to do here
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
MakeVerboseFormatProcess::~MakeVerboseFormatProcess()
|
||||
{
|
||||
MakeVerboseFormatProcess::~MakeVerboseFormatProcess() {
|
||||
// nothing to do here
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void MakeVerboseFormatProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
ai_assert(NULL != pScene);
|
||||
void MakeVerboseFormatProcess::Execute(aiScene *pScene) {
|
||||
ai_assert(nullptr != pScene);
|
||||
ASSIMP_LOG_DEBUG("MakeVerboseFormatProcess begin");
|
||||
|
||||
bool bHas = false;
|
||||
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
|
||||
{
|
||||
if( MakeVerboseFormat( pScene->mMeshes[a]))
|
||||
for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
|
||||
if (MakeVerboseFormat(pScene->mMeshes[a]))
|
||||
bHas = true;
|
||||
}
|
||||
if (bHas) {
|
||||
@@ -84,29 +79,26 @@ void MakeVerboseFormatProcess::Execute( aiScene* pScene)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
|
||||
{
|
||||
ai_assert(NULL != pcMesh);
|
||||
bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh *pcMesh) {
|
||||
ai_assert(nullptr != pcMesh);
|
||||
|
||||
unsigned int iOldNumVertices = pcMesh->mNumVertices;
|
||||
const unsigned int iNumVerts = pcMesh->mNumFaces*3;
|
||||
const unsigned int iNumVerts = pcMesh->mNumFaces * 3;
|
||||
|
||||
aiVector3D* pvPositions = new aiVector3D[ iNumVerts ];
|
||||
aiVector3D *pvPositions = new aiVector3D[iNumVerts];
|
||||
|
||||
aiVector3D* pvNormals = NULL;
|
||||
if (pcMesh->HasNormals())
|
||||
{
|
||||
aiVector3D *pvNormals = nullptr;
|
||||
if (pcMesh->HasNormals()) {
|
||||
pvNormals = new aiVector3D[iNumVerts];
|
||||
}
|
||||
aiVector3D* pvTangents = NULL, *pvBitangents = NULL;
|
||||
if (pcMesh->HasTangentsAndBitangents())
|
||||
{
|
||||
aiVector3D *pvTangents = nullptr, *pvBitangents = nullptr;
|
||||
if (pcMesh->HasTangentsAndBitangents()) {
|
||||
pvTangents = new aiVector3D[iNumVerts];
|
||||
pvBitangents = new aiVector3D[iNumVerts];
|
||||
}
|
||||
|
||||
aiVector3D* apvTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS] = {0};
|
||||
aiColor4D* apvColorSets[AI_MAX_NUMBER_OF_COLOR_SETS] = {0};
|
||||
aiVector3D *apvTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS] = { 0 };
|
||||
aiColor4D *apvColorSets[AI_MAX_NUMBER_OF_COLOR_SETS] = { 0 };
|
||||
|
||||
unsigned int p = 0;
|
||||
while (pcMesh->HasTextureCoords(p))
|
||||
@@ -117,24 +109,21 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
|
||||
apvColorSets[p++] = new aiColor4D[iNumVerts];
|
||||
|
||||
// allocate enough memory to hold output bones and vertex weights ...
|
||||
std::vector<aiVertexWeight>* newWeights = new std::vector<aiVertexWeight>[pcMesh->mNumBones];
|
||||
for (unsigned int i = 0;i < pcMesh->mNumBones;++i) {
|
||||
newWeights[i].reserve(pcMesh->mBones[i]->mNumWeights*3);
|
||||
std::vector<aiVertexWeight> *newWeights = new std::vector<aiVertexWeight>[pcMesh->mNumBones];
|
||||
for (unsigned int i = 0; i < pcMesh->mNumBones; ++i) {
|
||||
newWeights[i].reserve(pcMesh->mBones[i]->mNumWeights * 3);
|
||||
}
|
||||
|
||||
// iterate through all faces and build a clean list
|
||||
unsigned int iIndex = 0;
|
||||
for (unsigned int a = 0; a< pcMesh->mNumFaces;++a)
|
||||
{
|
||||
aiFace* pcFace = &pcMesh->mFaces[a];
|
||||
for (unsigned int q = 0; q < pcFace->mNumIndices;++q,++iIndex)
|
||||
{
|
||||
for (unsigned int a = 0; a < pcMesh->mNumFaces; ++a) {
|
||||
aiFace *pcFace = &pcMesh->mFaces[a];
|
||||
for (unsigned int q = 0; q < pcFace->mNumIndices; ++q, ++iIndex) {
|
||||
// need to build a clean list of bones, too
|
||||
for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
|
||||
{
|
||||
for (unsigned int boneIdx = 0; boneIdx < pcMesh->mBones[i]->mNumWeights; ++boneIdx) {
|
||||
const aiVertexWeight &w = pcMesh->mBones[i]->mWeights[boneIdx];
|
||||
if(pcFace->mIndices[q] == w.mVertexId) {
|
||||
for (unsigned int i = 0; i < pcMesh->mNumBones; ++i) {
|
||||
for (unsigned int boneIdx = 0; boneIdx < pcMesh->mBones[i]->mNumWeights; ++boneIdx) {
|
||||
const aiVertexWeight &w = pcMesh->mBones[i]->mWeights[boneIdx];
|
||||
if (pcFace->mIndices[q] == w.mVertexId) {
|
||||
aiVertexWeight wNew;
|
||||
wNew.mVertexId = iIndex;
|
||||
wNew.mWeight = w.mWeight;
|
||||
@@ -145,45 +134,38 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
|
||||
|
||||
pvPositions[iIndex] = pcMesh->mVertices[pcFace->mIndices[q]];
|
||||
|
||||
if (pcMesh->HasNormals())
|
||||
{
|
||||
if (pcMesh->HasNormals()) {
|
||||
pvNormals[iIndex] = pcMesh->mNormals[pcFace->mIndices[q]];
|
||||
}
|
||||
if (pcMesh->HasTangentsAndBitangents())
|
||||
{
|
||||
if (pcMesh->HasTangentsAndBitangents()) {
|
||||
pvTangents[iIndex] = pcMesh->mTangents[pcFace->mIndices[q]];
|
||||
pvBitangents[iIndex] = pcMesh->mBitangents[pcFace->mIndices[q]];
|
||||
}
|
||||
|
||||
unsigned int pp = 0;
|
||||
while (pcMesh->HasTextureCoords(pp))
|
||||
{
|
||||
apvTextureCoords[pp][iIndex] = pcMesh->mTextureCoords[pp][pcFace->mIndices[q]];
|
||||
++pp;
|
||||
while (pcMesh->HasTextureCoords(pp)) {
|
||||
apvTextureCoords[pp][iIndex] = pcMesh->mTextureCoords[pp][pcFace->mIndices[q]];
|
||||
++pp;
|
||||
}
|
||||
pp = 0;
|
||||
while (pcMesh->HasVertexColors(pp))
|
||||
{
|
||||
apvColorSets[pp][iIndex] = pcMesh->mColors[pp][pcFace->mIndices[q]];
|
||||
++pp;
|
||||
pp = 0;
|
||||
while (pcMesh->HasVertexColors(pp)) {
|
||||
apvColorSets[pp][iIndex] = pcMesh->mColors[pp][pcFace->mIndices[q]];
|
||||
++pp;
|
||||
}
|
||||
pcFace->mIndices[q] = iIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// build output vertex weights
|
||||
for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
|
||||
{
|
||||
delete [] pcMesh->mBones[i]->mWeights;
|
||||
for (unsigned int i = 0; i < pcMesh->mNumBones; ++i) {
|
||||
delete[] pcMesh->mBones[i]->mWeights;
|
||||
if (!newWeights[i].empty()) {
|
||||
pcMesh->mBones[i]->mWeights = new aiVertexWeight[newWeights[i].size()];
|
||||
aiVertexWeight *weightToCopy = &( newWeights[i][0] );
|
||||
aiVertexWeight *weightToCopy = &(newWeights[i][0]);
|
||||
memcpy(pcMesh->mBones[i]->mWeights, weightToCopy,
|
||||
sizeof(aiVertexWeight) * newWeights[i].size());
|
||||
sizeof(aiVertexWeight) * newWeights[i].size());
|
||||
} else {
|
||||
pcMesh->mBones[i]->mWeights = NULL;
|
||||
pcMesh->mBones[i]->mWeights = nullptr;
|
||||
}
|
||||
}
|
||||
delete[] newWeights;
|
||||
@@ -193,28 +175,24 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
|
||||
pcMesh->mVertices = pvPositions;
|
||||
|
||||
p = 0;
|
||||
while (pcMesh->HasTextureCoords(p))
|
||||
{
|
||||
while (pcMesh->HasTextureCoords(p)) {
|
||||
delete[] pcMesh->mTextureCoords[p];
|
||||
pcMesh->mTextureCoords[p] = apvTextureCoords[p];
|
||||
++p;
|
||||
}
|
||||
p = 0;
|
||||
while (pcMesh->HasVertexColors(p))
|
||||
{
|
||||
while (pcMesh->HasVertexColors(p)) {
|
||||
delete[] pcMesh->mColors[p];
|
||||
pcMesh->mColors[p] = apvColorSets[p];
|
||||
++p;
|
||||
}
|
||||
pcMesh->mNumVertices = iNumVerts;
|
||||
|
||||
if (pcMesh->HasNormals())
|
||||
{
|
||||
if (pcMesh->HasNormals()) {
|
||||
delete[] pcMesh->mNormals;
|
||||
pcMesh->mNormals = pvNormals;
|
||||
}
|
||||
if (pcMesh->HasTangentsAndBitangents())
|
||||
{
|
||||
if (pcMesh->HasTangentsAndBitangents()) {
|
||||
delete[] pcMesh->mTangents;
|
||||
pcMesh->mTangents = pvTangents;
|
||||
delete[] pcMesh->mBitangents;
|
||||
@@ -223,15 +201,14 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
|
||||
return (pcMesh->mNumVertices != iOldNumVertices);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool IsMeshInVerboseFormat(const aiMesh* mesh) {
|
||||
bool IsMeshInVerboseFormat(const aiMesh *mesh) {
|
||||
// avoid slow vector<bool> specialization
|
||||
std::vector<unsigned int> seen(mesh->mNumVertices,0);
|
||||
for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
|
||||
const aiFace& f = mesh->mFaces[i];
|
||||
for(unsigned int j = 0; j < f.mNumIndices; ++j) {
|
||||
if(++seen[f.mIndices[j]] == 2) {
|
||||
std::vector<unsigned int> seen(mesh->mNumVertices, 0);
|
||||
for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
|
||||
const aiFace &f = mesh->mFaces[i];
|
||||
for (unsigned int j = 0; j < f.mNumIndices; ++j) {
|
||||
if (++seen[f.mIndices[j]] == 2) {
|
||||
// found a duplicate index
|
||||
return false;
|
||||
}
|
||||
@@ -242,9 +219,9 @@ bool IsMeshInVerboseFormat(const aiMesh* mesh) {
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool MakeVerboseFormatProcess::IsVerboseFormat(const aiScene* pScene) {
|
||||
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||
if(!IsMeshInVerboseFormat(pScene->mMeshes[i])) {
|
||||
bool MakeVerboseFormatProcess::IsVerboseFormat(const aiScene *pScene) {
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||
if (!IsMeshInVerboseFormat(pScene->mMeshes[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,7 +445,7 @@ void PretransformVertices::Execute(aiScene *pScene) {
|
||||
delete mesh->mBones[a];
|
||||
|
||||
delete[] mesh->mBones;
|
||||
mesh->mBones = NULL;
|
||||
mesh->mBones = nullptr;
|
||||
}
|
||||
|
||||
// now build a list of output meshes
|
||||
@@ -472,12 +472,12 @@ void PretransformVertices::Execute(aiScene *pScene) {
|
||||
pScene->mMeshes = npp;
|
||||
}
|
||||
|
||||
// now iterate through all meshes and transform them to worldspace
|
||||
// now iterate through all meshes and transform them to world-space
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||
ApplyTransform(pScene->mMeshes[i], *reinterpret_cast<aiMatrix4x4 *>(pScene->mMeshes[i]->mBones));
|
||||
|
||||
// prevent improper destruction
|
||||
pScene->mMeshes[i]->mBones = NULL;
|
||||
pScene->mMeshes[i]->mBones = nullptr;
|
||||
pScene->mMeshes[i]->mNumBones = 0;
|
||||
}
|
||||
} else {
|
||||
@@ -539,22 +539,22 @@ void PretransformVertices::Execute(aiScene *pScene) {
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||
aiMesh *mesh = pScene->mMeshes[i];
|
||||
mesh->mNumBones = 0;
|
||||
mesh->mBones = NULL;
|
||||
mesh->mBones = nullptr;
|
||||
|
||||
// we're reusing the face index arrays. avoid destruction
|
||||
for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
|
||||
mesh->mFaces[a].mNumIndices = 0;
|
||||
mesh->mFaces[a].mIndices = NULL;
|
||||
mesh->mFaces[a].mIndices = nullptr;
|
||||
}
|
||||
|
||||
delete mesh;
|
||||
|
||||
// Invalidate the contents of the old mesh array. We will most
|
||||
// likely have less output meshes now, so the last entries of
|
||||
// the mesh array are not overridden. We set them to NULL to
|
||||
// the mesh array are not overridden. We set them to nullptr to
|
||||
// make sure the developer gets notified when his application
|
||||
// attempts to access these fields ...
|
||||
mesh = NULL;
|
||||
mesh = nullptr;
|
||||
}
|
||||
|
||||
// It is impossible that we have more output meshes than
|
||||
@@ -571,14 +571,14 @@ void PretransformVertices::Execute(aiScene *pScene) {
|
||||
delete pScene->mAnimations[i];
|
||||
delete[] pScene->mAnimations;
|
||||
|
||||
pScene->mAnimations = NULL;
|
||||
pScene->mAnimations = nullptr;
|
||||
pScene->mNumAnimations = 0;
|
||||
|
||||
// --- we need to keep all cameras and lights
|
||||
for (unsigned int i = 0; i < pScene->mNumCameras; ++i) {
|
||||
aiCamera *cam = pScene->mCameras[i];
|
||||
const aiNode *nd = pScene->mRootNode->FindNode(cam->mName);
|
||||
ai_assert(NULL != nd);
|
||||
ai_assert(nullptr != nd);
|
||||
|
||||
// multiply all properties of the camera with the absolute
|
||||
// transformation of the corresponding node
|
||||
@@ -590,7 +590,7 @@ void PretransformVertices::Execute(aiScene *pScene) {
|
||||
for (unsigned int i = 0; i < pScene->mNumLights; ++i) {
|
||||
aiLight *l = pScene->mLights[i];
|
||||
const aiNode *nd = pScene->mRootNode->FindNode(l->mName);
|
||||
ai_assert(NULL != nd);
|
||||
ai_assert(nullptr != nd);
|
||||
|
||||
// multiply all properties of the camera with the absolute
|
||||
// transformation of the corresponding node
|
||||
|
||||
@@ -43,22 +43,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
/// @file ProcessHelper.cpp
|
||||
/** Implement shared utility functions for postprocessing steps */
|
||||
|
||||
|
||||
#include "ProcessHelper.h"
|
||||
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
void ConvertListToStrings(const std::string& in, std::list<std::string>& out)
|
||||
{
|
||||
const char* s = in.c_str();
|
||||
void ConvertListToStrings(const std::string &in, std::list<std::string> &out) {
|
||||
const char *s = in.c_str();
|
||||
while (*s) {
|
||||
SkipSpacesAndLineEnd(&s);
|
||||
if (*s == '\'') {
|
||||
const char* base = ++s;
|
||||
const char *base = ++s;
|
||||
while (*s != '\'') {
|
||||
++s;
|
||||
if (*s == '\0') {
|
||||
@@ -66,43 +63,39 @@ void ConvertListToStrings(const std::string& in, std::list<std::string>& out)
|
||||
return;
|
||||
}
|
||||
}
|
||||
out.push_back(std::string(base,(size_t)(s-base)));
|
||||
out.push_back(std::string(base, (size_t)(s - base)));
|
||||
++s;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
out.push_back(GetNextToken(s));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max,
|
||||
const aiMatrix4x4& m)
|
||||
{
|
||||
min = aiVector3D ( ai_real( 10e10 ), ai_real( 10e10 ), ai_real( 10e10 ) );
|
||||
max = aiVector3D ( ai_real( -10e10 ), ai_real( -10e10 ), ai_real( -10e10 ) );
|
||||
for (unsigned int i = 0;i < mesh->mNumVertices;++i)
|
||||
{
|
||||
void FindAABBTransformed(const aiMesh *mesh, aiVector3D &min, aiVector3D &max,
|
||||
const aiMatrix4x4 &m) {
|
||||
min = aiVector3D(ai_real(10e10), ai_real(10e10), ai_real(10e10));
|
||||
max = aiVector3D(ai_real(-10e10), ai_real(-10e10), ai_real(-10e10));
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
const aiVector3D v = m * mesh->mVertices[i];
|
||||
min = std::min(v,min);
|
||||
max = std::max(v,max);
|
||||
min = std::min(v, min);
|
||||
max = std::max(v, max);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D& max)
|
||||
{
|
||||
ArrayBounds(mesh->mVertices,mesh->mNumVertices, min,max);
|
||||
out = min + (max-min)*(ai_real)0.5;
|
||||
void FindMeshCenter(aiMesh *mesh, aiVector3D &out, aiVector3D &min, aiVector3D &max) {
|
||||
ArrayBounds(mesh->mVertices, mesh->mNumVertices, min, max);
|
||||
out = min + (max - min) * (ai_real)0.5;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
void FindSceneCenter (aiScene* scene, aiVector3D& out, aiVector3D& min, aiVector3D& max) {
|
||||
if ( NULL == scene ) {
|
||||
void FindSceneCenter(aiScene *scene, aiVector3D &out, aiVector3D &min, aiVector3D &max) {
|
||||
if (nullptr == scene) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 0 == scene->mNumMeshes ) {
|
||||
if (0 == scene->mNumMeshes) {
|
||||
return;
|
||||
}
|
||||
FindMeshCenter(scene->mMeshes[0], out, min, max);
|
||||
@@ -116,79 +109,71 @@ void FindSceneCenter (aiScene* scene, aiVector3D& out, aiVector3D& min, aiVector
|
||||
if (max[1] < tmax[1]) max[1] = tmax[1];
|
||||
if (max[2] < tmax[2]) max[2] = tmax[2];
|
||||
}
|
||||
out = min + (max-min)*(ai_real)0.5;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out, aiVector3D& min,
|
||||
aiVector3D& max, const aiMatrix4x4& m)
|
||||
{
|
||||
FindAABBTransformed(mesh,min,max,m);
|
||||
out = min + (max-min)*(ai_real)0.5;
|
||||
out = min + (max - min) * (ai_real)0.5;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
void FindMeshCenter (aiMesh* mesh, aiVector3D& out)
|
||||
{
|
||||
aiVector3D min,max;
|
||||
FindMeshCenter(mesh,out,min,max);
|
||||
void FindMeshCenterTransformed(aiMesh *mesh, aiVector3D &out, aiVector3D &min,
|
||||
aiVector3D &max, const aiMatrix4x4 &m) {
|
||||
FindAABBTransformed(mesh, min, max, m);
|
||||
out = min + (max - min) * (ai_real)0.5;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out,
|
||||
const aiMatrix4x4& m)
|
||||
{
|
||||
aiVector3D min,max;
|
||||
FindMeshCenterTransformed(mesh,out,min,max,m);
|
||||
void FindMeshCenter(aiMesh *mesh, aiVector3D &out) {
|
||||
aiVector3D min, max;
|
||||
FindMeshCenter(mesh, out, min, max);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
ai_real ComputePositionEpsilon(const aiMesh* pMesh)
|
||||
{
|
||||
const ai_real epsilon = ai_real( 1e-4 );
|
||||
void FindMeshCenterTransformed(aiMesh *mesh, aiVector3D &out,
|
||||
const aiMatrix4x4 &m) {
|
||||
aiVector3D min, max;
|
||||
FindMeshCenterTransformed(mesh, out, min, max, m);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
ai_real ComputePositionEpsilon(const aiMesh *pMesh) {
|
||||
const ai_real epsilon = ai_real(1e-4);
|
||||
|
||||
// calculate the position bounds so we have a reliable epsilon to check position differences against
|
||||
aiVector3D minVec, maxVec;
|
||||
ArrayBounds(pMesh->mVertices,pMesh->mNumVertices,minVec,maxVec);
|
||||
ArrayBounds(pMesh->mVertices, pMesh->mNumVertices, minVec, maxVec);
|
||||
return (maxVec - minVec).Length() * epsilon;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
ai_real ComputePositionEpsilon(const aiMesh* const* pMeshes, size_t num)
|
||||
{
|
||||
ai_assert( NULL != pMeshes );
|
||||
ai_real ComputePositionEpsilon(const aiMesh *const *pMeshes, size_t num) {
|
||||
ai_assert(nullptr != pMeshes);
|
||||
|
||||
const ai_real epsilon = ai_real( 1e-4 );
|
||||
const ai_real epsilon = ai_real(1e-4);
|
||||
|
||||
// calculate the position bounds so we have a reliable epsilon to check position differences against
|
||||
aiVector3D minVec, maxVec, mi, ma;
|
||||
MinMaxChooser<aiVector3D>()(minVec,maxVec);
|
||||
MinMaxChooser<aiVector3D>()(minVec, maxVec);
|
||||
|
||||
for (size_t a = 0; a < num; ++a) {
|
||||
const aiMesh* pMesh = pMeshes[a];
|
||||
ArrayBounds(pMesh->mVertices,pMesh->mNumVertices,mi,ma);
|
||||
const aiMesh *pMesh = pMeshes[a];
|
||||
ArrayBounds(pMesh->mVertices, pMesh->mNumVertices, mi, ma);
|
||||
|
||||
minVec = std::min(minVec,mi);
|
||||
maxVec = std::max(maxVec,ma);
|
||||
minVec = std::min(minVec, mi);
|
||||
maxVec = std::max(maxVec, ma);
|
||||
}
|
||||
return (maxVec - minVec).Length() * epsilon;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh)
|
||||
{
|
||||
ai_assert(NULL != pcMesh);
|
||||
unsigned int GetMeshVFormatUnique(const aiMesh *pcMesh) {
|
||||
ai_assert(nullptr != 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;
|
||||
if (pcMesh->HasNormals()) iRet |= 0x2;
|
||||
// tangents and bitangents
|
||||
if (pcMesh->HasTangentsAndBitangents())iRet |= 0x4;
|
||||
if (pcMesh->HasTangentsAndBitangents()) iRet |= 0x4;
|
||||
|
||||
#ifdef BOOST_STATIC_ASSERT
|
||||
BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_COLOR_SETS);
|
||||
@@ -197,8 +182,7 @@ unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh)
|
||||
|
||||
// texture coordinates
|
||||
unsigned int p = 0;
|
||||
while (pcMesh->HasTextureCoords(p))
|
||||
{
|
||||
while (pcMesh->HasTextureCoords(p)) {
|
||||
iRet |= (0x100 << p);
|
||||
if (3 == pcMesh->mNumUVComponents[p])
|
||||
iRet |= (0x10000 << p);
|
||||
@@ -207,34 +191,32 @@ unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh)
|
||||
}
|
||||
// vertex colors
|
||||
p = 0;
|
||||
while (pcMesh->HasVertexColors(p))iRet |= (0x1000000 << p++);
|
||||
while (pcMesh->HasVertexColors(p))
|
||||
iRet |= (0x1000000 << p++);
|
||||
return iRet;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh)
|
||||
{
|
||||
VertexWeightTable *ComputeVertexBoneWeightTable(const aiMesh *pMesh) {
|
||||
if (!pMesh || !pMesh->mNumVertices || !pMesh->mNumBones) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VertexWeightTable* avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices];
|
||||
for (unsigned int i = 0; i < pMesh->mNumBones;++i) {
|
||||
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) {
|
||||
const aiVertexWeight& weight = bone->mWeights[a];
|
||||
avPerVertexWeights[weight.mVertexId].push_back( std::pair<unsigned int,float>(i,weight.mWeight) );
|
||||
aiBone *bone = pMesh->mBones[i];
|
||||
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));
|
||||
}
|
||||
}
|
||||
return avPerVertexWeights;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
const char* MappingTypeToString(aiTextureMapping in)
|
||||
{
|
||||
switch (in)
|
||||
{
|
||||
const char *MappingTypeToString(aiTextureMapping in) {
|
||||
switch (in) {
|
||||
case aiTextureMapping_UV:
|
||||
return "UV";
|
||||
case aiTextureMapping_BOX:
|
||||
@@ -252,24 +234,22 @@ const char* MappingTypeToString(aiTextureMapping in)
|
||||
}
|
||||
|
||||
ai_assert(false);
|
||||
return "BUG";
|
||||
return "BUG";
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
aiMesh* MakeSubmesh(const aiMesh *pMesh, const std::vector<unsigned int> &subMeshFaces, unsigned int subFlags)
|
||||
{
|
||||
aiMesh *MakeSubmesh(const aiMesh *pMesh, const std::vector<unsigned int> &subMeshFaces, unsigned int subFlags) {
|
||||
aiMesh *oMesh = new aiMesh();
|
||||
std::vector<unsigned int> vMap(pMesh->mNumVertices,UINT_MAX);
|
||||
std::vector<unsigned int> vMap(pMesh->mNumVertices, UINT_MAX);
|
||||
|
||||
size_t numSubVerts = 0;
|
||||
size_t numSubFaces = subMeshFaces.size();
|
||||
|
||||
for(unsigned int i=0;i<numSubFaces;i++) {
|
||||
for (unsigned int i = 0; i < numSubFaces; i++) {
|
||||
const aiFace &f = pMesh->mFaces[subMeshFaces[i]];
|
||||
|
||||
for(unsigned int j=0;j<f.mNumIndices;j++) {
|
||||
if(vMap[f.mIndices[j]]==UINT_MAX) {
|
||||
for (unsigned int j = 0; j < f.mNumIndices; j++) {
|
||||
if (vMap[f.mIndices[j]] == UINT_MAX) {
|
||||
vMap[f.mIndices[j]] = static_cast<unsigned int>(numSubVerts++);
|
||||
}
|
||||
}
|
||||
@@ -285,114 +265,114 @@ aiMesh* MakeSubmesh(const aiMesh *pMesh, const std::vector<unsigned int> &subMes
|
||||
oMesh->mNumFaces = static_cast<unsigned int>(subMeshFaces.size());
|
||||
oMesh->mNumVertices = static_cast<unsigned int>(numSubVerts);
|
||||
oMesh->mVertices = new aiVector3D[numSubVerts];
|
||||
if( pMesh->HasNormals() ) {
|
||||
if (pMesh->HasNormals()) {
|
||||
oMesh->mNormals = new aiVector3D[numSubVerts];
|
||||
}
|
||||
|
||||
if( pMesh->HasTangentsAndBitangents() ) {
|
||||
if (pMesh->HasTangentsAndBitangents()) {
|
||||
oMesh->mTangents = new aiVector3D[numSubVerts];
|
||||
oMesh->mBitangents = new aiVector3D[numSubVerts];
|
||||
}
|
||||
|
||||
for( size_t a = 0; pMesh->HasTextureCoords(static_cast<unsigned int>(a)) ; ++a ) {
|
||||
for (size_t a = 0; pMesh->HasTextureCoords(static_cast<unsigned int>(a)); ++a) {
|
||||
oMesh->mTextureCoords[a] = new aiVector3D[numSubVerts];
|
||||
oMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a];
|
||||
}
|
||||
|
||||
for( size_t a = 0; pMesh->HasVertexColors( static_cast<unsigned int>(a)); ++a ) {
|
||||
for (size_t a = 0; pMesh->HasVertexColors(static_cast<unsigned int>(a)); ++a) {
|
||||
oMesh->mColors[a] = new aiColor4D[numSubVerts];
|
||||
}
|
||||
|
||||
// and copy over the data, generating faces with linear indices along the way
|
||||
oMesh->mFaces = new aiFace[numSubFaces];
|
||||
|
||||
for(unsigned int a = 0; a < numSubFaces; ++a ) {
|
||||
for (unsigned int a = 0; a < numSubFaces; ++a) {
|
||||
|
||||
const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]];
|
||||
aiFace& dstFace = oMesh->mFaces[a];
|
||||
const aiFace &srcFace = pMesh->mFaces[subMeshFaces[a]];
|
||||
aiFace &dstFace = oMesh->mFaces[a];
|
||||
dstFace.mNumIndices = srcFace.mNumIndices;
|
||||
dstFace.mIndices = new unsigned int[dstFace.mNumIndices];
|
||||
|
||||
// accumulate linearly all the vertices of the source face
|
||||
for( size_t b = 0; b < dstFace.mNumIndices; ++b ) {
|
||||
for (size_t b = 0; b < dstFace.mNumIndices; ++b) {
|
||||
dstFace.mIndices[b] = vMap[srcFace.mIndices[b]];
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned int srcIndex = 0; srcIndex < pMesh->mNumVertices; ++srcIndex ) {
|
||||
for (unsigned int srcIndex = 0; srcIndex < pMesh->mNumVertices; ++srcIndex) {
|
||||
unsigned int nvi = vMap[srcIndex];
|
||||
if(nvi==UINT_MAX) {
|
||||
if (nvi == UINT_MAX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
oMesh->mVertices[nvi] = pMesh->mVertices[srcIndex];
|
||||
if( pMesh->HasNormals() ) {
|
||||
if (pMesh->HasNormals()) {
|
||||
oMesh->mNormals[nvi] = pMesh->mNormals[srcIndex];
|
||||
}
|
||||
|
||||
if( pMesh->HasTangentsAndBitangents() ) {
|
||||
if (pMesh->HasTangentsAndBitangents()) {
|
||||
oMesh->mTangents[nvi] = pMesh->mTangents[srcIndex];
|
||||
oMesh->mBitangents[nvi] = pMesh->mBitangents[srcIndex];
|
||||
}
|
||||
for( size_t c = 0, cc = pMesh->GetNumUVChannels(); c < cc; ++c ) {
|
||||
oMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
|
||||
for (size_t c = 0, cc = pMesh->GetNumUVChannels(); c < cc; ++c) {
|
||||
oMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
|
||||
}
|
||||
for( size_t c = 0, cc = pMesh->GetNumColorChannels(); c < cc; ++c ) {
|
||||
for (size_t c = 0, cc = pMesh->GetNumColorChannels(); c < cc; ++c) {
|
||||
oMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex];
|
||||
}
|
||||
}
|
||||
|
||||
if(~subFlags&AI_SUBMESH_FLAGS_SANS_BONES) {
|
||||
std::vector<unsigned int> subBones(pMesh->mNumBones,0);
|
||||
if (~subFlags & AI_SUBMESH_FLAGS_SANS_BONES) {
|
||||
std::vector<unsigned int> subBones(pMesh->mNumBones, 0);
|
||||
|
||||
for(unsigned int a=0;a<pMesh->mNumBones;++a) {
|
||||
const aiBone* bone = pMesh->mBones[a];
|
||||
for (unsigned int a = 0; a < pMesh->mNumBones; ++a) {
|
||||
const aiBone *bone = pMesh->mBones[a];
|
||||
|
||||
for(unsigned int b=0;b<bone->mNumWeights;b++) {
|
||||
for (unsigned int b = 0; b < bone->mNumWeights; b++) {
|
||||
unsigned int v = vMap[bone->mWeights[b].mVertexId];
|
||||
|
||||
if(v!=UINT_MAX) {
|
||||
if (v != UINT_MAX) {
|
||||
subBones[a]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned int a=0;a<pMesh->mNumBones;++a) {
|
||||
if(subBones[a]>0) {
|
||||
for (unsigned int a = 0; a < pMesh->mNumBones; ++a) {
|
||||
if (subBones[a] > 0) {
|
||||
oMesh->mNumBones++;
|
||||
}
|
||||
}
|
||||
|
||||
if(oMesh->mNumBones) {
|
||||
oMesh->mBones = new aiBone*[oMesh->mNumBones]();
|
||||
if (oMesh->mNumBones) {
|
||||
oMesh->mBones = new aiBone *[oMesh->mNumBones]();
|
||||
unsigned int nbParanoia = oMesh->mNumBones;
|
||||
|
||||
oMesh->mNumBones = 0; //rewind
|
||||
|
||||
for(unsigned int a=0;a<pMesh->mNumBones;++a) {
|
||||
if(subBones[a]==0) {
|
||||
for (unsigned int a = 0; a < pMesh->mNumBones; ++a) {
|
||||
if (subBones[a] == 0) {
|
||||
continue;
|
||||
}
|
||||
aiBone *newBone = new aiBone;
|
||||
oMesh->mBones[oMesh->mNumBones++] = newBone;
|
||||
|
||||
const aiBone* bone = pMesh->mBones[a];
|
||||
const aiBone *bone = pMesh->mBones[a];
|
||||
|
||||
newBone->mName = bone->mName;
|
||||
newBone->mOffsetMatrix = bone->mOffsetMatrix;
|
||||
newBone->mWeights = new aiVertexWeight[subBones[a]];
|
||||
|
||||
for(unsigned int b=0;b<bone->mNumWeights;b++) {
|
||||
for (unsigned int b = 0; b < bone->mNumWeights; b++) {
|
||||
const unsigned int v = vMap[bone->mWeights[b].mVertexId];
|
||||
|
||||
if(v!=UINT_MAX) {
|
||||
aiVertexWeight w(v,bone->mWeights[b].mWeight);
|
||||
if (v != UINT_MAX) {
|
||||
aiVertexWeight w(v, bone->mWeights[b].mWeight);
|
||||
newBone->mWeights[newBone->mNumWeights++] = w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ai_assert(nbParanoia==oMesh->mNumBones);
|
||||
ai_assert(nbParanoia == oMesh->mNumBones);
|
||||
(void)nbParanoia; // remove compiler warning on release build
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,16 +43,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef AI_PROCESS_HELPER_H_INCLUDED
|
||||
#define AI_PROCESS_HELPER_H_INCLUDED
|
||||
|
||||
#include <assimp/postprocess.h>
|
||||
#include <assimp/anim.h>
|
||||
#include <assimp/mesh.h>
|
||||
#include <assimp/material.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/mesh.h>
|
||||
#include <assimp/postprocess.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
|
||||
#include <assimp/SpatialSort.h>
|
||||
#include "Common/BaseProcess.h"
|
||||
#include <assimp/ParsingUtils.h>
|
||||
#include <assimp/SpatialSort.h>
|
||||
|
||||
#include <list>
|
||||
|
||||
@@ -63,86 +63,83 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifdef __cplusplus
|
||||
namespace std {
|
||||
|
||||
// std::min for aiVector3D
|
||||
template <typename TReal>
|
||||
inline ::aiVector3t<TReal> min (const ::aiVector3t<TReal>& a, const ::aiVector3t<TReal>& b) {
|
||||
return ::aiVector3t<TReal> (min(a.x,b.x),min(a.y,b.y),min(a.z,b.z));
|
||||
}
|
||||
// std::min for aiVector3D
|
||||
template <typename TReal>
|
||||
inline ::aiVector3t<TReal> min(const ::aiVector3t<TReal> &a, const ::aiVector3t<TReal> &b) {
|
||||
return ::aiVector3t<TReal>(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
|
||||
}
|
||||
|
||||
// std::max for aiVector3t<TReal>
|
||||
template <typename TReal>
|
||||
inline ::aiVector3t<TReal> max (const ::aiVector3t<TReal>& a, const ::aiVector3t<TReal>& b) {
|
||||
return ::aiVector3t<TReal> (max(a.x,b.x),max(a.y,b.y),max(a.z,b.z));
|
||||
}
|
||||
// std::max for aiVector3t<TReal>
|
||||
template <typename TReal>
|
||||
inline ::aiVector3t<TReal> max(const ::aiVector3t<TReal> &a, const ::aiVector3t<TReal> &b) {
|
||||
return ::aiVector3t<TReal>(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
|
||||
}
|
||||
|
||||
// std::min for aiVector2t<TReal>
|
||||
template <typename TReal>
|
||||
inline ::aiVector2t<TReal> min (const ::aiVector2t<TReal>& a, const ::aiVector2t<TReal>& b) {
|
||||
return ::aiVector2t<TReal> (min(a.x,b.x),min(a.y,b.y));
|
||||
}
|
||||
// std::min for aiVector2t<TReal>
|
||||
template <typename TReal>
|
||||
inline ::aiVector2t<TReal> min(const ::aiVector2t<TReal> &a, const ::aiVector2t<TReal> &b) {
|
||||
return ::aiVector2t<TReal>(min(a.x, b.x), min(a.y, b.y));
|
||||
}
|
||||
|
||||
// std::max for aiVector2t<TReal>
|
||||
template <typename TReal>
|
||||
inline ::aiVector2t<TReal> max (const ::aiVector2t<TReal>& a, const ::aiVector2t<TReal>& b) {
|
||||
return ::aiVector2t<TReal> (max(a.x,b.x),max(a.y,b.y));
|
||||
}
|
||||
// std::max for aiVector2t<TReal>
|
||||
template <typename TReal>
|
||||
inline ::aiVector2t<TReal> max(const ::aiVector2t<TReal> &a, const ::aiVector2t<TReal> &b) {
|
||||
return ::aiVector2t<TReal>(max(a.x, b.x), max(a.y, b.y));
|
||||
}
|
||||
|
||||
// std::min for aiColor4D
|
||||
template <typename TReal>
|
||||
inline ::aiColor4t<TReal> min (const ::aiColor4t<TReal>& a, const ::aiColor4t<TReal>& b) {
|
||||
return ::aiColor4t<TReal> (min(a.r,b.r),min(a.g,b.g),min(a.b,b.b),min(a.a,b.a));
|
||||
}
|
||||
// std::min for aiColor4D
|
||||
template <typename TReal>
|
||||
inline ::aiColor4t<TReal> min(const ::aiColor4t<TReal> &a, const ::aiColor4t<TReal> &b) {
|
||||
return ::aiColor4t<TReal>(min(a.r, b.r), min(a.g, b.g), min(a.b, b.b), min(a.a, b.a));
|
||||
}
|
||||
|
||||
// std::max for aiColor4D
|
||||
template <typename TReal>
|
||||
inline ::aiColor4t<TReal> max (const ::aiColor4t<TReal>& a, const ::aiColor4t<TReal>& b) {
|
||||
return ::aiColor4t<TReal> (max(a.r,b.r),max(a.g,b.g),max(a.b,b.b),max(a.a,b.a));
|
||||
}
|
||||
// std::max for aiColor4D
|
||||
template <typename TReal>
|
||||
inline ::aiColor4t<TReal> max(const ::aiColor4t<TReal> &a, const ::aiColor4t<TReal> &b) {
|
||||
return ::aiColor4t<TReal>(max(a.r, b.r), max(a.g, b.g), max(a.b, b.b), max(a.a, b.a));
|
||||
}
|
||||
|
||||
// std::min for aiQuaterniont<TReal>
|
||||
template <typename TReal>
|
||||
inline ::aiQuaterniont<TReal> min(const ::aiQuaterniont<TReal> &a, const ::aiQuaterniont<TReal> &b) {
|
||||
return ::aiQuaterniont<TReal>(min(a.w, b.w), min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
|
||||
}
|
||||
|
||||
// std::min for aiQuaterniont<TReal>
|
||||
template <typename TReal>
|
||||
inline ::aiQuaterniont<TReal> min (const ::aiQuaterniont<TReal>& a, const ::aiQuaterniont<TReal>& b) {
|
||||
return ::aiQuaterniont<TReal> (min(a.w,b.w),min(a.x,b.x),min(a.y,b.y),min(a.z,b.z));
|
||||
}
|
||||
// std::max for aiQuaterniont<TReal>
|
||||
template <typename TReal>
|
||||
inline ::aiQuaterniont<TReal> max(const ::aiQuaterniont<TReal> &a, const ::aiQuaterniont<TReal> &b) {
|
||||
return ::aiQuaterniont<TReal>(max(a.w, b.w), max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
|
||||
}
|
||||
|
||||
// std::max for aiQuaterniont<TReal>
|
||||
template <typename TReal>
|
||||
inline ::aiQuaterniont<TReal> max (const ::aiQuaterniont<TReal>& a, const ::aiQuaterniont<TReal>& b) {
|
||||
return ::aiQuaterniont<TReal> (max(a.w,b.w),max(a.x,b.x),max(a.y,b.y),max(a.z,b.z));
|
||||
}
|
||||
// std::min for aiVectorKey
|
||||
inline ::aiVectorKey min(const ::aiVectorKey &a, const ::aiVectorKey &b) {
|
||||
return ::aiVectorKey(min(a.mTime, b.mTime), min(a.mValue, b.mValue));
|
||||
}
|
||||
|
||||
// std::max for aiVectorKey
|
||||
inline ::aiVectorKey max(const ::aiVectorKey &a, const ::aiVectorKey &b) {
|
||||
return ::aiVectorKey(max(a.mTime, b.mTime), max(a.mValue, b.mValue));
|
||||
}
|
||||
|
||||
// std::min for aiQuatKey
|
||||
inline ::aiQuatKey min(const ::aiQuatKey &a, const ::aiQuatKey &b) {
|
||||
return ::aiQuatKey(min(a.mTime, b.mTime), min(a.mValue, b.mValue));
|
||||
}
|
||||
|
||||
// std::min for aiVectorKey
|
||||
inline ::aiVectorKey min (const ::aiVectorKey& a, const ::aiVectorKey& b) {
|
||||
return ::aiVectorKey (min(a.mTime,b.mTime),min(a.mValue,b.mValue));
|
||||
}
|
||||
// std::max for aiQuatKey
|
||||
inline ::aiQuatKey max(const ::aiQuatKey &a, const ::aiQuatKey &b) {
|
||||
return ::aiQuatKey(max(a.mTime, b.mTime), max(a.mValue, b.mValue));
|
||||
}
|
||||
|
||||
// std::max for aiVectorKey
|
||||
inline ::aiVectorKey max (const ::aiVectorKey& a, const ::aiVectorKey& b) {
|
||||
return ::aiVectorKey (max(a.mTime,b.mTime),max(a.mValue,b.mValue));
|
||||
}
|
||||
// std::min for aiVertexWeight
|
||||
inline ::aiVertexWeight min(const ::aiVertexWeight &a, const ::aiVertexWeight &b) {
|
||||
return ::aiVertexWeight(min(a.mVertexId, b.mVertexId), min(a.mWeight, b.mWeight));
|
||||
}
|
||||
|
||||
// std::min for aiQuatKey
|
||||
inline ::aiQuatKey min (const ::aiQuatKey& a, const ::aiQuatKey& b) {
|
||||
return ::aiQuatKey (min(a.mTime,b.mTime),min(a.mValue,b.mValue));
|
||||
}
|
||||
|
||||
// std::max for aiQuatKey
|
||||
inline ::aiQuatKey max (const ::aiQuatKey& a, const ::aiQuatKey& b) {
|
||||
return ::aiQuatKey (max(a.mTime,b.mTime),max(a.mValue,b.mValue));
|
||||
}
|
||||
|
||||
// std::min for aiVertexWeight
|
||||
inline ::aiVertexWeight min (const ::aiVertexWeight& a, const ::aiVertexWeight& b) {
|
||||
return ::aiVertexWeight (min(a.mVertexId,b.mVertexId),min(a.mWeight,b.mWeight));
|
||||
}
|
||||
|
||||
// std::max for aiVertexWeight
|
||||
inline ::aiVertexWeight max (const ::aiVertexWeight& a, const ::aiVertexWeight& b) {
|
||||
return ::aiVertexWeight (max(a.mVertexId,b.mVertexId),max(a.mWeight,b.mWeight));
|
||||
}
|
||||
// std::max for aiVertexWeight
|
||||
inline ::aiVertexWeight max(const ::aiVertexWeight &a, const ::aiVertexWeight &b) {
|
||||
return ::aiVertexWeight(max(a.mVertexId, b.mVertexId), max(a.mWeight, b.mWeight));
|
||||
}
|
||||
|
||||
} // end namespace std
|
||||
#endif // !! C++
|
||||
@@ -154,60 +151,80 @@ namespace Assimp {
|
||||
template <typename T>
|
||||
struct MinMaxChooser;
|
||||
|
||||
template <> struct MinMaxChooser<float> {
|
||||
void operator ()(float& min,float& max) {
|
||||
template <>
|
||||
struct MinMaxChooser<float> {
|
||||
void operator()(float &min, float &max) {
|
||||
max = -1e10f;
|
||||
min = 1e10f;
|
||||
}};
|
||||
template <> struct MinMaxChooser<double> {
|
||||
void operator ()(double& min,double& max) {
|
||||
min = 1e10f;
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct MinMaxChooser<double> {
|
||||
void operator()(double &min, double &max) {
|
||||
max = -1e10;
|
||||
min = 1e10;
|
||||
}};
|
||||
template <> struct MinMaxChooser<unsigned int> {
|
||||
void operator ()(unsigned int& min,unsigned int& max) {
|
||||
min = 1e10;
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct MinMaxChooser<unsigned int> {
|
||||
void operator()(unsigned int &min, unsigned int &max) {
|
||||
max = 0;
|
||||
min = (1u<<(sizeof(unsigned int)*8-1));
|
||||
}};
|
||||
min = (1u << (sizeof(unsigned int) * 8 - 1));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct MinMaxChooser< aiVector3t<T> > {
|
||||
void operator ()(aiVector3t<T>& min,aiVector3t<T>& max) {
|
||||
max = aiVector3t<T>(-1e10f,-1e10f,-1e10f);
|
||||
min = aiVector3t<T>( 1e10f, 1e10f, 1e10f);
|
||||
}};
|
||||
template <typename T> struct MinMaxChooser< aiVector2t<T> > {
|
||||
void operator ()(aiVector2t<T>& min,aiVector2t<T>& max) {
|
||||
max = aiVector2t<T>(-1e10f,-1e10f);
|
||||
min = aiVector2t<T>( 1e10f, 1e10f);
|
||||
}};
|
||||
template <typename T> struct MinMaxChooser< aiColor4t<T> > {
|
||||
void operator ()(aiColor4t<T>& min,aiColor4t<T>& max) {
|
||||
max = aiColor4t<T>(-1e10f,-1e10f,-1e10f,-1e10f);
|
||||
min = aiColor4t<T>( 1e10f, 1e10f, 1e10f, 1e10f);
|
||||
}};
|
||||
template <typename T>
|
||||
struct MinMaxChooser<aiVector3t<T>> {
|
||||
void operator()(aiVector3t<T> &min, aiVector3t<T> &max) {
|
||||
max = aiVector3t<T>(-1e10f, -1e10f, -1e10f);
|
||||
min = aiVector3t<T>(1e10f, 1e10f, 1e10f);
|
||||
}
|
||||
};
|
||||
template <typename T>
|
||||
struct MinMaxChooser<aiVector2t<T>> {
|
||||
void operator()(aiVector2t<T> &min, aiVector2t<T> &max) {
|
||||
max = aiVector2t<T>(-1e10f, -1e10f);
|
||||
min = aiVector2t<T>(1e10f, 1e10f);
|
||||
}
|
||||
};
|
||||
template <typename T>
|
||||
struct MinMaxChooser<aiColor4t<T>> {
|
||||
void operator()(aiColor4t<T> &min, aiColor4t<T> &max) {
|
||||
max = aiColor4t<T>(-1e10f, -1e10f, -1e10f, -1e10f);
|
||||
min = aiColor4t<T>(1e10f, 1e10f, 1e10f, 1e10f);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct MinMaxChooser< aiQuaterniont<T> > {
|
||||
void operator ()(aiQuaterniont<T>& min,aiQuaterniont<T>& max) {
|
||||
max = aiQuaterniont<T>(-1e10f,-1e10f,-1e10f,-1e10f);
|
||||
min = aiQuaterniont<T>( 1e10f, 1e10f, 1e10f, 1e10f);
|
||||
}};
|
||||
template <typename T>
|
||||
struct MinMaxChooser<aiQuaterniont<T>> {
|
||||
void operator()(aiQuaterniont<T> &min, aiQuaterniont<T> &max) {
|
||||
max = aiQuaterniont<T>(-1e10f, -1e10f, -1e10f, -1e10f);
|
||||
min = aiQuaterniont<T>(1e10f, 1e10f, 1e10f, 1e10f);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MinMaxChooser<aiVectorKey> {
|
||||
void operator ()(aiVectorKey& min,aiVectorKey& max) {
|
||||
MinMaxChooser<double>()(min.mTime,max.mTime);
|
||||
MinMaxChooser<aiVector3D>()(min.mValue,max.mValue);
|
||||
}};
|
||||
template <> struct MinMaxChooser<aiQuatKey> {
|
||||
void operator ()(aiQuatKey& min,aiQuatKey& max) {
|
||||
MinMaxChooser<double>()(min.mTime,max.mTime);
|
||||
MinMaxChooser<aiQuaternion>()(min.mValue,max.mValue);
|
||||
}};
|
||||
template <>
|
||||
struct MinMaxChooser<aiVectorKey> {
|
||||
void operator()(aiVectorKey &min, aiVectorKey &max) {
|
||||
MinMaxChooser<double>()(min.mTime, max.mTime);
|
||||
MinMaxChooser<aiVector3D>()(min.mValue, max.mValue);
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct MinMaxChooser<aiQuatKey> {
|
||||
void operator()(aiQuatKey &min, aiQuatKey &max) {
|
||||
MinMaxChooser<double>()(min.mTime, max.mTime);
|
||||
MinMaxChooser<aiQuaternion>()(min.mValue, max.mValue);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MinMaxChooser<aiVertexWeight> {
|
||||
void operator ()(aiVertexWeight& min,aiVertexWeight& max) {
|
||||
MinMaxChooser<unsigned int>()(min.mVertexId,max.mVertexId);
|
||||
MinMaxChooser<float>()(min.mWeight,max.mWeight);
|
||||
}};
|
||||
template <>
|
||||
struct MinMaxChooser<aiVertexWeight> {
|
||||
void operator()(aiVertexWeight &min, aiVertexWeight &max) {
|
||||
MinMaxChooser<unsigned int>()(min.mVertexId, max.mVertexId);
|
||||
MinMaxChooser<float>()(min.mWeight, max.mWeight);
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** @brief Find the min/max values of an array of Ts
|
||||
@@ -217,36 +234,31 @@ template <> struct MinMaxChooser<aiVertexWeight> {
|
||||
* @param[out] max maximum value
|
||||
*/
|
||||
template <typename T>
|
||||
inline void ArrayBounds(const T* in, unsigned int size, T& min, T& max)
|
||||
{
|
||||
MinMaxChooser<T> ()(min,max);
|
||||
for (unsigned int i = 0; i < size;++i) {
|
||||
min = std::min(in[i],min);
|
||||
max = std::max(in[i],max);
|
||||
inline void ArrayBounds(const T *in, unsigned int size, T &min, T &max) {
|
||||
MinMaxChooser<T>()(min, max);
|
||||
for (unsigned int i = 0; i < size; ++i) {
|
||||
min = std::min(in[i], min);
|
||||
max = std::max(in[i], max);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Little helper function to calculate the quadratic difference
|
||||
* of two colours.
|
||||
* @param pColor1 First color
|
||||
* @param pColor2 second color
|
||||
* @return Quadratic color difference */
|
||||
inline ai_real 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;
|
||||
inline ai_real 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;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** @brief Extract single strings from a list of identifiers
|
||||
* @param in Input string list.
|
||||
* @param out Receives a list of clean output strings
|
||||
* @sdee #AI_CONFIG_PP_OG_EXCLUDE_LIST */
|
||||
void ConvertListToStrings(const std::string& in, std::list<std::string>& out);
|
||||
|
||||
void ConvertListToStrings(const std::string &in, std::list<std::string> &out);
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** @brief Compute the AABB of a mesh after applying a given transform
|
||||
@@ -254,8 +266,7 @@ void ConvertListToStrings(const std::string& in, std::list<std::string>& out);
|
||||
* @param[out] min Receives minimum transformed vertex
|
||||
* @param[out] max Receives maximum transformed vertex
|
||||
* @param m Transformation matrix to be applied */
|
||||
void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max, const aiMatrix4x4& m);
|
||||
|
||||
void FindAABBTransformed(const aiMesh *mesh, aiVector3D &min, aiVector3D &max, const aiMatrix4x4 &m);
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** @brief Helper function to determine the 'real' center of a mesh
|
||||
@@ -265,7 +276,7 @@ void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max,
|
||||
* @param[out] min Minimum vertex of the mesh
|
||||
* @param[out] max maximum vertex of the mesh
|
||||
* @param[out] out Center point */
|
||||
void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D& max);
|
||||
void FindMeshCenter(aiMesh *mesh, aiVector3D &out, aiVector3D &min, aiVector3D &max);
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** @brief Helper function to determine the 'real' center of a scene
|
||||
@@ -275,106 +286,90 @@ void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D&
|
||||
* @param[out] min Minimum vertex of the scene
|
||||
* @param[out] max maximum vertex of the scene
|
||||
* @param[out] out Center point */
|
||||
void FindSceneCenter (aiScene* scene, aiVector3D& out, aiVector3D& min, aiVector3D& max);
|
||||
|
||||
void FindSceneCenter(aiScene *scene, aiVector3D &out, aiVector3D &min, aiVector3D &max);
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Helper function to determine the 'real' center of a mesh after applying a given transform
|
||||
void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out, aiVector3D& min,aiVector3D& max, const aiMatrix4x4& m);
|
||||
|
||||
void FindMeshCenterTransformed(aiMesh *mesh, aiVector3D &out, aiVector3D &min, aiVector3D &max, const aiMatrix4x4 &m);
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Helper function to determine the 'real' center of a mesh
|
||||
void FindMeshCenter (aiMesh* mesh, aiVector3D& out);
|
||||
|
||||
void FindMeshCenter(aiMesh *mesh, aiVector3D &out);
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Helper function to determine the 'real' center of a mesh after applying a given transform
|
||||
void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out,const aiMatrix4x4& m);
|
||||
|
||||
void FindMeshCenterTransformed(aiMesh *mesh, aiVector3D &out, const aiMatrix4x4 &m);
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Compute a good epsilon value for position comparisons on a mesh
|
||||
ai_real ComputePositionEpsilon(const aiMesh* pMesh);
|
||||
|
||||
ai_real ComputePositionEpsilon(const aiMesh *pMesh);
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Compute a good epsilon value for position comparisons on a array of meshes
|
||||
ai_real ComputePositionEpsilon(const aiMesh* const* pMeshes, size_t num);
|
||||
|
||||
ai_real ComputePositionEpsilon(const aiMesh *const *pMeshes, size_t num);
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Compute an unique value for the vertex format of a mesh
|
||||
unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh);
|
||||
|
||||
unsigned int GetMeshVFormatUnique(const aiMesh *pcMesh);
|
||||
|
||||
// defs for ComputeVertexBoneWeightTable()
|
||||
typedef std::pair <unsigned int,float> PerVertexWeight;
|
||||
typedef std::vector <PerVertexWeight> VertexWeightTable;
|
||||
typedef std::pair<unsigned int, float> PerVertexWeight;
|
||||
typedef std::vector<PerVertexWeight> VertexWeightTable;
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Compute a per-vertex bone weight table
|
||||
VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh);
|
||||
VertexWeightTable *ComputeVertexBoneWeightTable(const aiMesh *pMesh);
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Get a string for a given aiTextureMapping
|
||||
const char* MappingTypeToString(aiTextureMapping in);
|
||||
|
||||
const char *MappingTypeToString(aiTextureMapping in);
|
||||
|
||||
// flags for MakeSubmesh()
|
||||
#define AI_SUBMESH_FLAGS_SANS_BONES 0x1
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Split a mesh given a list of faces to be contained in the sub mesh
|
||||
aiMesh* MakeSubmesh(const aiMesh *superMesh, const std::vector<unsigned int> &subMeshFaces, unsigned int subFlags);
|
||||
aiMesh *MakeSubmesh(const aiMesh *superMesh, const std::vector<unsigned int> &subMeshFaces, unsigned int subFlags);
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// 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
|
||||
{
|
||||
return NULL != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
|
||||
aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
|
||||
class ComputeSpatialSortProcess : public BaseProcess {
|
||||
bool IsActive(unsigned int pFlags) const {
|
||||
return nullptr != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
|
||||
aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
|
||||
}
|
||||
|
||||
void Execute( aiScene* pScene)
|
||||
{
|
||||
void Execute(aiScene *pScene) {
|
||||
typedef std::pair<SpatialSort, ai_real> _Type;
|
||||
ASSIMP_LOG_DEBUG("Generate spatially-sorted vertex cache");
|
||||
|
||||
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();
|
||||
|
||||
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));
|
||||
aiMesh *mesh = pScene->mMeshes[i];
|
||||
_Type &blubb = *it;
|
||||
blubb.first.Fill(mesh->mVertices, mesh->mNumVertices, sizeof(aiVector3D));
|
||||
blubb.second = ComputePositionEpsilon(mesh);
|
||||
}
|
||||
|
||||
shared->AddProperty(AI_SPP_SPATIAL_SORT,p);
|
||||
shared->AddProperty(AI_SPP_SPATIAL_SORT, p);
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// ... and the same again to cleanup the whole stuff
|
||||
class DestroySpatialSortProcess : public BaseProcess
|
||||
{
|
||||
bool IsActive( unsigned int pFlags) const
|
||||
{
|
||||
return NULL != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
|
||||
aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
|
||||
class DestroySpatialSortProcess : public BaseProcess {
|
||||
bool IsActive(unsigned int pFlags) const {
|
||||
return nullptr != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
|
||||
aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
|
||||
}
|
||||
|
||||
void Execute( aiScene* /*pScene*/)
|
||||
{
|
||||
void Execute(aiScene * /*pScene*/) {
|
||||
shared->RemoveProperty(AI_SPP_SPATIAL_SORT);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // ! namespace Assimp
|
||||
} // namespace Assimp
|
||||
#endif // !! AI_PROCESS_HELPER_H_INCLUDED
|
||||
|
||||
@@ -122,7 +122,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
|
||||
|
||||
// Keep this material even if no mesh references it
|
||||
abReferenced[i] = true;
|
||||
ASSIMP_LOG_DEBUG_F( "Found positive match in exclusion list: \'", name.data, "\'");
|
||||
ASSIMP_LOG_VERBOSE_DEBUG_F( "Found positive match in exclusion list: \'", name.data, "\'");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,7 +197,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
|
||||
// update all material indices
|
||||
for (unsigned int p = 0; p < pScene->mNumMeshes;++p) {
|
||||
aiMesh* mesh = pScene->mMeshes[p];
|
||||
ai_assert( NULL!=mesh );
|
||||
ai_assert(nullptr != mesh);
|
||||
mesh->mMaterialIndex = aiMappingTable[mesh->mMaterialIndex];
|
||||
}
|
||||
// delete the old material list
|
||||
|
||||
@@ -44,43 +44,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* any parts of the mesh structure from the imported data.
|
||||
*/
|
||||
|
||||
|
||||
#include "RemoveVCProcess.h"
|
||||
#include <assimp/postprocess.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
RemoveVCProcess::RemoveVCProcess() :
|
||||
configDeleteFlags()
|
||||
, mScene()
|
||||
{}
|
||||
configDeleteFlags(), mScene() {}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
RemoveVCProcess::~RemoveVCProcess()
|
||||
{}
|
||||
RemoveVCProcess::~RemoveVCProcess() {}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
bool RemoveVCProcess::IsActive( unsigned int pFlags) const
|
||||
{
|
||||
bool RemoveVCProcess::IsActive(unsigned int pFlags) const {
|
||||
return (pFlags & aiProcess_RemoveComponent) != 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Small helper function to delete all elements in a T** aray using delete
|
||||
template <typename T>
|
||||
inline void ArrayDelete(T**& in, unsigned int& num)
|
||||
{
|
||||
inline void ArrayDelete(T **&in, unsigned int &num) {
|
||||
for (unsigned int i = 0; i < num; ++i)
|
||||
delete in[i];
|
||||
|
||||
delete[] in;
|
||||
in = NULL;
|
||||
in = nullptr;
|
||||
num = 0;
|
||||
}
|
||||
|
||||
@@ -108,9 +102,9 @@ bool UpdateNodeGraph(aiNode* node,std::list<aiNode*>& childsOfParent,bool root)
|
||||
{
|
||||
childsOfParent.insert(childsOfParent.end(),mine.begin(),mine.end());
|
||||
|
||||
// set all children to NULL to make sure they are not deleted when we delete ourself
|
||||
// set all children to nullptr to make sure they are not deleted when we delete ourself
|
||||
for (unsigned int i = 0; i < node->mNumChildren;++i)
|
||||
node->mChildren[i] = NULL;
|
||||
node->mChildren[i] = nullptr;
|
||||
}
|
||||
b = true;
|
||||
delete node;
|
||||
@@ -143,86 +137,74 @@ bool UpdateNodeGraph(aiNode* node,std::list<aiNode*>& childsOfParent,bool root)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void RemoveVCProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
void RemoveVCProcess::Execute(aiScene *pScene) {
|
||||
ASSIMP_LOG_DEBUG("RemoveVCProcess begin");
|
||||
bool bHas = false; //,bMasked = false;
|
||||
|
||||
mScene = pScene;
|
||||
|
||||
// handle animations
|
||||
if ( configDeleteFlags & aiComponent_ANIMATIONS)
|
||||
{
|
||||
if (configDeleteFlags & aiComponent_ANIMATIONS) {
|
||||
|
||||
bHas = true;
|
||||
ArrayDelete(pScene->mAnimations,pScene->mNumAnimations);
|
||||
ArrayDelete(pScene->mAnimations, pScene->mNumAnimations);
|
||||
}
|
||||
|
||||
// handle textures
|
||||
if ( configDeleteFlags & aiComponent_TEXTURES)
|
||||
{
|
||||
if (configDeleteFlags & aiComponent_TEXTURES) {
|
||||
bHas = true;
|
||||
ArrayDelete(pScene->mTextures,pScene->mNumTextures);
|
||||
ArrayDelete(pScene->mTextures, pScene->mNumTextures);
|
||||
}
|
||||
|
||||
// handle materials
|
||||
if ( configDeleteFlags & aiComponent_MATERIALS && pScene->mNumMaterials)
|
||||
{
|
||||
if (configDeleteFlags & aiComponent_MATERIALS && pScene->mNumMaterials) {
|
||||
bHas = true;
|
||||
for (unsigned int i = 1;i < pScene->mNumMaterials;++i)
|
||||
for (unsigned int i = 1; i < pScene->mNumMaterials; ++i)
|
||||
delete pScene->mMaterials[i];
|
||||
|
||||
pScene->mNumMaterials = 1;
|
||||
aiMaterial* helper = (aiMaterial*) pScene->mMaterials[0];
|
||||
ai_assert(NULL != helper);
|
||||
aiMaterial *helper = (aiMaterial *)pScene->mMaterials[0];
|
||||
ai_assert(nullptr != helper);
|
||||
helper->Clear();
|
||||
|
||||
// gray
|
||||
aiColor3D clr(0.6f,0.6f,0.6f);
|
||||
helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
|
||||
aiColor3D clr(0.6f, 0.6f, 0.6f);
|
||||
helper->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
|
||||
// add a small ambient color value
|
||||
clr = aiColor3D(0.05f,0.05f,0.05f);
|
||||
helper->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT);
|
||||
clr = aiColor3D(0.05f, 0.05f, 0.05f);
|
||||
helper->AddProperty(&clr, 1, AI_MATKEY_COLOR_AMBIENT);
|
||||
|
||||
aiString s;
|
||||
s.Set("Dummy_MaterialsRemoved");
|
||||
helper->AddProperty(&s,AI_MATKEY_NAME);
|
||||
helper->AddProperty(&s, AI_MATKEY_NAME);
|
||||
}
|
||||
|
||||
// handle light sources
|
||||
if ( configDeleteFlags & aiComponent_LIGHTS)
|
||||
{
|
||||
bHas = true;
|
||||
ArrayDelete(pScene->mLights,pScene->mNumLights);
|
||||
if (configDeleteFlags & aiComponent_LIGHTS) {
|
||||
bHas = true;
|
||||
ArrayDelete(pScene->mLights, pScene->mNumLights);
|
||||
}
|
||||
|
||||
// handle camneras
|
||||
if ( configDeleteFlags & aiComponent_CAMERAS)
|
||||
{
|
||||
if (configDeleteFlags & aiComponent_CAMERAS) {
|
||||
bHas = true;
|
||||
ArrayDelete(pScene->mCameras,pScene->mNumCameras);
|
||||
ArrayDelete(pScene->mCameras, pScene->mNumCameras);
|
||||
}
|
||||
|
||||
// handle meshes
|
||||
if (configDeleteFlags & aiComponent_MESHES)
|
||||
{
|
||||
if (configDeleteFlags & aiComponent_MESHES) {
|
||||
bHas = true;
|
||||
ArrayDelete(pScene->mMeshes,pScene->mNumMeshes);
|
||||
}
|
||||
else
|
||||
{
|
||||
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
|
||||
{
|
||||
if( ProcessMesh( pScene->mMeshes[a]))
|
||||
ArrayDelete(pScene->mMeshes, pScene->mNumMeshes);
|
||||
} else {
|
||||
for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
|
||||
if (ProcessMesh(pScene->mMeshes[a]))
|
||||
bHas = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// now check whether the result is still a full scene
|
||||
if (!pScene->mNumMeshes || !pScene->mNumMaterials)
|
||||
{
|
||||
if (!pScene->mNumMeshes || !pScene->mNumMaterials) {
|
||||
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
|
||||
ASSIMP_LOG_DEBUG("Setting AI_SCENE_FLAGS_INCOMPLETE flag");
|
||||
|
||||
@@ -240,63 +222,55 @@ void RemoveVCProcess::Execute( aiScene* pScene)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup configuration properties for the step
|
||||
void RemoveVCProcess::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
configDeleteFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS,0x0);
|
||||
if (!configDeleteFlags)
|
||||
{
|
||||
void RemoveVCProcess::SetupProperties(const Importer *pImp) {
|
||||
configDeleteFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, 0x0);
|
||||
if (!configDeleteFlags) {
|
||||
ASSIMP_LOG_WARN("RemoveVCProcess: AI_CONFIG_PP_RVC_FLAGS is zero.");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh)
|
||||
{
|
||||
bool RemoveVCProcess::ProcessMesh(aiMesh *pMesh) {
|
||||
bool ret = false;
|
||||
|
||||
// if all materials have been deleted let the material
|
||||
// index of the mesh point to the created default material
|
||||
if ( configDeleteFlags & aiComponent_MATERIALS)
|
||||
if (configDeleteFlags & aiComponent_MATERIALS)
|
||||
pMesh->mMaterialIndex = 0;
|
||||
|
||||
// handle normals
|
||||
if (configDeleteFlags & aiComponent_NORMALS && pMesh->mNormals)
|
||||
{
|
||||
if (configDeleteFlags & aiComponent_NORMALS && pMesh->mNormals) {
|
||||
delete[] pMesh->mNormals;
|
||||
pMesh->mNormals = NULL;
|
||||
pMesh->mNormals = nullptr;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// handle tangents and bitangents
|
||||
if (configDeleteFlags & aiComponent_TANGENTS_AND_BITANGENTS && pMesh->mTangents)
|
||||
{
|
||||
if (configDeleteFlags & aiComponent_TANGENTS_AND_BITANGENTS && pMesh->mTangents) {
|
||||
delete[] pMesh->mTangents;
|
||||
pMesh->mTangents = NULL;
|
||||
pMesh->mTangents = nullptr;
|
||||
|
||||
delete[] pMesh->mBitangents;
|
||||
pMesh->mBitangents = NULL;
|
||||
pMesh->mBitangents = nullptr;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// handle texture coordinates
|
||||
bool b = (0 != (configDeleteFlags & aiComponent_TEXCOORDS));
|
||||
for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++real)
|
||||
{
|
||||
if (!pMesh->mTextureCoords[i])break;
|
||||
if (configDeleteFlags & aiComponent_TEXCOORDSn(real) || b)
|
||||
{
|
||||
delete [] pMesh->mTextureCoords[i];
|
||||
pMesh->mTextureCoords[i] = NULL;
|
||||
for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++real) {
|
||||
if (!pMesh->mTextureCoords[i]) break;
|
||||
if (configDeleteFlags & aiComponent_TEXCOORDSn(real) || b) {
|
||||
delete[] pMesh->mTextureCoords[i];
|
||||
pMesh->mTextureCoords[i] = nullptr;
|
||||
ret = true;
|
||||
|
||||
if (!b)
|
||||
{
|
||||
if (!b) {
|
||||
// collapse the rest of the array
|
||||
for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a)
|
||||
pMesh->mTextureCoords[a-1] = pMesh->mTextureCoords[a];
|
||||
for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a)
|
||||
pMesh->mTextureCoords[a - 1] = pMesh->mTextureCoords[a];
|
||||
|
||||
pMesh->mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS-1] = NULL;
|
||||
pMesh->mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS - 1] = nullptr;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -305,22 +279,19 @@ bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh)
|
||||
|
||||
// handle vertex colors
|
||||
b = (0 != (configDeleteFlags & aiComponent_COLORS));
|
||||
for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_COLOR_SETS; ++real)
|
||||
{
|
||||
if (!pMesh->mColors[i])break;
|
||||
if (configDeleteFlags & aiComponent_COLORSn(i) || b)
|
||||
{
|
||||
delete [] pMesh->mColors[i];
|
||||
pMesh->mColors[i] = NULL;
|
||||
for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_COLOR_SETS; ++real) {
|
||||
if (!pMesh->mColors[i]) break;
|
||||
if (configDeleteFlags & aiComponent_COLORSn(i) || b) {
|
||||
delete[] pMesh->mColors[i];
|
||||
pMesh->mColors[i] = nullptr;
|
||||
ret = true;
|
||||
|
||||
if (!b)
|
||||
{
|
||||
if (!b) {
|
||||
// collapse the rest of the array
|
||||
for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a)
|
||||
pMesh->mColors[a-1] = pMesh->mColors[a];
|
||||
for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a)
|
||||
pMesh->mColors[a - 1] = pMesh->mColors[a];
|
||||
|
||||
pMesh->mColors[AI_MAX_NUMBER_OF_COLOR_SETS-1] = NULL;
|
||||
pMesh->mColors[AI_MAX_NUMBER_OF_COLOR_SETS - 1] = nullptr;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -328,9 +299,8 @@ bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh)
|
||||
}
|
||||
|
||||
// handle bones
|
||||
if (configDeleteFlags & aiComponent_BONEWEIGHTS && pMesh->mBones)
|
||||
{
|
||||
ArrayDelete(pMesh->mBones,pMesh->mNumBones);
|
||||
if (configDeleteFlags & aiComponent_BONEWEIGHTS && pMesh->mBones) {
|
||||
ArrayDelete(pMesh->mBones, pMesh->mNumBones);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -94,4 +94,4 @@ private:
|
||||
} // Namespace Assimp
|
||||
|
||||
|
||||
#endif // SCALE_PROCESS_H_
|
||||
#endif // SCALE_PROCESS_H_
|
||||
|
||||
@@ -45,111 +45,96 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SortByPTypeProcess post-process steps.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// internal headers
|
||||
#include "ProcessHelper.h"
|
||||
#include "SortByPTypeProcess.h"
|
||||
#include "ProcessHelper.h"
|
||||
#include <assimp/Exceptional.h>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
SortByPTypeProcess::SortByPTypeProcess()
|
||||
: mConfigRemoveMeshes( 0 ) {
|
||||
SortByPTypeProcess::SortByPTypeProcess() :
|
||||
mConfigRemoveMeshes(0) {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
SortByPTypeProcess::~SortByPTypeProcess()
|
||||
{
|
||||
SortByPTypeProcess::~SortByPTypeProcess() {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
bool SortByPTypeProcess::IsActive( unsigned int pFlags) const
|
||||
{
|
||||
return (pFlags & aiProcess_SortByPType) != 0;
|
||||
bool SortByPTypeProcess::IsActive(unsigned int pFlags) const {
|
||||
return (pFlags & aiProcess_SortByPType) != 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SortByPTypeProcess::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
mConfigRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,0);
|
||||
void SortByPTypeProcess::SetupProperties(const Importer *pImp) {
|
||||
mConfigRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, 0);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Update changed meshes in all nodes
|
||||
void UpdateNodes(const std::vector<unsigned int>& replaceMeshIndex, aiNode* node)
|
||||
{
|
||||
if (node->mNumMeshes)
|
||||
{
|
||||
void UpdateNodes(const std::vector<unsigned int> &replaceMeshIndex, aiNode *node) {
|
||||
if (node->mNumMeshes) {
|
||||
unsigned int newSize = 0;
|
||||
for (unsigned int m = 0; m< node->mNumMeshes; ++m)
|
||||
{
|
||||
unsigned int add = node->mMeshes[m]<<2;
|
||||
for (unsigned int i = 0; i < 4;++i)
|
||||
{
|
||||
if (UINT_MAX != replaceMeshIndex[add+i])++newSize;
|
||||
for (unsigned int m = 0; m < node->mNumMeshes; ++m) {
|
||||
unsigned int add = node->mMeshes[m] << 2;
|
||||
for (unsigned int i = 0; i < 4; ++i) {
|
||||
if (UINT_MAX != replaceMeshIndex[add + i]) ++newSize;
|
||||
}
|
||||
}
|
||||
if (!newSize)
|
||||
{
|
||||
if (!newSize) {
|
||||
delete[] node->mMeshes;
|
||||
node->mNumMeshes = 0;
|
||||
node->mMeshes = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->mMeshes = nullptr;
|
||||
} else {
|
||||
// Try to reuse the old array if possible
|
||||
unsigned int* newMeshes = (newSize > node->mNumMeshes
|
||||
? new unsigned int[newSize] : node->mMeshes);
|
||||
unsigned int *newMeshes = (newSize > node->mNumMeshes ? new unsigned int[newSize] : node->mMeshes);
|
||||
|
||||
for (unsigned int m = 0; m< node->mNumMeshes; ++m)
|
||||
{
|
||||
unsigned int add = node->mMeshes[m]<<2;
|
||||
for (unsigned int i = 0; i < 4;++i)
|
||||
{
|
||||
if (UINT_MAX != replaceMeshIndex[add+i])
|
||||
*newMeshes++ = replaceMeshIndex[add+i];
|
||||
for (unsigned int m = 0; m < node->mNumMeshes; ++m) {
|
||||
unsigned int add = node->mMeshes[m] << 2;
|
||||
for (unsigned int i = 0; i < 4; ++i) {
|
||||
if (UINT_MAX != replaceMeshIndex[add + i])
|
||||
*newMeshes++ = replaceMeshIndex[add + i];
|
||||
}
|
||||
}
|
||||
if (newSize > node->mNumMeshes)
|
||||
delete[] node->mMeshes;
|
||||
|
||||
node->mMeshes = newMeshes-(node->mNumMeshes = newSize);
|
||||
node->mMeshes = newMeshes - (node->mNumMeshes = newSize);
|
||||
}
|
||||
}
|
||||
|
||||
// call all subnodes recursively
|
||||
for (unsigned int m = 0; m < node->mNumChildren; ++m)
|
||||
UpdateNodes(replaceMeshIndex,node->mChildren[m]);
|
||||
UpdateNodes(replaceMeshIndex, node->mChildren[m]);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void SortByPTypeProcess::Execute( aiScene* pScene) {
|
||||
if ( 0 == pScene->mNumMeshes) {
|
||||
void SortByPTypeProcess::Execute(aiScene *pScene) {
|
||||
if (0 == pScene->mNumMeshes) {
|
||||
ASSIMP_LOG_DEBUG("SortByPTypeProcess skipped, there are no meshes");
|
||||
return;
|
||||
}
|
||||
|
||||
ASSIMP_LOG_DEBUG("SortByPTypeProcess begin");
|
||||
|
||||
unsigned int aiNumMeshesPerPType[4] = {0,0,0,0};
|
||||
unsigned int aiNumMeshesPerPType[4] = { 0, 0, 0, 0 };
|
||||
|
||||
std::vector<aiMesh*> outMeshes;
|
||||
outMeshes.reserve(pScene->mNumMeshes<<1u);
|
||||
std::vector<aiMesh *> outMeshes;
|
||||
outMeshes.reserve(pScene->mNumMeshes << 1u);
|
||||
|
||||
bool bAnyChanges = false;
|
||||
|
||||
std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes*4,UINT_MAX);
|
||||
std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes * 4, UINT_MAX);
|
||||
std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin();
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||
aiMesh* const mesh = pScene->mMeshes[i];
|
||||
aiMesh *const mesh = pScene->mMeshes[i];
|
||||
ai_assert(0 != mesh->mPrimitiveTypes);
|
||||
|
||||
// if there's just one primitive type in the mesh there's nothing to do for us
|
||||
@@ -173,11 +158,11 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
|
||||
|
||||
if (1 == num) {
|
||||
if (!(mConfigRemoveMeshes & mesh->mPrimitiveTypes)) {
|
||||
*meshIdx = static_cast<unsigned int>( outMeshes.size() );
|
||||
*meshIdx = static_cast<unsigned int>(outMeshes.size());
|
||||
outMeshes.push_back(mesh);
|
||||
} else {
|
||||
delete mesh;
|
||||
pScene->mMeshes[ i ] = nullptr;
|
||||
pScene->mMeshes[i] = nullptr;
|
||||
bAnyChanges = true;
|
||||
}
|
||||
|
||||
@@ -188,32 +173,29 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
|
||||
|
||||
// reuse our current mesh arrays for the submesh
|
||||
// with the largest number of primitives
|
||||
unsigned int aiNumPerPType[4] = {0,0,0,0};
|
||||
aiFace* pFirstFace = mesh->mFaces;
|
||||
aiFace* const pLastFace = pFirstFace + mesh->mNumFaces;
|
||||
unsigned int aiNumPerPType[4] = { 0, 0, 0, 0 };
|
||||
aiFace *pFirstFace = mesh->mFaces;
|
||||
aiFace *const pLastFace = pFirstFace + mesh->mNumFaces;
|
||||
|
||||
unsigned int numPolyVerts = 0;
|
||||
for (;pFirstFace != pLastFace; ++pFirstFace) {
|
||||
for (; pFirstFace != pLastFace; ++pFirstFace) {
|
||||
if (pFirstFace->mNumIndices <= 3)
|
||||
++aiNumPerPType[pFirstFace->mNumIndices-1];
|
||||
else
|
||||
{
|
||||
++aiNumPerPType[pFirstFace->mNumIndices - 1];
|
||||
else {
|
||||
++aiNumPerPType[3];
|
||||
numPolyVerts += pFirstFace-> mNumIndices;
|
||||
numPolyVerts += pFirstFace->mNumIndices;
|
||||
}
|
||||
}
|
||||
|
||||
VertexWeightTable* avw = ComputeVertexBoneWeightTable(mesh);
|
||||
for (unsigned int real = 0; real < 4; ++real,++meshIdx)
|
||||
{
|
||||
if ( !aiNumPerPType[real] || mConfigRemoveMeshes & (1u << real))
|
||||
{
|
||||
VertexWeightTable *avw = ComputeVertexBoneWeightTable(mesh);
|
||||
for (unsigned int real = 0; real < 4; ++real, ++meshIdx) {
|
||||
if (!aiNumPerPType[real] || mConfigRemoveMeshes & (1u << real)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
*meshIdx = (unsigned int) outMeshes.size();
|
||||
*meshIdx = (unsigned int)outMeshes.size();
|
||||
outMeshes.push_back(new aiMesh());
|
||||
aiMesh* out = outMeshes.back();
|
||||
aiMesh *out = outMeshes.back();
|
||||
|
||||
// the name carries the adjacency information between the meshes
|
||||
out->mName = mesh->mName;
|
||||
@@ -224,13 +206,13 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
|
||||
|
||||
// allocate output storage
|
||||
out->mNumFaces = aiNumPerPType[real];
|
||||
aiFace* outFaces = out->mFaces = new aiFace[out->mNumFaces];
|
||||
aiFace *outFaces = out->mFaces = new aiFace[out->mNumFaces];
|
||||
|
||||
out->mNumVertices = (3 == real ? numPolyVerts : out->mNumFaces * (real+1));
|
||||
out->mNumVertices = (3 == real ? numPolyVerts : out->mNumFaces * (real + 1));
|
||||
|
||||
aiVector3D *vert(nullptr), *nor(nullptr), *tan(nullptr), *bit(nullptr);
|
||||
aiVector3D *uv [AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||||
aiColor4D *cols [AI_MAX_NUMBER_OF_COLOR_SETS];
|
||||
aiVector3D *uv[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||||
aiColor4D *cols[AI_MAX_NUMBER_OF_COLOR_SETS];
|
||||
|
||||
if (mesh->mVertices) {
|
||||
vert = out->mVertices = new aiVector3D[out->mNumVertices];
|
||||
@@ -241,11 +223,11 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
|
||||
}
|
||||
|
||||
if (mesh->mTangents) {
|
||||
tan = out->mTangents = new aiVector3D[out->mNumVertices];
|
||||
tan = out->mTangents = new aiVector3D[out->mNumVertices];
|
||||
bit = out->mBitangents = new aiVector3D[out->mNumVertices];
|
||||
}
|
||||
|
||||
for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_TEXTURECOORDS;++j) {
|
||||
for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++j) {
|
||||
uv[j] = nullptr;
|
||||
if (mesh->mTextureCoords[j]) {
|
||||
uv[j] = out->mTextureCoords[j] = new aiVector3D[out->mNumVertices];
|
||||
@@ -254,70 +236,60 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
|
||||
out->mNumUVComponents[j] = mesh->mNumUVComponents[j];
|
||||
}
|
||||
|
||||
for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_COLOR_SETS;++j) {
|
||||
for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_COLOR_SETS; ++j) {
|
||||
cols[j] = nullptr;
|
||||
if (mesh->mColors[j]) {
|
||||
cols[j] = out->mColors[j] = new aiColor4D[out->mNumVertices];
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::vector< aiVertexWeight > TempBoneInfo;
|
||||
std::vector< TempBoneInfo > tempBones(mesh->mNumBones);
|
||||
typedef std::vector<aiVertexWeight> TempBoneInfo;
|
||||
std::vector<TempBoneInfo> tempBones(mesh->mNumBones);
|
||||
|
||||
// try to guess how much storage we'll need
|
||||
for (unsigned int q = 0; q < mesh->mNumBones;++q)
|
||||
{
|
||||
tempBones[q].reserve(mesh->mBones[q]->mNumWeights / (num-1));
|
||||
for (unsigned int q = 0; q < mesh->mNumBones; ++q) {
|
||||
tempBones[q].reserve(mesh->mBones[q]->mNumWeights / (num - 1));
|
||||
}
|
||||
|
||||
unsigned int outIdx = 0;
|
||||
for (unsigned int m = 0; m < mesh->mNumFaces; ++m)
|
||||
{
|
||||
aiFace& in = mesh->mFaces[m];
|
||||
if ((real == 3 && in.mNumIndices <= 3) || (real != 3 && in.mNumIndices != real+1))
|
||||
{
|
||||
for (unsigned int m = 0; m < mesh->mNumFaces; ++m) {
|
||||
aiFace &in = mesh->mFaces[m];
|
||||
if ((real == 3 && in.mNumIndices <= 3) || (real != 3 && in.mNumIndices != real + 1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
outFaces->mNumIndices = in.mNumIndices;
|
||||
outFaces->mIndices = in.mIndices;
|
||||
outFaces->mIndices = in.mIndices;
|
||||
|
||||
for (unsigned int q = 0; q < in.mNumIndices; ++q)
|
||||
{
|
||||
for (unsigned int q = 0; q < in.mNumIndices; ++q) {
|
||||
unsigned int idx = in.mIndices[q];
|
||||
|
||||
// process all bones of this index
|
||||
if (avw)
|
||||
{
|
||||
VertexWeightTable& tbl = avw[idx];
|
||||
if (avw) {
|
||||
VertexWeightTable &tbl = avw[idx];
|
||||
for (VertexWeightTable::const_iterator it = tbl.begin(), end = tbl.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
tempBones[ (*it).first ].push_back( aiVertexWeight(outIdx, (*it).second) );
|
||||
it != end; ++it) {
|
||||
tempBones[(*it).first].push_back(aiVertexWeight(outIdx, (*it).second));
|
||||
}
|
||||
}
|
||||
|
||||
if (vert)
|
||||
{
|
||||
if (vert) {
|
||||
*vert++ = mesh->mVertices[idx];
|
||||
//mesh->mVertices[idx].x = get_qnan();
|
||||
}
|
||||
if (nor )*nor++ = mesh->mNormals[idx];
|
||||
if (tan )
|
||||
{
|
||||
*tan++ = mesh->mTangents[idx];
|
||||
*bit++ = mesh->mBitangents[idx];
|
||||
if (nor) *nor++ = mesh->mNormals[idx];
|
||||
if (tan) {
|
||||
*tan++ = mesh->mTangents[idx];
|
||||
*bit++ = mesh->mBitangents[idx];
|
||||
}
|
||||
|
||||
for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp)
|
||||
{
|
||||
if (!uv[pp])break;
|
||||
for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp) {
|
||||
if (!uv[pp]) break;
|
||||
*uv[pp]++ = mesh->mTextureCoords[pp][idx];
|
||||
}
|
||||
|
||||
for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp)
|
||||
{
|
||||
if (!cols[pp])break;
|
||||
for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp) {
|
||||
if (!cols[pp]) break;
|
||||
*cols[pp]++ = mesh->mColors[pp][idx];
|
||||
}
|
||||
|
||||
@@ -330,23 +302,22 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
|
||||
ai_assert(outFaces == out->mFaces + out->mNumFaces);
|
||||
|
||||
// now generate output bones
|
||||
for (unsigned int q = 0; q < mesh->mNumBones; ++q) {
|
||||
if (!tempBones[q].empty()) {
|
||||
++out->mNumBones;
|
||||
}
|
||||
}
|
||||
for (unsigned int q = 0; q < mesh->mNumBones; ++q) {
|
||||
if (!tempBones[q].empty()) {
|
||||
++out->mNumBones;
|
||||
}
|
||||
}
|
||||
|
||||
if (out->mNumBones) {
|
||||
out->mBones = new aiBone*[out->mNumBones];
|
||||
for (unsigned int q = 0, boneIdx = 0; q < mesh->mNumBones;++q)
|
||||
{
|
||||
TempBoneInfo& in = tempBones[q];
|
||||
if (in.empty()) {
|
||||
continue;
|
||||
}
|
||||
out->mBones = new aiBone *[out->mNumBones];
|
||||
for (unsigned int q = 0, boneIdx = 0; q < mesh->mNumBones; ++q) {
|
||||
TempBoneInfo &in = tempBones[q];
|
||||
if (in.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
aiBone* srcBone = mesh->mBones[q];
|
||||
aiBone *bone = out->mBones[boneIdx] = new aiBone();
|
||||
aiBone *srcBone = mesh->mBones[q];
|
||||
aiBone *bone = out->mBones[boneIdx] = new aiBone();
|
||||
|
||||
bone->mName = srcBone->mName;
|
||||
bone->mOffsetMatrix = srcBone->mOffsetMatrix;
|
||||
@@ -354,7 +325,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
|
||||
bone->mNumWeights = (unsigned int)in.size();
|
||||
bone->mWeights = new aiVertexWeight[bone->mNumWeights];
|
||||
|
||||
::memcpy(bone->mWeights,&in[0],bone->mNumWeights*sizeof(aiVertexWeight));
|
||||
::memcpy(bone->mWeights, &in[0], bone->mNumWeights * sizeof(aiVertexWeight));
|
||||
|
||||
++boneIdx;
|
||||
}
|
||||
@@ -371,37 +342,32 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
|
||||
pScene->mMeshes[i] = nullptr;
|
||||
}
|
||||
|
||||
if (outMeshes.empty())
|
||||
{
|
||||
if (outMeshes.empty()) {
|
||||
// This should not occur
|
||||
throw DeadlyImportError("No meshes remaining");
|
||||
}
|
||||
|
||||
// If we added at least one mesh process all nodes in the node
|
||||
// graph and update their respective mesh indices.
|
||||
if (bAnyChanges)
|
||||
{
|
||||
UpdateNodes(replaceMeshIndex,pScene->mRootNode);
|
||||
if (bAnyChanges) {
|
||||
UpdateNodes(replaceMeshIndex, pScene->mRootNode);
|
||||
}
|
||||
|
||||
if (outMeshes.size() != pScene->mNumMeshes)
|
||||
{
|
||||
if (outMeshes.size() != pScene->mNumMeshes) {
|
||||
delete[] pScene->mMeshes;
|
||||
pScene->mNumMeshes = (unsigned int)outMeshes.size();
|
||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
||||
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
|
||||
}
|
||||
::memcpy(pScene->mMeshes,&outMeshes[0],pScene->mNumMeshes*sizeof(void*));
|
||||
::memcpy(pScene->mMeshes, &outMeshes[0], pScene->mNumMeshes * sizeof(void *));
|
||||
|
||||
if (!DefaultLogger::isNullLogger())
|
||||
{
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
char buffer[1024];
|
||||
::ai_snprintf(buffer,1024,"Points: %u%s, Lines: %u%s, Triangles: %u%s, Polygons: %u%s (Meshes, X = removed)",
|
||||
aiNumMeshesPerPType[0], ((mConfigRemoveMeshes & aiPrimitiveType_POINT) ? "X" : ""),
|
||||
aiNumMeshesPerPType[1], ((mConfigRemoveMeshes & aiPrimitiveType_LINE) ? "X" : ""),
|
||||
aiNumMeshesPerPType[2], ((mConfigRemoveMeshes & aiPrimitiveType_TRIANGLE) ? "X" : ""),
|
||||
aiNumMeshesPerPType[3], ((mConfigRemoveMeshes & aiPrimitiveType_POLYGON) ? "X" : ""));
|
||||
::ai_snprintf(buffer, 1024, "Points: %u%s, Lines: %u%s, Triangles: %u%s, Polygons: %u%s (Meshes, X = removed)",
|
||||
aiNumMeshesPerPType[0], ((mConfigRemoveMeshes & aiPrimitiveType_POINT) ? "X" : ""),
|
||||
aiNumMeshesPerPType[1], ((mConfigRemoveMeshes & aiPrimitiveType_LINE) ? "X" : ""),
|
||||
aiNumMeshesPerPType[2], ((mConfigRemoveMeshes & aiPrimitiveType_TRIANGLE) ? "X" : ""),
|
||||
aiNumMeshesPerPType[3], ((mConfigRemoveMeshes & aiPrimitiveType_POLYGON) ? "X" : ""));
|
||||
ASSIMP_LOG_INFO(buffer);
|
||||
ASSIMP_LOG_DEBUG("SortByPTypeProcess finished");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <limits>
|
||||
#include <assimp/TinyFormatter.h>
|
||||
#include <assimp/Exceptional.h>
|
||||
#include <set>
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Formatter;
|
||||
@@ -172,7 +173,15 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
|
||||
const aiBone* bone = pMesh->mBones[a];
|
||||
for( unsigned int b = 0; b < bone->mNumWeights; ++b)
|
||||
{
|
||||
vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight));
|
||||
if (bone->mWeights[b].mWeight > 0.0f)
|
||||
{
|
||||
int vertexId = bone->mWeights[b].mVertexId;
|
||||
vertexBones[vertexId].push_back( BoneWeight( a, bone->mWeights[b].mWeight));
|
||||
if (vertexBones[vertexId].size() > mMaxBoneCount)
|
||||
{
|
||||
throw DeadlyImportError("SplitByBoneCountProcess: Single face requires more bones than specified max bone count!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,9 +197,6 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
|
||||
subMeshFaces.reserve( pMesh->mNumFaces);
|
||||
// accumulated vertex count of all the faces in this submesh
|
||||
unsigned int numSubMeshVertices = 0;
|
||||
// a small local array of new bones for the current face. State of all used bones for that face
|
||||
// can only be updated AFTER the face is completely analysed. Thanks to imre for the fix.
|
||||
std::vector<unsigned int> newBonesAtCurrentFace;
|
||||
|
||||
// add faces to the new submesh as long as all bones affecting the faces' vertices fit in the limit
|
||||
for( unsigned int a = 0; a < pMesh->mNumFaces; ++a)
|
||||
@@ -200,33 +206,25 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// a small local set of new bones for the current face. State of all used bones for that face
|
||||
// can only be updated AFTER the face is completely analysed. Thanks to imre for the fix.
|
||||
std::set<unsigned int> newBonesAtCurrentFace;
|
||||
|
||||
const aiFace& face = pMesh->mFaces[a];
|
||||
// check every vertex if its bones would still fit into the current submesh
|
||||
for( unsigned int b = 0; b < face.mNumIndices; ++b )
|
||||
{
|
||||
const std::vector<BoneWeight>& vb = vertexBones[face.mIndices[b]];
|
||||
for( unsigned int c = 0; c < vb.size(); ++c)
|
||||
const std::vector<BoneWeight>& vb = vertexBones[face.mIndices[b]];
|
||||
for( unsigned int c = 0; c < vb.size(); ++c)
|
||||
{
|
||||
unsigned int boneIndex = vb[c].first;
|
||||
if( !isBoneUsed[boneIndex] )
|
||||
{
|
||||
unsigned int boneIndex = vb[c].first;
|
||||
// if the bone is already used in this submesh, it's ok
|
||||
if( isBoneUsed[boneIndex] )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if it's not used, yet, we would need to add it. Store its bone index
|
||||
if( std::find( newBonesAtCurrentFace.begin(), newBonesAtCurrentFace.end(), boneIndex) == newBonesAtCurrentFace.end() )
|
||||
{
|
||||
newBonesAtCurrentFace.push_back( boneIndex);
|
||||
}
|
||||
}
|
||||
newBonesAtCurrentFace.insert(boneIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newBonesAtCurrentFace.size() > mMaxBoneCount)
|
||||
{
|
||||
throw DeadlyImportError("SplitByBoneCountProcess: Single face requires more bones than specified max bone count!");
|
||||
}
|
||||
// leave out the face if the new bones required for this face don't fit the bone count limit anymore
|
||||
if( numBones + newBonesAtCurrentFace.size() > mMaxBoneCount )
|
||||
{
|
||||
@@ -234,17 +232,13 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
|
||||
}
|
||||
|
||||
// mark all new bones as necessary
|
||||
while( !newBonesAtCurrentFace.empty() )
|
||||
for (std::set<unsigned int>::iterator it = newBonesAtCurrentFace.begin(); it != newBonesAtCurrentFace.end(); ++it)
|
||||
{
|
||||
unsigned int newIndex = newBonesAtCurrentFace.back();
|
||||
newBonesAtCurrentFace.pop_back(); // this also avoids the deallocation which comes with a clear()
|
||||
if( isBoneUsed[newIndex] )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
isBoneUsed[newIndex] = true;
|
||||
if (!isBoneUsed[*it])
|
||||
{
|
||||
isBoneUsed[*it] = true;
|
||||
numBones++;
|
||||
}
|
||||
}
|
||||
|
||||
// store the face index and the vertex count
|
||||
|
||||
@@ -508,7 +508,7 @@ void TextureTransformStep::Execute( aiScene* pScene)
|
||||
aiVector3D* dest, *end;
|
||||
dest = mesh->mTextureCoords[n];
|
||||
|
||||
ai_assert(NULL != src);
|
||||
ai_assert(nullptr != src);
|
||||
|
||||
// Copy the data to the destination array
|
||||
if (dest != src)
|
||||
|
||||
@@ -161,7 +161,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||
// Just another check whether aiMesh::mPrimitiveTypes is correct
|
||||
ai_assert(numOut != pMesh->mNumFaces);
|
||||
|
||||
aiVector3D* nor_out = NULL;
|
||||
aiVector3D *nor_out = nullptr;
|
||||
|
||||
// if we don't have normals yet, but expect them to be a cheap side
|
||||
// product of triangulation anyway, allocate storage for them.
|
||||
@@ -220,7 +220,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||
nface.mNumIndices = face.mNumIndices;
|
||||
nface.mIndices = face.mIndices;
|
||||
|
||||
face.mIndices = NULL;
|
||||
face.mIndices = nullptr;
|
||||
continue;
|
||||
}
|
||||
// optimized code for quadrilaterals
|
||||
@@ -272,7 +272,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||
sface.mIndices[2] = temp[(start_vertex + 3) % 4];
|
||||
|
||||
// prevent double deletion of the indices field
|
||||
face.mIndices = NULL;
|
||||
face.mIndices = nullptr;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
@@ -490,7 +490,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||
// drop dumb 0-area triangles - deactivated for now:
|
||||
//FindDegenerates post processing step can do the same thing
|
||||
//if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) {
|
||||
// ASSIMP_LOG_DEBUG("Dropping triangle with area 0");
|
||||
// ASSIMP_LOG_VERBOSE_DEBUG("Dropping triangle with area 0");
|
||||
// --curOut;
|
||||
|
||||
// delete[] f->mIndices;
|
||||
@@ -511,7 +511,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||
}
|
||||
|
||||
delete[] face.mIndices;
|
||||
face.mIndices = NULL;
|
||||
face.mIndices = nullptr;
|
||||
}
|
||||
|
||||
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user