* Adjustment: Update Assimp version to 5.0.1.

This commit is contained in:
Robert MacGregor 2021-10-21 21:14:55 -04:00
parent 14ebeaf3eb
commit 4758f7bdaf
679 changed files with 50502 additions and 19698 deletions

View file

@ -1,262 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#include "ArmaturePopulate.h"
#include <assimp/BaseImporter.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include <iostream>
namespace Assimp {
/// The default class constructor.
ArmaturePopulate::ArmaturePopulate() :
BaseProcess() {
// do nothing
}
/// The class destructor.
ArmaturePopulate::~ArmaturePopulate() {
// do nothing
}
bool ArmaturePopulate::IsActive(unsigned int pFlags) const {
return (pFlags & aiProcess_PopulateArmatureData) != 0;
}
void ArmaturePopulate::SetupProperties(const Importer *pImp) {
// do nothing
}
void ArmaturePopulate::Execute(aiScene *out) {
// Now convert all bone positions to the correct mOffsetMatrix
std::vector<aiBone *> bones;
std::vector<aiNode *> nodes;
std::map<aiBone *, aiNode *> bone_stack;
BuildBoneList(out->mRootNode, out->mRootNode, out, bones);
BuildNodeList(out->mRootNode, nodes);
BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes);
ASSIMP_LOG_DEBUG_F("Bone stack size: ", bone_stack.size());
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());
// lcl transform grab - done in generate_nodes :)
// bone->mOffsetMatrix = bone_node->mTransformation;
aiNode *armature = GetArmatureRoot(bone_node, bones);
ai_assert(armature);
// set up bone armature id
bone->mArmature = armature;
// set this bone node to be referenced properly
ai_assert(bone_node);
bone->mNode = bone_node;
}
}
// Reprocess all nodes to calculate bone transforms properly based on the REAL
// mOffsetMatrix not the local.
// Before this would use mesh transforms which is wrong for bone transforms
// Before this would work for simple character skeletons but not complex meshes
// with multiple origins
// Source: sketch fab log cutter fbx
void ArmaturePopulate::BuildBoneList(aiNode *current_node,
const aiNode *root_node,
const aiScene *scene,
std::vector<aiBone *> &bones) {
ai_assert(scene);
for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) {
aiNode *child = current_node->mChildren[nodeId];
ai_assert(child);
// check for bones
for (unsigned int meshId = 0; meshId < child->mNumMeshes; ++meshId) {
ai_assert(child->mMeshes);
unsigned int mesh_index = child->mMeshes[meshId];
aiMesh *mesh = scene->mMeshes[mesh_index];
ai_assert(mesh);
for (unsigned int boneId = 0; boneId < mesh->mNumBones; ++boneId) {
aiBone *bone = mesh->mBones[boneId];
ai_assert(bone);
// duplicate mehes exist with the same bones sometimes :)
// so this must be detected
if (std::find(bones.begin(), bones.end(), bone) == bones.end()) {
// add the element once
bones.push_back(bone);
}
}
// find mesh and get bones
// then do recursive lookup for bones in root node hierarchy
}
BuildBoneList(child, root_node, scene, bones);
}
}
// Prepare flat node list which can be used for non recursive lookups later
void ArmaturePopulate::BuildNodeList(const aiNode *current_node,
std::vector<aiNode *> &nodes) {
ai_assert(current_node);
for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) {
aiNode *child = current_node->mChildren[nodeId];
ai_assert(child);
if (child->mNumMeshes == 0) {
nodes.push_back(child);
}
BuildNodeList(child, nodes);
}
}
// A bone stack allows us to have multiple armatures, with the same bone names
// A bone stack allows us also to retrieve bones true transform even with
// duplicate names :)
void ArmaturePopulate::BuildBoneStack(aiNode *current_node,
const aiNode *root_node,
const aiScene *scene,
const std::vector<aiBone *> &bones,
std::map<aiBone *, aiNode *> &bone_stack,
std::vector<aiNode *> &node_stack) {
ai_assert(scene);
ai_assert(root_node);
ai_assert(!node_stack.empty());
for (aiBone *bone : bones) {
ai_assert(bone);
aiNode *node = GetNodeFromStack(bone->mName, node_stack);
if (node == nullptr) {
node_stack.clear();
BuildNodeList(root_node, node_stack);
ASSIMP_LOG_DEBUG_F("Resetting bone stack: nullptr element ", bone->mName.C_Str());
node = GetNodeFromStack(bone->mName, node_stack);
if (!node) {
ASSIMP_LOG_ERROR("serious import issue node for bone was not detected");
continue;
}
}
ASSIMP_LOG_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));
}
}
// Returns the armature root node
// This is required to be detected for a bone initially, it will recurse up
// until it cannot find another bone and return the node No known failure
// points. (yet)
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());
return bone_node;
}
bone_node = bone_node->mParent;
}
ASSIMP_LOG_ERROR("GetArmatureRoot() can't find armature!");
return nullptr;
}
// Simple IsBoneNode check if this could be a bone
bool ArmaturePopulate::IsBoneNode(const aiString &bone_name,
std::vector<aiBone *> &bones) {
for (aiBone *bone : bones) {
if (bone->mName == bone_name) {
return true;
}
}
return false;
}
// Pop this node by name from the stack if found
// Used in multiple armature situations with duplicate node / bone names
// Known flaw: cannot have nodes with bone names, will be fixed in later release
// (serious to be fixed) Known flaw: nodes which have more than one bone could
// be prematurely dropped from stack
aiNode *ArmaturePopulate::GetNodeFromStack(const aiString &node_name,
std::vector<aiNode *> &nodes) {
std::vector<aiNode *>::iterator iter;
aiNode *found = nullptr;
for (iter = nodes.begin(); iter < nodes.end(); ++iter) {
aiNode *element = *iter;
ai_assert(element);
// node valid and node name matches
if (element->mName == node_name) {
found = element;
break;
}
}
if (found != nullptr) {
ASSIMP_LOG_INFO_F("Removed node from stack: ", found->mName.C_Str());
// now pop the element from the node list
nodes.erase(iter);
return found;
}
// unique names can cause this problem
ASSIMP_LOG_ERROR("[Serious] GetNodeFromStack() can't find node from stack!");
return nullptr;
}
} // Namespace Assimp

View file

@ -1,112 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef ARMATURE_POPULATE_H_
#define ARMATURE_POPULATE_H_
#include "Common/BaseProcess.h"
#include <assimp/BaseImporter.h>
#include <vector>
#include <map>
struct aiNode;
struct aiBone;
namespace Assimp {
// ---------------------------------------------------------------------------
/** Armature Populate: This is a post process designed
* To save you time when importing models into your game engines
* This was originally designed only for fbx but will work with other formats
* it is intended to auto populate aiBone data with armature and the aiNode
* This is very useful when dealing with skinned meshes
* or when dealing with many different skeletons
* It's off by default but recommend that you try it and use it
* It should reduce down any glue code you have in your
* importers
* You can contact RevoluPowered <gordon@gordonite.tech>
* For more info about this
*/
class ASSIMP_API ArmaturePopulate : public BaseProcess {
public:
/// The default class constructor.
ArmaturePopulate();
/// The class destructor.
virtual ~ArmaturePopulate();
/// Overwritten, @see BaseProcess
virtual bool IsActive( unsigned int pFlags ) const;
/// Overwritten, @see BaseProcess
virtual void SetupProperties( const Importer* pImp );
/// Overwritten, @see BaseProcess
virtual void Execute( aiScene* pScene );
static aiNode *GetArmatureRoot(aiNode *bone_node,
std::vector<aiBone *> &bone_list);
static bool IsBoneNode(const aiString &bone_name,
std::vector<aiBone *> &bones);
static aiNode *GetNodeFromStack(const aiString &node_name,
std::vector<aiNode *> &nodes);
static void BuildNodeList(const aiNode *current_node,
std::vector<aiNode *> &nodes);
static void BuildBoneList(aiNode *current_node, const aiNode *root_node,
const aiScene *scene,
std::vector<aiBone *> &bones);
static void BuildBoneStack(aiNode *current_node, const aiNode *root_node,
const aiScene *scene,
const std::vector<aiBone *> &bones,
std::map<aiBone *, aiNode *> &bone_stack,
std::vector<aiNode *> &node_stack);
};
} // Namespace Assimp
#endif // SCALE_PROCESS_H_

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.
@ -137,9 +137,8 @@ public:
// -------------------------------------------------------------------
void Execute( aiScene* pScene);
public:
/** Some other types of post-processing require winding order flips */
static void ProcessMesh( aiMesh* pMesh);
protected:
void ProcessMesh( aiMesh* pMesh);
};
// ---------------------------------------------------------------------------

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.
@ -128,8 +128,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
auto oldTextures = pScene->mTextures;
pScene->mTextures = new aiTexture*[pScene->mNumTextures];
::memmove(pScene->mTextures, oldTextures, sizeof(aiTexture*) * (pScene->mNumTextures - 1u));
delete [] oldTextures;
// Add the new texture
auto pTexture = new aiTexture;
pTexture->mHeight = 0; // Means that this is still compressed

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FindInvalidDataProcess.h"
#include "ProcessHelper.h"
#include <assimp/Macros.h>
#include <assimp/Exceptional.h>
#include <assimp/qnan.h>

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.
@ -43,13 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the aiProcess_OptimizGraph step
*/
#ifndef ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS
#include "OptimizeGraph.h"
#include "ProcessHelper.h"
#include "ConvertToLHProcess.h"
#include <assimp/Exceptional.h>
#include <assimp/SceneCombiner.h>
#include <assimp/Exceptional.h>
#include <stdio.h>
using namespace Assimp;
@ -60,299 +60,292 @@ using namespace Assimp;
* The unhashed variant should be faster, except for *very* large data sets
*/
#ifdef AI_OG_USE_HASHING
// Use our standard hashing function to compute the hash
#define AI_OG_GETKEY(str) SuperFastHash(str.data, str.length)
// Use our standard hashing function to compute the hash
# define AI_OG_GETKEY(str) SuperFastHash(str.data,str.length)
#else
// Otherwise hope that std::string will utilize a static buffer
// for shorter node names. This would avoid endless heap copying.
#define AI_OG_GETKEY(str) std::string(str.data)
// Otherwise hope that std::string will utilize a static buffer
// for shorter node names. This would avoid endless heap copying.
# define AI_OG_GETKEY(str) std::string(str.data)
#endif
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
OptimizeGraphProcess::OptimizeGraphProcess() :
mScene(),
nodes_in(),
nodes_out(),
count_merged() {
// empty
OptimizeGraphProcess::OptimizeGraphProcess()
: mScene()
, nodes_in()
, nodes_out()
, count_merged() {
// empty
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
OptimizeGraphProcess::~OptimizeGraphProcess() {
// empty
// empty
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool OptimizeGraphProcess::IsActive(unsigned int pFlags) const {
return (0 != (pFlags & aiProcess_OptimizeGraph));
bool OptimizeGraphProcess::IsActive( unsigned int pFlags) const {
return (0 != (pFlags & aiProcess_OptimizeGraph));
}
// ------------------------------------------------------------------------------------------------
// Setup properties for the post-processing step
void OptimizeGraphProcess::SetupProperties(const Importer *pImp) {
// Get value of AI_CONFIG_PP_OG_EXCLUDE_LIST
std::string tmp = pImp->GetPropertyString(AI_CONFIG_PP_OG_EXCLUDE_LIST, "");
AddLockedNodeList(tmp);
void OptimizeGraphProcess::SetupProperties(const Importer* pImp) {
// Get value of AI_CONFIG_PP_OG_EXCLUDE_LIST
std::string tmp = pImp->GetPropertyString(AI_CONFIG_PP_OG_EXCLUDE_LIST,"");
AddLockedNodeList(tmp);
}
// ------------------------------------------------------------------------------------------------
// Collect new children
void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list<aiNode *> &nodes) {
nodes_in += nd->mNumChildren;
void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list<aiNode*>& nodes) {
nodes_in += nd->mNumChildren;
// Process children
std::list<aiNode *> child_nodes;
for (unsigned int i = 0; i < nd->mNumChildren; ++i) {
CollectNewChildren(nd->mChildren[i], child_nodes);
nd->mChildren[i] = nullptr;
}
// Process children
std::list<aiNode*> child_nodes;
for (unsigned int i = 0; i < nd->mNumChildren; ++i) {
CollectNewChildren(nd->mChildren[i],child_nodes);
nd->mChildren[i] = nullptr;
}
// Check whether we need this node; if not we can replace it by our own children (warn, danger of incest).
if (locked.find(AI_OG_GETKEY(nd->mName)) == locked.end()) {
for (std::list<aiNode *>::iterator it = child_nodes.begin(); it != child_nodes.end();) {
// Check whether we need this node; if not we can replace it by our own children (warn, danger of incest).
if (locked.find(AI_OG_GETKEY(nd->mName)) == locked.end() ) {
for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end();) {
if (locked.find(AI_OG_GETKEY((*it)->mName)) == locked.end()) {
(*it)->mTransformation = nd->mTransformation * (*it)->mTransformation;
nodes.push_back(*it);
if (locked.find(AI_OG_GETKEY((*it)->mName)) == locked.end()) {
(*it)->mTransformation = nd->mTransformation * (*it)->mTransformation;
nodes.push_back(*it);
it = child_nodes.erase(it);
continue;
}
++it;
}
it = child_nodes.erase(it);
continue;
}
++it;
}
if (nd->mNumMeshes || !child_nodes.empty()) {
nodes.push_back(nd);
} else {
delete nd; /* bye, node */
return;
}
} else {
if (nd->mNumMeshes || !child_nodes.empty()) {
nodes.push_back(nd);
} else {
delete nd; /* bye, node */
return;
}
} else {
// Retain our current position in the hierarchy
nodes.push_back(nd);
// Retain our current position in the hierarchy
nodes.push_back(nd);
// Now check for possible optimizations in our list of child nodes. join as many as possible
aiNode *join_master = nullptr;
aiMatrix4x4 inv;
// Now check for possible optimizations in our list of child nodes. join as many as possible
aiNode* join_master = NULL;
aiMatrix4x4 inv;
const LockedSetType::const_iterator end = locked.end();
const LockedSetType::const_iterator end = locked.end();
std::list<aiNode *> join;
for (std::list<aiNode *>::iterator it = child_nodes.begin(); it != child_nodes.end();) {
aiNode *child = *it;
if (child->mNumChildren == 0 && locked.find(AI_OG_GETKEY(child->mName)) == end) {
std::list<aiNode*> join;
for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end();) {
aiNode* child = *it;
if (child->mNumChildren == 0 && locked.find(AI_OG_GETKEY(child->mName)) == end) {
// There may be no instanced meshes
unsigned int n = 0;
for (; n < child->mNumMeshes; ++n) {
if (meshes[child->mMeshes[n]] > 1) {
break;
}
}
if (n == child->mNumMeshes) {
if (!join_master) {
join_master = child;
inv = join_master->mTransformation;
inv.Inverse();
} else {
child->mTransformation = inv * child->mTransformation;
// There may be no instanced meshes
unsigned int n = 0;
for (; n < child->mNumMeshes;++n) {
if (meshes[child->mMeshes[n]] > 1) {
break;
}
}
if (n == child->mNumMeshes) {
if (!join_master) {
join_master = child;
inv = join_master->mTransformation;
inv.Inverse();
} else {
child->mTransformation = inv * child->mTransformation ;
join.push_back(child);
it = child_nodes.erase(it);
continue;
}
}
}
++it;
}
if (join_master && !join.empty()) {
join_master->mName.length = ::ai_snprintf(join_master->mName.data, MAXLEN, "$MergedNode_%i", count_merged++);
join.push_back(child);
it = child_nodes.erase(it);
continue;
}
}
}
++it;
}
if (join_master && !join.empty()) {
join_master->mName.length = ::ai_snprintf(join_master->mName.data, MAXLEN, "$MergedNode_%i",count_merged++);
unsigned int out_meshes = 0;
for (std::list<aiNode *>::const_iterator it = join.cbegin(); it != join.cend(); ++it) {
out_meshes += (*it)->mNumMeshes;
}
unsigned int out_meshes = 0;
for (std::list<aiNode*>::iterator it = join.begin(); it != join.end(); ++it) {
out_meshes += (*it)->mNumMeshes;
}
// copy all mesh references in one array
if (out_meshes) {
unsigned int *meshes = new unsigned int[out_meshes + join_master->mNumMeshes], *tmp = meshes;
for (unsigned int n = 0; n < join_master->mNumMeshes; ++n) {
*tmp++ = join_master->mMeshes[n];
}
// copy all mesh references in one array
if (out_meshes) {
unsigned int* meshes = new unsigned int[out_meshes+join_master->mNumMeshes], *tmp = meshes;
for (unsigned int n = 0; n < join_master->mNumMeshes;++n) {
*tmp++ = join_master->mMeshes[n];
}
for (const aiNode *join_node : join) {
for (unsigned int n = 0; n < join_node->mNumMeshes; ++n) {
for (std::list<aiNode*>::iterator it = join.begin(); it != join.end(); ++it) {
for (unsigned int n = 0; n < (*it)->mNumMeshes; ++n) {
*tmp = join_node->mMeshes[n];
aiMesh *mesh = mScene->mMeshes[*tmp++];
*tmp = (*it)->mMeshes[n];
aiMesh* mesh = mScene->mMeshes[*tmp++];
// Assume the transformation is affine
// manually move the mesh into the right coordinate system
// manually move the mesh into the right coordinate system
const aiMatrix3x3 IT = aiMatrix3x3( (*it)->mTransformation ).Inverse().Transpose();
for (unsigned int a = 0; a < mesh->mNumVertices; ++a) {
// Check for odd negative scale (mirror)
if (join_node->mTransformation.Determinant() < 0) {
// Reverse the mesh face winding order
FlipWindingOrderProcess::ProcessMesh(mesh);
}
mesh->mVertices[a] *= (*it)->mTransformation;
// Update positions, normals and tangents
const aiMatrix3x3 IT = aiMatrix3x3(join_node->mTransformation).Inverse().Transpose();
for (unsigned int a = 0; a < mesh->mNumVertices; ++a) {
if (mesh->HasNormals())
mesh->mNormals[a] *= IT;
mesh->mVertices[a] *= join_node->mTransformation;
if (mesh->HasTangentsAndBitangents()) {
mesh->mTangents[a] *= IT;
mesh->mBitangents[a] *= IT;
}
}
}
delete *it; // bye, node
}
delete[] join_master->mMeshes;
join_master->mMeshes = meshes;
join_master->mNumMeshes += out_meshes;
}
}
}
// reassign children if something changed
if (child_nodes.empty() || child_nodes.size() > nd->mNumChildren) {
if (mesh->HasNormals())
mesh->mNormals[a] *= IT;
delete[] nd->mChildren;
if (mesh->HasTangentsAndBitangents()) {
mesh->mTangents[a] *= IT;
mesh->mBitangents[a] *= IT;
}
}
}
delete join_node; // bye, node
}
delete[] join_master->mMeshes;
join_master->mMeshes = meshes;
join_master->mNumMeshes += out_meshes;
}
}
}
// reassign children if something changed
if (child_nodes.empty() || child_nodes.size() > nd->mNumChildren) {
if (!child_nodes.empty()) {
nd->mChildren = new aiNode*[child_nodes.size()];
}
else nd->mChildren = nullptr;
}
delete[] nd->mChildren;
nd->mNumChildren = static_cast<unsigned int>(child_nodes.size());
if (!child_nodes.empty()) {
nd->mChildren = new aiNode *[child_nodes.size()];
} else
nd->mChildren = nullptr;
}
if (nd->mChildren) {
aiNode** tmp = nd->mChildren;
for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end(); ++it) {
aiNode* node = *tmp++ = *it;
node->mParent = nd;
}
}
nd->mNumChildren = static_cast<unsigned int>(child_nodes.size());
if (nd->mChildren) {
aiNode **tmp = nd->mChildren;
for (std::list<aiNode *>::iterator it = child_nodes.begin(); it != child_nodes.end(); ++it) {
aiNode *node = *tmp++ = *it;
node->mParent = nd;
}
}
nodes_out += static_cast<unsigned int>(child_nodes.size());
nodes_out += static_cast<unsigned int>(child_nodes.size());
}
// ------------------------------------------------------------------------------------------------
// Execute the post-processing step on the given scene
void OptimizeGraphProcess::Execute(aiScene *pScene) {
ASSIMP_LOG_DEBUG("OptimizeGraphProcess begin");
nodes_in = nodes_out = count_merged = 0;
mScene = pScene;
void OptimizeGraphProcess::Execute( aiScene* pScene) {
ASSIMP_LOG_DEBUG("OptimizeGraphProcess begin");
nodes_in = nodes_out = count_merged = 0;
mScene = pScene;
meshes.resize(pScene->mNumMeshes, 0);
FindInstancedMeshes(pScene->mRootNode);
meshes.resize(pScene->mNumMeshes,0);
FindInstancedMeshes(pScene->mRootNode);
// build a blacklist of identifiers. If the name of a node matches one of these, we won't touch it
locked.clear();
for (std::list<std::string>::const_iterator it = locked_nodes.begin(); it != locked_nodes.end(); ++it) {
// build a blacklist of identifiers. If the name of a node matches one of these, we won't touch it
locked.clear();
for (std::list<std::string>::const_iterator it = locked_nodes.begin(); it != locked_nodes.end(); ++it) {
#ifdef AI_OG_USE_HASHING
locked.insert(SuperFastHash((*it).c_str()));
locked.insert(SuperFastHash((*it).c_str()));
#else
locked.insert(*it);
locked.insert(*it);
#endif
}
}
for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) {
for (unsigned int a = 0; a < pScene->mAnimations[i]->mNumChannels; ++a) {
aiNodeAnim *anim = pScene->mAnimations[i]->mChannels[a];
locked.insert(AI_OG_GETKEY(anim->mNodeName));
}
}
for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) {
for (unsigned int a = 0; a < pScene->mAnimations[i]->mNumChannels; ++a) {
aiNodeAnim* anim = pScene->mAnimations[i]->mChannels[a];
locked.insert(AI_OG_GETKEY(anim->mNodeName));
}
}
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
for (unsigned int a = 0; a < pScene->mMeshes[i]->mNumBones; ++a) {
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
for (unsigned int a = 0; a < pScene->mMeshes[i]->mNumBones; ++a) {
aiBone *bone = pScene->mMeshes[i]->mBones[a];
locked.insert(AI_OG_GETKEY(bone->mName));
aiBone* bone = pScene->mMeshes[i]->mBones[a];
locked.insert(AI_OG_GETKEY(bone->mName));
// HACK: Meshes referencing bones may not be transformed; we need to look them.
// The easiest way to do this is to increase their reference counters ...
meshes[i] += 2;
}
}
// HACK: Meshes referencing bones may not be transformed; we need to look them.
// The easiest way to do this is to increase their reference counters ...
meshes[i] += 2;
}
}
for (unsigned int i = 0; i < pScene->mNumCameras; ++i) {
aiCamera *cam = pScene->mCameras[i];
locked.insert(AI_OG_GETKEY(cam->mName));
}
for (unsigned int i = 0; i < pScene->mNumCameras; ++i) {
aiCamera* cam = pScene->mCameras[i];
locked.insert(AI_OG_GETKEY(cam->mName));
}
for (unsigned int i = 0; i < pScene->mNumLights; ++i) {
aiLight *lgh = pScene->mLights[i];
locked.insert(AI_OG_GETKEY(lgh->mName));
}
for (unsigned int i = 0; i < pScene->mNumLights; ++i) {
aiLight* lgh = pScene->mLights[i];
locked.insert(AI_OG_GETKEY(lgh->mName));
}
// Insert a dummy master node and make it read-only
aiNode *dummy_root = new aiNode(AI_RESERVED_NODE_NAME);
locked.insert(AI_OG_GETKEY(dummy_root->mName));
// Insert a dummy master node and make it read-only
aiNode* dummy_root = new aiNode(AI_RESERVED_NODE_NAME);
locked.insert(AI_OG_GETKEY(dummy_root->mName));
const aiString prev = pScene->mRootNode->mName;
pScene->mRootNode->mParent = dummy_root;
const aiString prev = pScene->mRootNode->mName;
pScene->mRootNode->mParent = dummy_root;
dummy_root->mChildren = new aiNode *[dummy_root->mNumChildren = 1];
dummy_root->mChildren[0] = pScene->mRootNode;
dummy_root->mChildren = new aiNode*[dummy_root->mNumChildren = 1];
dummy_root->mChildren[0] = pScene->mRootNode;
// Do our recursive processing of scenegraph nodes. For each node collect
// a fully new list of children and allow their children to place themselves
// on the same hierarchy layer as their parents.
std::list<aiNode *> nodes;
CollectNewChildren(dummy_root, nodes);
// Do our recursive processing of scenegraph nodes. For each node collect
// a fully new list of children and allow their children to place themselves
// on the same hierarchy layer as their parents.
std::list<aiNode*> nodes;
CollectNewChildren (dummy_root,nodes);
ai_assert(nodes.size() == 1);
ai_assert(nodes.size() == 1);
if (dummy_root->mNumChildren == 0) {
pScene->mRootNode = nullptr;
throw DeadlyImportError("After optimizing the scene graph, no data remains");
}
if (dummy_root->mNumChildren == 0) {
pScene->mRootNode = NULL;
throw DeadlyImportError("After optimizing the scene graph, no data remains");
}
if (dummy_root->mNumChildren > 1) {
pScene->mRootNode = dummy_root;
if (dummy_root->mNumChildren > 1) {
pScene->mRootNode = dummy_root;
// Keep the dummy node but assign the name of the old root node to it
pScene->mRootNode->mName = prev;
} else {
// Keep the dummy node but assign the name of the old root node to it
pScene->mRootNode->mName = prev;
}
else {
// Remove the dummy root node again.
pScene->mRootNode = dummy_root->mChildren[0];
// Remove the dummy root node again.
pScene->mRootNode = dummy_root->mChildren[0];
dummy_root->mChildren[0] = nullptr;
delete dummy_root;
}
dummy_root->mChildren[0] = NULL;
delete dummy_root;
}
pScene->mRootNode->mParent = nullptr;
if (!DefaultLogger::isNullLogger()) {
if (nodes_in != nodes_out) {
ASSIMP_LOG_INFO_F("OptimizeGraphProcess finished; Input nodes: ", nodes_in, ", Output nodes: ", nodes_out);
} else {
ASSIMP_LOG_DEBUG("OptimizeGraphProcess finished");
}
}
meshes.clear();
locked.clear();
pScene->mRootNode->mParent = NULL;
if (!DefaultLogger::isNullLogger()) {
if ( nodes_in != nodes_out) {
ASSIMP_LOG_INFO_F("OptimizeGraphProcess finished; Input nodes: ", nodes_in, ", Output nodes: ", nodes_out);
} else {
ASSIMP_LOG_DEBUG("OptimizeGraphProcess finished");
}
}
meshes.clear();
locked.clear();
}
// ------------------------------------------------------------------------------------------------
// Build a LUT of all instanced meshes
void OptimizeGraphProcess::FindInstancedMeshes(aiNode *pNode) {
for (unsigned int i = 0; i < pNode->mNumMeshes; ++i) {
++meshes[pNode->mMeshes[i]];
}
void OptimizeGraphProcess::FindInstancedMeshes (aiNode* pNode)
{
for (unsigned int i = 0; i < pNode->mNumMeshes;++i) {
++meshes[pNode->mMeshes[i]];
}
for (unsigned int i = 0; i < pNode->mNumChildren; ++i)
FindInstancedMeshes(pNode->mChildren[i]);
for (unsigned int i = 0; i < pNode->mNumChildren; ++i)
FindInstancedMeshes(pNode->mChildren[i]);
}
#endif // !! ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.
@ -75,13 +75,13 @@ public:
~OptimizeGraphProcess();
// -------------------------------------------------------------------
bool IsActive( unsigned int pFlags) const override;
bool IsActive( unsigned int pFlags) const;
// -------------------------------------------------------------------
void Execute( aiScene* pScene) override;
void Execute( aiScene* pScene);
// -------------------------------------------------------------------
void SetupProperties(const Importer* pImp) override;
void SetupProperties(const Importer* pImp);
// -------------------------------------------------------------------
/** @brief Add a list of node names to be locked and not modified.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.
@ -59,7 +59,7 @@ struct aiNode;
class PretransformVerticesTest;
namespace Assimp {
namespace Assimp {
// ---------------------------------------------------------------------------
/** The PretransformVertices pre-transforms all vertices in the node tree
@ -68,97 +68,97 @@ namespace Assimp {
*/
class ASSIMP_API PretransformVertices : public BaseProcess {
public:
PretransformVertices();
~PretransformVertices();
PretransformVertices ();
~PretransformVertices ();
// -------------------------------------------------------------------
// Check whether step is active
bool IsActive(unsigned int pFlags) const override;
// -------------------------------------------------------------------
// Check whether step is active
bool IsActive( unsigned int pFlags) const;
// -------------------------------------------------------------------
// Execute step on a given scene
void Execute(aiScene *pScene) override;
// -------------------------------------------------------------------
// Execute step on a given scene
void Execute( aiScene* pScene);
// -------------------------------------------------------------------
// Setup import settings
void SetupProperties(const Importer *pImp) override;
// -------------------------------------------------------------------
// Setup import settings
void SetupProperties(const Importer* pImp);
// -------------------------------------------------------------------
/** @brief Toggle the 'keep hierarchy' option
// -------------------------------------------------------------------
/** @brief Toggle the 'keep hierarchy' option
* @param keep true for keep configuration.
*/
void KeepHierarchy(bool keep) {
configKeepHierarchy = keep;
}
void KeepHierarchy(bool keep) {
configKeepHierarchy = keep;
}
// -------------------------------------------------------------------
/** @brief Check whether 'keep hierarchy' is currently enabled.
// -------------------------------------------------------------------
/** @brief Check whether 'keep hierarchy' is currently enabled.
* @return ...
*/
bool IsHierarchyKept() const {
return configKeepHierarchy;
}
bool IsHierarchyKept() const {
return configKeepHierarchy;
}
private:
// -------------------------------------------------------------------
// Count the number of nodes
unsigned int CountNodes(const aiNode *pcNode) const;
// -------------------------------------------------------------------
// Count the number of nodes
unsigned int CountNodes( aiNode* pcNode );
// -------------------------------------------------------------------
// Get a bitwise combination identifying the vertex format of a mesh
unsigned int GetMeshVFormat(aiMesh *pcMesh) const;
// -------------------------------------------------------------------
// Get a bitwise combination identifying the vertex format of a mesh
unsigned int GetMeshVFormat(aiMesh* pcMesh);
// -------------------------------------------------------------------
// Count the number of vertices in the whole scene and a given
// material index
void CountVerticesAndFaces(const aiScene *pcScene, const aiNode *pcNode,
unsigned int iMat,
unsigned int iVFormat,
unsigned int *piFaces,
unsigned int *piVertices) const;
// -------------------------------------------------------------------
// Count the number of vertices in the whole scene and a given
// material index
void CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode,
unsigned int iMat,
unsigned int iVFormat,
unsigned int* piFaces,
unsigned int* piVertices);
// -------------------------------------------------------------------
// Collect vertex/face data
void CollectData(const aiScene *pcScene, const aiNode *pcNode,
unsigned int iMat,
unsigned int iVFormat,
aiMesh *pcMeshOut,
unsigned int aiCurrent[2],
unsigned int *num_refs) const;
// -------------------------------------------------------------------
// Collect vertex/face data
void CollectData( aiScene* pcScene, aiNode* pcNode,
unsigned int iMat,
unsigned int iVFormat,
aiMesh* pcMeshOut,
unsigned int aiCurrent[2],
unsigned int* num_refs);
// -------------------------------------------------------------------
// Get a list of all vertex formats that occur for a given material
// The output list contains duplicate elements
void GetVFormatList(const aiScene *pcScene, unsigned int iMat,
std::list<unsigned int> &aiOut) const;
// -------------------------------------------------------------------
// Get a list of all vertex formats that occur for a given material
// The output list contains duplicate elements
void GetVFormatList( aiScene* pcScene, unsigned int iMat,
std::list<unsigned int>& aiOut);
// -------------------------------------------------------------------
// Compute the absolute transformation matrices of each node
void ComputeAbsoluteTransform(aiNode *pcNode);
// -------------------------------------------------------------------
// Compute the absolute transformation matrices of each node
void ComputeAbsoluteTransform( aiNode* pcNode );
// -------------------------------------------------------------------
// Simple routine to build meshes in worldspace, no further optimization
void BuildWCSMeshes(std::vector<aiMesh *> &out, aiMesh **in,
unsigned int numIn, aiNode *node) const;
// -------------------------------------------------------------------
// Simple routine to build meshes in worldspace, no further optimization
void BuildWCSMeshes(std::vector<aiMesh*>& out, aiMesh** in,
unsigned int numIn, aiNode* node);
// -------------------------------------------------------------------
// Apply the node transformation to a mesh
void ApplyTransform(aiMesh *mesh, const aiMatrix4x4 &mat) const;
// -------------------------------------------------------------------
// Apply the node transformation to a mesh
void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat);
// -------------------------------------------------------------------
// Reset transformation matrices to identity
void MakeIdentityTransform(aiNode *nd) const;
// -------------------------------------------------------------------
// Reset transformation matrices to identity
void MakeIdentityTransform(aiNode* nd);
// -------------------------------------------------------------------
// Build reference counters for all meshes
void BuildMeshRefCountArray(const aiNode *nd, unsigned int *refs) const;
// -------------------------------------------------------------------
// Build reference counters for all meshes
void BuildMeshRefCountArray(aiNode* nd, unsigned int * refs);
//! Configuration option: keep scene hierarchy as long as possible
bool configKeepHierarchy;
bool configNormalize;
bool configTransform;
aiMatrix4x4 configTransformation;
bool mConfigPointCloud;
//! Configuration option: keep scene hierarchy as long as possible
bool configKeepHierarchy;
bool configNormalize;
bool configTransform;
aiMatrix4x4 configTransformation;
bool mConfigPointCloud;
};
} // end of namespace Assimp

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.
@ -230,6 +230,46 @@ VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh)
return avPerVertexWeights;
}
// -------------------------------------------------------------------------------
const char* TextureTypeToString(aiTextureType in)
{
switch (in)
{
case aiTextureType_NONE:
return "n/a";
case aiTextureType_DIFFUSE:
return "Diffuse";
case aiTextureType_SPECULAR:
return "Specular";
case aiTextureType_AMBIENT:
return "Ambient";
case aiTextureType_EMISSIVE:
return "Emissive";
case aiTextureType_OPACITY:
return "Opacity";
case aiTextureType_NORMALS:
return "Normals";
case aiTextureType_HEIGHT:
return "Height";
case aiTextureType_SHININESS:
return "Shininess";
case aiTextureType_DISPLACEMENT:
return "Displacement";
case aiTextureType_LIGHTMAP:
return "Lightmap";
case aiTextureType_REFLECTION:
return "Reflection";
case aiTextureType_UNKNOWN:
return "Unknown";
default:
break;
}
ai_assert(false);
return "BUG";
}
// -------------------------------------------------------------------------------
const char* MappingTypeToString(aiTextureMapping in)
{

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.
@ -316,6 +316,12 @@ typedef std::vector <PerVertexWeight> VertexWeightTable;
// Compute a per-vertex bone weight table
VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh);
// -------------------------------------------------------------------------------
// Get a string for a given aiTextureType
const char* TextureTypeToString(aiTextureType in);
// -------------------------------------------------------------------------------
// Get a string for a given aiTextureMapping
const char* MappingTypeToString(aiTextureMapping in);

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -1,447 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/// @file SplitByBoneCountProcess.cpp
/// Implementation of the SplitByBoneCount postprocessing step
// internal headers of the post-processing framework
#include "SplitByBoneCountProcess.h"
#include <assimp/postprocess.h>
#include <assimp/DefaultLogger.hpp>
#include <limits>
#include <assimp/TinyFormatter.h>
#include <assimp/Exceptional.h>
using namespace Assimp;
using namespace Assimp::Formatter;
// ------------------------------------------------------------------------------------------------
// Constructor
SplitByBoneCountProcess::SplitByBoneCountProcess()
{
// set default, might be overridden by importer config
mMaxBoneCount = AI_SBBC_DEFAULT_MAX_BONES;
}
// ------------------------------------------------------------------------------------------------
// Destructor
SplitByBoneCountProcess::~SplitByBoneCountProcess()
{
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag.
bool SplitByBoneCountProcess::IsActive( unsigned int pFlags) const
{
return !!(pFlags & aiProcess_SplitByBoneCount);
}
// ------------------------------------------------------------------------------------------------
// Updates internal properties
void SplitByBoneCountProcess::SetupProperties(const Importer* pImp)
{
mMaxBoneCount = pImp->GetPropertyInteger(AI_CONFIG_PP_SBBC_MAX_BONES,AI_SBBC_DEFAULT_MAX_BONES);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void SplitByBoneCountProcess::Execute( aiScene* pScene)
{
ASSIMP_LOG_DEBUG("SplitByBoneCountProcess begin");
// early out
bool isNecessary = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
if( pScene->mMeshes[a]->mNumBones > mMaxBoneCount )
{
isNecessary = true;
break;
}
if( !isNecessary )
{
ASSIMP_LOG_DEBUG( format() << "SplitByBoneCountProcess early-out: no meshes with more than " << mMaxBoneCount << " bones." );
return;
}
// we need to do something. Let's go.
mSubMeshIndices.clear();
mSubMeshIndices.resize( pScene->mNumMeshes);
// build a new array of meshes for the scene
std::vector<aiMesh*> meshes;
for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
{
aiMesh* srcMesh = pScene->mMeshes[a];
std::vector<aiMesh*> newMeshes;
SplitMesh( pScene->mMeshes[a], newMeshes);
// mesh was split
if( !newMeshes.empty() )
{
// store new meshes and indices of the new meshes
for( unsigned int b = 0; b < newMeshes.size(); ++b)
{
mSubMeshIndices[a].push_back( static_cast<unsigned int>(meshes.size()));
meshes.push_back( newMeshes[b]);
}
// and destroy the source mesh. It should be completely contained inside the new submeshes
delete srcMesh;
}
else
{
// Mesh is kept unchanged - store it's new place in the mesh array
mSubMeshIndices[a].push_back( static_cast<unsigned int>(meshes.size()));
meshes.push_back( srcMesh);
}
}
// rebuild the scene's mesh array
pScene->mNumMeshes = static_cast<unsigned int>(meshes.size());
delete [] pScene->mMeshes;
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
std::copy( meshes.begin(), meshes.end(), pScene->mMeshes);
// recurse through all nodes and translate the node's mesh indices to fit the new mesh array
UpdateNode( pScene->mRootNode);
ASSIMP_LOG_DEBUG( format() << "SplitByBoneCountProcess end: split " << mSubMeshIndices.size() << " meshes into " << meshes.size() << " submeshes." );
}
// ------------------------------------------------------------------------------------------------
// Splits the given mesh by bone count.
void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh*>& poNewMeshes) const
{
// skip if not necessary
if( pMesh->mNumBones <= mMaxBoneCount )
{
return;
}
// necessary optimisation: build a list of all affecting bones for each vertex
// TODO: (thom) maybe add a custom allocator here to avoid allocating tens of thousands of small arrays
typedef std::pair<unsigned int, float> BoneWeight;
std::vector< std::vector<BoneWeight> > vertexBones( pMesh->mNumVertices);
for( unsigned int a = 0; a < pMesh->mNumBones; ++a)
{
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));
}
}
unsigned int numFacesHandled = 0;
std::vector<bool> isFaceHandled( pMesh->mNumFaces, false);
while( numFacesHandled < pMesh->mNumFaces )
{
// which bones are used in the current submesh
unsigned int numBones = 0;
std::vector<bool> isBoneUsed( pMesh->mNumBones, false);
// indices of the faces which are going to go into this submesh
std::vector<unsigned int> subMeshFaces;
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)
{
// skip if the face is already stored in a submesh
if( isFaceHandled[a] )
{
continue;
}
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)
{
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);
}
}
}
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 )
{
continue;
}
// mark all new bones as necessary
while( !newBonesAtCurrentFace.empty() )
{
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;
numBones++;
}
// store the face index and the vertex count
subMeshFaces.push_back( a);
numSubMeshVertices += face.mNumIndices;
// remember that this face is handled
isFaceHandled[a] = true;
numFacesHandled++;
}
// create a new mesh to hold this subset of the source mesh
aiMesh* newMesh = new aiMesh;
if( pMesh->mName.length > 0 )
{
newMesh->mName.Set( format() << pMesh->mName.data << "_sub" << poNewMeshes.size());
}
newMesh->mMaterialIndex = pMesh->mMaterialIndex;
newMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes;
poNewMeshes.push_back( newMesh);
// create all the arrays for this mesh if the old mesh contained them
newMesh->mNumVertices = numSubMeshVertices;
newMesh->mNumFaces = static_cast<unsigned int>(subMeshFaces.size());
newMesh->mVertices = new aiVector3D[newMesh->mNumVertices];
if( pMesh->HasNormals() )
{
newMesh->mNormals = new aiVector3D[newMesh->mNumVertices];
}
if( pMesh->HasTangentsAndBitangents() )
{
newMesh->mTangents = new aiVector3D[newMesh->mNumVertices];
newMesh->mBitangents = new aiVector3D[newMesh->mNumVertices];
}
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
{
if( pMesh->HasTextureCoords( a) )
{
newMesh->mTextureCoords[a] = new aiVector3D[newMesh->mNumVertices];
}
newMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a];
}
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
{
if( pMesh->HasVertexColors( a) )
{
newMesh->mColors[a] = new aiColor4D[newMesh->mNumVertices];
}
}
// and copy over the data, generating faces with linear indices along the way
newMesh->mFaces = new aiFace[subMeshFaces.size()];
unsigned int nvi = 0; // next vertex index
std::vector<unsigned int> previousVertexIndices( numSubMeshVertices, std::numeric_limits<unsigned int>::max()); // per new vertex: its index in the source mesh
for( unsigned int a = 0; a < subMeshFaces.size(); ++a )
{
const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]];
aiFace& dstFace = newMesh->mFaces[a];
dstFace.mNumIndices = srcFace.mNumIndices;
dstFace.mIndices = new unsigned int[dstFace.mNumIndices];
// accumulate linearly all the vertices of the source face
for( unsigned int b = 0; b < dstFace.mNumIndices; ++b )
{
unsigned int srcIndex = srcFace.mIndices[b];
dstFace.mIndices[b] = nvi;
previousVertexIndices[nvi] = srcIndex;
newMesh->mVertices[nvi] = pMesh->mVertices[srcIndex];
if( pMesh->HasNormals() )
{
newMesh->mNormals[nvi] = pMesh->mNormals[srcIndex];
}
if( pMesh->HasTangentsAndBitangents() )
{
newMesh->mTangents[nvi] = pMesh->mTangents[srcIndex];
newMesh->mBitangents[nvi] = pMesh->mBitangents[srcIndex];
}
for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c )
{
if( pMesh->HasTextureCoords( c) )
{
newMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
}
}
for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c )
{
if( pMesh->HasVertexColors( c) )
{
newMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex];
}
}
nvi++;
}
}
ai_assert( nvi == numSubMeshVertices );
// Create the bones for the new submesh: first create the bone array
newMesh->mNumBones = 0;
newMesh->mBones = new aiBone*[numBones];
std::vector<unsigned int> mappedBoneIndex( pMesh->mNumBones, std::numeric_limits<unsigned int>::max());
for( unsigned int a = 0; a < pMesh->mNumBones; ++a )
{
if( !isBoneUsed[a] )
{
continue;
}
// create the new bone
const aiBone* srcBone = pMesh->mBones[a];
aiBone* dstBone = new aiBone;
mappedBoneIndex[a] = newMesh->mNumBones;
newMesh->mBones[newMesh->mNumBones++] = dstBone;
dstBone->mName = srcBone->mName;
dstBone->mOffsetMatrix = srcBone->mOffsetMatrix;
dstBone->mNumWeights = 0;
}
ai_assert( newMesh->mNumBones == numBones );
// iterate over all new vertices and count which bones affected its old vertex in the source mesh
for( unsigned int a = 0; a < numSubMeshVertices; ++a )
{
unsigned int oldIndex = previousVertexIndices[a];
const std::vector<BoneWeight>& bonesOnThisVertex = vertexBones[oldIndex];
for( unsigned int b = 0; b < bonesOnThisVertex.size(); ++b )
{
unsigned int newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
if( newBoneIndex != std::numeric_limits<unsigned int>::max() )
{
newMesh->mBones[newBoneIndex]->mNumWeights++;
}
}
}
// allocate all bone weight arrays accordingly
for( unsigned int a = 0; a < newMesh->mNumBones; ++a )
{
aiBone* bone = newMesh->mBones[a];
ai_assert( bone->mNumWeights > 0 );
bone->mWeights = new aiVertexWeight[bone->mNumWeights];
bone->mNumWeights = 0; // for counting up in the next step
}
// now copy all the bone vertex weights for all the vertices which made it into the new submesh
for( unsigned int a = 0; a < numSubMeshVertices; ++a)
{
// find the source vertex for it in the source mesh
unsigned int previousIndex = previousVertexIndices[a];
// these bones were affecting it
const std::vector<BoneWeight>& bonesOnThisVertex = vertexBones[previousIndex];
// all of the bones affecting it should be present in the new submesh, or else
// the face it comprises shouldn't be present
for( unsigned int b = 0; b < bonesOnThisVertex.size(); ++b)
{
unsigned int newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
ai_assert( newBoneIndex != std::numeric_limits<unsigned int>::max() );
aiVertexWeight* dstWeight = newMesh->mBones[newBoneIndex]->mWeights + newMesh->mBones[newBoneIndex]->mNumWeights;
newMesh->mBones[newBoneIndex]->mNumWeights++;
dstWeight->mVertexId = a;
dstWeight->mWeight = bonesOnThisVertex[b].second;
}
}
// I have the strange feeling that this will break apart at some point in time...
}
}
// ------------------------------------------------------------------------------------------------
// Recursively updates the node's mesh list to account for the changed mesh list
void SplitByBoneCountProcess::UpdateNode( aiNode* pNode) const
{
// rebuild the node's mesh index list
if( pNode->mNumMeshes > 0 )
{
std::vector<unsigned int> newMeshList;
for( unsigned int a = 0; a < pNode->mNumMeshes; ++a)
{
unsigned int srcIndex = pNode->mMeshes[a];
const std::vector<unsigned int>& replaceMeshes = mSubMeshIndices[srcIndex];
newMeshList.insert( newMeshList.end(), replaceMeshes.begin(), replaceMeshes.end());
}
delete [] pNode->mMeshes;
pNode->mNumMeshes = static_cast<unsigned int>(newMeshList.size());
pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
std::copy( newMeshList.begin(), newMeshList.end(), pNode->mMeshes);
}
// do that also recursively for all children
for( unsigned int a = 0; a < pNode->mNumChildren; ++a )
{
UpdateNode( pNode->mChildren[a]);
}
}

View file

@ -1,111 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/// @file SplitByBoneCountProcess.h
/// Defines a post processing step to split meshes with many bones into submeshes
#ifndef AI_SPLITBYBONECOUNTPROCESS_H_INC
#define AI_SPLITBYBONECOUNTPROCESS_H_INC
#include <vector>
#include "Common/BaseProcess.h"
#include <assimp/mesh.h>
#include <assimp/scene.h>
namespace Assimp
{
/** Postprocessing filter to split meshes with many bones into submeshes
* so that each submesh has a certain max bone count.
*
* Applied BEFORE the JoinVertices-Step occurs.
* Returns NON-UNIQUE vertices, splits by bone count.
*/
class SplitByBoneCountProcess : public BaseProcess
{
public:
SplitByBoneCountProcess();
~SplitByBoneCountProcess();
public:
/** Returns whether the processing step is present in the given flag.
* @param pFlags The processing flags the importer was called with. A
* bitwise combination of #aiPostProcessSteps.
* @return true if the process is present in this flag fields,
* false if not.
*/
bool IsActive( unsigned int pFlags) const;
/** Called prior to ExecuteOnScene().
* The function is a request to the process to update its configuration
* basing on the Importer's configuration property list.
*/
virtual void SetupProperties(const Importer* pImp);
protected:
/** Executes the post processing step on the given imported data.
* At the moment a process is not supposed to fail.
* @param pScene The imported data to work at.
*/
void Execute( aiScene* pScene);
/// Splits the given mesh by bone count.
/// @param pMesh the Mesh to split. Is not changed at all, but might be superfluous in case it was split.
/// @param poNewMeshes Array of submeshes created in the process. Empty if splitting was not necessary.
void SplitMesh( const aiMesh* pMesh, std::vector<aiMesh*>& poNewMeshes) const;
/// Recursively updates the node's mesh list to account for the changed mesh list
void UpdateNode( aiNode* pNode) const;
public:
/// Max bone count. Splitting occurs if a mesh has more than that number of bones.
size_t mMaxBoneCount;
/// Per mesh index: Array of indices of the new submeshes.
std::vector< std::vector<unsigned int> > mSubMeshIndices;
};
} // end of namespace Assimp
#endif // !!AI_SPLITBYBONECOUNTPROCESS_H_INC

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.
@ -92,8 +92,9 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info)
* are applied is - as always - scaling, rotation, translation.
*/
int rounded;
char szTemp[512];
char szTemp[512];
int rounded = 0;
/* Optimize the rotation angle. That's slightly difficult as
* we have an inprecise floating-point number (when comparing
@ -184,6 +185,7 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info)
info.mTranslation.y = out;
}
}
return;
}
// ------------------------------------------------------------------------------------------------
@ -426,7 +428,7 @@ void TextureTransformStep::Execute( aiScene* pScene)
// at the end of the list
bool ref[AI_MAX_NUMBER_OF_TEXTURECOORDS];
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
ref[n] = !mesh->mTextureCoords[n];
ref[n] = (!mesh->mTextureCoords[n] ? true : false);
for (it = trafo.begin();it != trafo.end(); ++it)
ref[(*it).uvIndex] = true;

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
@ -538,17 +538,13 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
{
Validate(&pAnimation->mName);
// validate all animations
if (pAnimation->mNumChannels || pAnimation->mNumMorphMeshChannels)
// validate all materials
if (pAnimation->mNumChannels)
{
if (!pAnimation->mChannels && pAnimation->mNumChannels) {
if (!pAnimation->mChannels) {
ReportError("aiAnimation::mChannels is NULL (aiAnimation::mNumChannels is %i)",
pAnimation->mNumChannels);
}
if (!pAnimation->mMorphMeshChannels && pAnimation->mNumMorphMeshChannels) {
ReportError("aiAnimation::mMorphMeshChannels is NULL (aiAnimation::mNumMorphMeshChannels is %i)",
pAnimation->mNumMorphMeshChannels);
}
for (unsigned int i = 0; i < pAnimation->mNumChannels;++i)
{
if (!pAnimation->mChannels[i])
@ -558,15 +554,6 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
}
Validate(pAnimation, pAnimation->mChannels[i]);
}
for (unsigned int i = 0; i < pAnimation->mNumMorphMeshChannels;++i)
{
if (!pAnimation->mMorphMeshChannels[i])
{
ReportError("aiAnimation::mMorphMeshChannels[%i] is NULL (aiAnimation::mNumMorphMeshChannels is %i)",
i, pAnimation->mNumMorphMeshChannels);
}
Validate(pAnimation, pAnimation->mMorphMeshChannels[i]);
}
}
else {
ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there.");
@ -603,18 +590,15 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
ReportError("%s #%i is set, but there are only %i %s textures",
szType,iIndex,iNumIndices,szType);
}
if (!iNumIndices) {
return;
}
if (!iNumIndices)return;
std::vector<aiTextureMapping> mappings(iNumIndices);
// Now check whether all UV indices are valid ...
bool bNoSpecified = true;
for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) {
for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
{
aiMaterialProperty* prop = pMaterial->mProperties[i];
if (prop->mSemantic != type) {
continue;
}
if (prop->mSemantic != type)continue;
if ((int)prop->mIndex >= iNumIndices)
{
@ -637,7 +621,7 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
ReportError("Material property %s%i is expected to be 5 floats large (size is %i)",
prop->mKey.data,prop->mIndex, prop->mDataLength);
}
//mappings[prop->mIndex] = ((aiUVTransform*)prop->mData);
mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData);
}
else if (!::strcmp(prop->mKey.data,"$tex.uvwsrc")) {
if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength)
@ -777,12 +761,6 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
SearchForInvalidTextures(pMaterial,aiTextureType_DISPLACEMENT);
SearchForInvalidTextures(pMaterial,aiTextureType_LIGHTMAP);
SearchForInvalidTextures(pMaterial,aiTextureType_REFLECTION);
SearchForInvalidTextures(pMaterial,aiTextureType_BASE_COLOR);
SearchForInvalidTextures(pMaterial,aiTextureType_NORMAL_CAMERA);
SearchForInvalidTextures(pMaterial,aiTextureType_EMISSION_COLOR);
SearchForInvalidTextures(pMaterial,aiTextureType_METALNESS);
SearchForInvalidTextures(pMaterial,aiTextureType_DIFFUSE_ROUGHNESS);
SearchForInvalidTextures(pMaterial,aiTextureType_AMBIENT_OCCLUSION);
}
// ------------------------------------------------------------------------------------------------
@ -804,7 +782,7 @@ void ValidateDSProcess::Validate( const aiTexture* pTexture)
if (!pTexture->mWidth) {
ReportError("aiTexture::mWidth is zero (compressed texture)");
}
if ('\0' != pTexture->achFormatHint[HINTMAXTEXTURELEN - 1]) {
if ('\0' != pTexture->achFormatHint[3]) {
ReportWarning("aiTexture::achFormatHint must be zero-terminated");
}
else if ('.' == pTexture->achFormatHint[0]) {
@ -925,48 +903,6 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
}
}
void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
const aiMeshMorphAnim* pMeshMorphAnim)
{
Validate(&pMeshMorphAnim->mName);
if (!pMeshMorphAnim->mNumKeys) {
ReportError("Empty mesh morph animation channel");
}
// otherwise check whether one of the keys exceeds the total duration of the animation
if (pMeshMorphAnim->mNumKeys)
{
if (!pMeshMorphAnim->mKeys)
{
ReportError("aiMeshMorphAnim::mKeys is NULL (aiMeshMorphAnim::mNumKeys is %i)",
pMeshMorphAnim->mNumKeys);
}
double dLast = -10e10;
for (unsigned int i = 0; i < pMeshMorphAnim->mNumKeys;++i)
{
// ScenePreprocessor will compute the duration if still the default value
// (Aramis) Add small epsilon, comparison tended to fail if max_time == duration,
// seems to be due the compilers register usage/width.
if (pAnimation->mDuration > 0. && pMeshMorphAnim->mKeys[i].mTime > pAnimation->mDuration+0.001)
{
ReportError("aiMeshMorphAnim::mKeys[%i].mTime (%.5f) is larger "
"than aiAnimation::mDuration (which is %.5f)",i,
(float)pMeshMorphAnim->mKeys[i].mTime,
(float)pAnimation->mDuration);
}
if (i && pMeshMorphAnim->mKeys[i].mTime <= dLast)
{
ReportWarning("aiMeshMorphAnim::mKeys[%i].mTime (%.5f) is smaller "
"than aiMeshMorphAnim::mKeys[%i] (which is %.5f)",i,
(float)pMeshMorphAnim->mKeys[i].mTime,
i-1, (float)dLast);
}
dLast = pMeshMorphAnim->mKeys[i].mTime;
}
}
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiNode* pNode)
{

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.
@ -55,7 +55,6 @@ struct aiBone;
struct aiMesh;
struct aiAnimation;
struct aiNodeAnim;
struct aiMeshMorphAnim;
struct aiTexture;
struct aiMaterial;
struct aiNode;
@ -151,13 +150,6 @@ protected:
void Validate( const aiAnimation* pAnimation,
const aiNodeAnim* pBoneAnim);
/** Validates a mesh morph animation channel.
* @param pAnimation Input animation.
* @param pMeshMorphAnim Mesh morph animation channel.
* */
void Validate( const aiAnimation* pAnimation,
const aiMeshMorphAnim* pMeshMorphAnim);
// -------------------------------------------------------------------
/** Validates a node and all of its subnodes
* @param Node Input node*/