mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-06 14:00:39 +00:00
Updated Assimp
Added initial behavior for ImageAssets to hold a list of GFX resources of different texture profiles to avoid mem leaks with incorrect-typed usages Added function to ImageAsset to get best-fit asset, allowing for fallbacks if the requested assetID is not found Added function to ShapeAsset to get best-fit asset, allowing for fallbacks if the requested assetID is not found Disabled fields for dynamic and static shadowmap refresh rates Moved noShape model to core/rendering/shapes to place it in a more logical module position Added an include to avoid undefined type compile error and removed unneeded semicolon from zone code Added call to reload probe textures when a reloadTextures call is made Adjusted default directional light shadowmap settings to not be as extreme Added utility function to probe manager to allow any class to request a 'best fit' list of probes that would affect a given location, allowing other classes such as fog or particles to utilize IBL. Also updated probeManager's forward rendering to utilize same function to reduce code duplication. Shifted shape loader code to utilize assimp for loader consistency and testing Changed render bin used for SSAO postfx so it runs at the right time Made Core_Rendering module scan for assets Updated loose file references to a number of assets to follow proper formatting Refactored asset import code to follow a more consistent object heirarchy structure on importing assets, allowing more reliable cross-referencing between inbound items Updated asset import logic for materials/images so that they properly utilize ImageType. Images correctly save out the assigned image type, materials reference the images' type to know what map slot they should be used in. Importer logic also updated to better find-and-add associated images based on type. Cleaned up a bunch of old, outdated code in the asset importer Added initial handling for in-place importing of files without needing to process them through the UI. Added ability to edit module script from RMB context menu if torsion path is set Updated list field code for variable inspector to utilize correct ownerObject field
This commit is contained in:
parent
2d015bc426
commit
6ade6f08ce
545 changed files with 15077 additions and 8437 deletions
|
|
@ -2,8 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -36,7 +35,6 @@ 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"
|
||||
|
|
@ -50,219 +48,215 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace Assimp {
|
||||
|
||||
/// The default class constructor.
|
||||
ArmaturePopulate::ArmaturePopulate() : BaseProcess()
|
||||
{}
|
||||
ArmaturePopulate::ArmaturePopulate() :
|
||||
BaseProcess() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/// The class destructor.
|
||||
ArmaturePopulate::~ArmaturePopulate()
|
||||
{}
|
||||
ArmaturePopulate::~ArmaturePopulate() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
bool ArmaturePopulate::IsActive(unsigned int pFlags) const {
|
||||
return (pFlags & aiProcess_PopulateArmatureData) != 0;
|
||||
return (pFlags & aiProcess_PopulateArmatureData) != 0;
|
||||
}
|
||||
|
||||
void ArmaturePopulate::SetupProperties(const Importer *pImp) {
|
||||
// do nothing
|
||||
// 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);
|
||||
// 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);
|
||||
BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes);
|
||||
|
||||
ASSIMP_LOG_DEBUG_F("Bone stack size: ", bone_stack.size());
|
||||
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 :)
|
||||
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);
|
||||
// bone->mOffsetMatrix = bone_node->mTransformation;
|
||||
aiNode *armature = GetArmatureRoot(bone_node, bones);
|
||||
|
||||
ai_assert(armature);
|
||||
ai_assert(armature);
|
||||
|
||||
// set up bone armature id
|
||||
bone->mArmature = 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;
|
||||
}
|
||||
// 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 */
|
||||
// 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);
|
||||
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);
|
||||
// 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);
|
||||
for (unsigned int boneId = 0; boneId < mesh->mNumBones; ++boneId) {
|
||||
aiBone *bone = mesh->mBones[boneId];
|
||||
ai_assert(bone);
|
||||
|
||||
// duplicate meshes 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);
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
// find mesh and get bones
|
||||
// then do recursive lookup for bones in root node hierarchy
|
||||
BuildBoneList(child, root_node, scene, bones);
|
||||
}
|
||||
|
||||
BuildBoneList(child, root_node, scene, bones);
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare flat node list which can be used for non recursive lookups later */
|
||||
// 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);
|
||||
ai_assert(current_node);
|
||||
|
||||
for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) {
|
||||
aiNode *child = current_node->mChildren[nodeId];
|
||||
ai_assert(child);
|
||||
for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) {
|
||||
aiNode *child = current_node->mChildren[nodeId];
|
||||
ai_assert(child);
|
||||
|
||||
nodes.push_back(child);
|
||||
if (child->mNumMeshes == 0) {
|
||||
nodes.push_back(child);
|
||||
}
|
||||
|
||||
BuildNodeList(child, nodes);
|
||||
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 :)
|
||||
*/
|
||||
// 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());
|
||||
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());
|
||||
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);
|
||||
node = GetNodeFromStack(bone->mName, node_stack);
|
||||
|
||||
if (!node) {
|
||||
ASSIMP_LOG_ERROR("serious import issue node for bone was not detected");
|
||||
continue;
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
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)
|
||||
*/
|
||||
// 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;
|
||||
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;
|
||||
}
|
||||
|
||||
bone_node = bone_node->mParent;
|
||||
}
|
||||
|
||||
ASSIMP_LOG_ERROR("GetArmatureRoot() can't find armature!");
|
||||
|
||||
return nullptr;
|
||||
ASSIMP_LOG_ERROR("GetArmatureRoot() can't find armature!");
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Simple IsBoneNode check if this could be a bone */
|
||||
// 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;
|
||||
for (aiBone *bone : bones) {
|
||||
if (bone->mName == bone_name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
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 */
|
||||
// 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;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
// unique names can cause this problem
|
||||
ASSIMP_LOG_ERROR("[Serious] GetNodeFromStack() can't find node from stack!");
|
||||
// unique names can cause this problem
|
||||
ASSIMP_LOG_ERROR("[Serious] GetNodeFromStack() can't find node from stack!");
|
||||
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // Namespace Assimp
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
@ -137,8 +137,9 @@ public:
|
|||
// -------------------------------------------------------------------
|
||||
void Execute( aiScene* pScene);
|
||||
|
||||
protected:
|
||||
void ProcessMesh( aiMesh* pMesh);
|
||||
public:
|
||||
/** Some other types of post-processing require winding order flips */
|
||||
static void ProcessMesh( aiMesh* pMesh);
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
@ -128,7 +128,8 @@ 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
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, 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 <assimp/SceneCombiner.h>
|
||||
#include "ConvertToLHProcess.h"
|
||||
#include <assimp/Exceptional.h>
|
||||
#include <assimp/SceneCombiner.h>
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace Assimp;
|
||||
|
|
@ -60,292 +60,299 @@ 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 = NULL;
|
||||
aiMatrix4x4 inv;
|
||||
// Now check for possible optimizations in our list of child nodes. join as many as possible
|
||||
aiNode *join_master = nullptr;
|
||||
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*>::iterator it = join.begin(); it != join.end(); ++it) {
|
||||
out_meshes += (*it)->mNumMeshes;
|
||||
}
|
||||
unsigned int out_meshes = 0;
|
||||
for (std::list<aiNode *>::const_iterator it = join.cbegin(); it != join.cend(); ++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 (std::list<aiNode*>::iterator it = join.begin(); it != join.end(); ++it) {
|
||||
for (unsigned int n = 0; n < (*it)->mNumMeshes; ++n) {
|
||||
for (const aiNode *join_node : join) {
|
||||
for (unsigned int n = 0; n < join_node->mNumMeshes; ++n) {
|
||||
|
||||
*tmp = (*it)->mMeshes[n];
|
||||
aiMesh* mesh = mScene->mMeshes[*tmp++];
|
||||
*tmp = join_node->mMeshes[n];
|
||||
aiMesh *mesh = mScene->mMeshes[*tmp++];
|
||||
|
||||
// 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) {
|
||||
// Assume the transformation is affine
|
||||
// manually move the mesh into the right coordinate system
|
||||
|
||||
mesh->mVertices[a] *= (*it)->mTransformation;
|
||||
// Check for odd negative scale (mirror)
|
||||
if (join_node->mTransformation.Determinant() < 0) {
|
||||
// Reverse the mesh face winding order
|
||||
FlipWindingOrderProcess::ProcessMesh(mesh);
|
||||
}
|
||||
|
||||
if (mesh->HasNormals())
|
||||
mesh->mNormals[a] *= IT;
|
||||
// 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->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) {
|
||||
mesh->mVertices[a] *= join_node->mTransformation;
|
||||
|
||||
delete[] nd->mChildren;
|
||||
if (mesh->HasNormals())
|
||||
mesh->mNormals[a] *= IT;
|
||||
|
||||
if (!child_nodes.empty()) {
|
||||
nd->mChildren = new aiNode*[child_nodes.size()];
|
||||
}
|
||||
else nd->mChildren = nullptr;
|
||||
}
|
||||
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) {
|
||||
|
||||
nd->mNumChildren = static_cast<unsigned int>(child_nodes.size());
|
||||
delete[] nd->mChildren;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (!child_nodes.empty()) {
|
||||
nd->mChildren = new aiNode *[child_nodes.size()];
|
||||
} else
|
||||
nd->mChildren = nullptr;
|
||||
}
|
||||
|
||||
nodes_out += static_cast<unsigned int>(child_nodes.size());
|
||||
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());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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 = NULL;
|
||||
throw DeadlyImportError("After optimizing the scene graph, no data remains");
|
||||
}
|
||||
if (dummy_root->mNumChildren == 0) {
|
||||
pScene->mRootNode = nullptr;
|
||||
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] = NULL;
|
||||
delete dummy_root;
|
||||
}
|
||||
dummy_root->mChildren[0] = nullptr;
|
||||
delete dummy_root;
|
||||
}
|
||||
|
||||
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();
|
||||
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();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
@ -75,13 +75,13 @@ public:
|
|||
~OptimizeGraphProcess();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
bool IsActive( unsigned int pFlags) const;
|
||||
bool IsActive( unsigned int pFlags) const override;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
void Execute( aiScene* pScene);
|
||||
void Execute( aiScene* pScene) override;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
void SetupProperties(const Importer* pImp);
|
||||
void SetupProperties(const Importer* pImp) override;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** @brief Add a list of node names to be locked and not modified.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, 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;
|
||||
// -------------------------------------------------------------------
|
||||
// Check whether step is active
|
||||
bool IsActive(unsigned int pFlags) const override;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Execute step on a given scene
|
||||
void Execute( aiScene* pScene);
|
||||
// -------------------------------------------------------------------
|
||||
// Execute step on a given scene
|
||||
void Execute(aiScene *pScene) override;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Setup import settings
|
||||
void SetupProperties(const Importer* pImp);
|
||||
// -------------------------------------------------------------------
|
||||
// Setup import settings
|
||||
void SetupProperties(const Importer *pImp) override;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** @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( aiNode* pcNode );
|
||||
// -------------------------------------------------------------------
|
||||
// Count the number of nodes
|
||||
unsigned int CountNodes(const aiNode *pcNode) const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Get a bitwise combination identifying the vertex format of a mesh
|
||||
unsigned int GetMeshVFormat(aiMesh* pcMesh);
|
||||
// -------------------------------------------------------------------
|
||||
// Get a bitwise combination identifying the vertex format of a mesh
|
||||
unsigned int GetMeshVFormat(aiMesh *pcMesh) 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);
|
||||
// -------------------------------------------------------------------
|
||||
// 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;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// 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);
|
||||
// -------------------------------------------------------------------
|
||||
// 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;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// 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);
|
||||
// -------------------------------------------------------------------
|
||||
// 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;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// 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);
|
||||
// -------------------------------------------------------------------
|
||||
// Simple routine to build meshes in worldspace, no further optimization
|
||||
void BuildWCSMeshes(std::vector<aiMesh *> &out, aiMesh **in,
|
||||
unsigned int numIn, aiNode *node) const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Apply the node transformation to a mesh
|
||||
void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat);
|
||||
// -------------------------------------------------------------------
|
||||
// Apply the node transformation to a mesh
|
||||
void ApplyTransform(aiMesh *mesh, const aiMatrix4x4 &mat) const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Reset transformation matrices to identity
|
||||
void MakeIdentityTransform(aiNode* nd);
|
||||
// -------------------------------------------------------------------
|
||||
// Reset transformation matrices to identity
|
||||
void MakeIdentityTransform(aiNode *nd) const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Build reference counters for all meshes
|
||||
void BuildMeshRefCountArray(aiNode* nd, unsigned int * refs);
|
||||
// -------------------------------------------------------------------
|
||||
// Build reference counters for all meshes
|
||||
void BuildMeshRefCountArray(const aiNode *nd, unsigned int *refs) const;
|
||||
|
||||
//! 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
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
@ -230,46 +230,6 @@ 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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
@ -316,12 +316,6 @@ 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);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,447 @@
|
|||
/*
|
||||
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]);
|
||||
}
|
||||
}
|
||||
111
Engine/lib/assimp/code/PostProcessing/SplitByBoneCountProcess.h
Normal file
111
Engine/lib/assimp/code/PostProcessing/SplitByBoneCountProcess.h
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
@ -92,9 +92,8 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info)
|
|||
* are applied is - as always - scaling, rotation, translation.
|
||||
*/
|
||||
|
||||
char szTemp[512];
|
||||
int rounded = 0;
|
||||
|
||||
int rounded;
|
||||
char szTemp[512];
|
||||
|
||||
/* Optimize the rotation angle. That's slightly difficult as
|
||||
* we have an inprecise floating-point number (when comparing
|
||||
|
|
@ -185,7 +184,6 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info)
|
|||
info.mTranslation.y = out;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
@ -428,7 +426,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] ? true : false);
|
||||
ref[n] = !mesh->mTextureCoords[n];
|
||||
|
||||
for (it = trafo.begin();it != trafo.end(); ++it)
|
||||
ref[(*it).uvIndex] = true;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
|
|
@ -603,15 +603,18 @@ 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)
|
||||
{
|
||||
|
|
@ -634,7 +637,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] = *((aiTextureMapping*)prop->mData);
|
||||
//mappings[prop->mIndex] = ((aiUVTransform*)prop->mData);
|
||||
}
|
||||
else if (!::strcmp(prop->mKey.data,"$tex.uvwsrc")) {
|
||||
if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength)
|
||||
|
|
@ -774,6 +777,12 @@ 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);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
@ -795,7 +804,7 @@ void ValidateDSProcess::Validate( const aiTexture* pTexture)
|
|||
if (!pTexture->mWidth) {
|
||||
ReportError("aiTexture::mWidth is zero (compressed texture)");
|
||||
}
|
||||
if ('\0' != pTexture->achFormatHint[3]) {
|
||||
if ('\0' != pTexture->achFormatHint[HINTMAXTEXTURELEN - 1]) {
|
||||
ReportWarning("aiTexture::achFormatHint must be zero-terminated");
|
||||
}
|
||||
else if ('.' == pTexture->achFormatHint[0]) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue