Merge branch 'master' into Dependabot-GitHub-Actions
commit
4a5ad50828
3
Build.md
3
Build.md
|
@ -14,7 +14,8 @@ The assimp port in vcpkg is kept up to date by Microsoft team members and commun
|
|||
## Install on Ubuntu
|
||||
You can install the Asset-Importer-Lib via apt:
|
||||
```
|
||||
sudo apt-get install assimp
|
||||
sudp apt-get update
|
||||
sudo apt-get install libassimp-dev
|
||||
```
|
||||
|
||||
## Install pyassimp
|
||||
|
|
|
@ -90,7 +90,7 @@ OPTION( ASSIMP_BUILD_ZLIB
|
|||
)
|
||||
OPTION( ASSIMP_BUILD_ASSIMP_TOOLS
|
||||
"If the supplementary tools for Assimp are built in addition to the library."
|
||||
ON
|
||||
OFF
|
||||
)
|
||||
OPTION ( ASSIMP_BUILD_SAMPLES
|
||||
"If the official samples are built as well (needs Glut)."
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Use this section to tell people about which versions of your project are
|
||||
currently being supported with security updates.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 5.2.4 | :white_check_mark: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you have found any security vulnerability you can contact us via
|
||||
kim.kulling@googlemail.com
|
||||
|
|
@ -74,6 +74,8 @@ namespace XmlTag {
|
|||
const char* const pid = "pid";
|
||||
const char* const pindex = "pindex";
|
||||
const char* const p1 = "p1";
|
||||
const char *const p2 = "p2";
|
||||
const char *const p3 = "p3";
|
||||
const char* const name = "name";
|
||||
const char* const type = "type";
|
||||
const char* const build = "build";
|
||||
|
|
|
@ -64,7 +64,7 @@ bool validateColorString(const char *color) {
|
|||
return true;
|
||||
}
|
||||
|
||||
aiFace ReadTriangle(XmlNode &node) {
|
||||
aiFace ReadTriangle(XmlNode &node, unsigned int &texId0, unsigned int &texId1, unsigned int &texId2) {
|
||||
aiFace face;
|
||||
|
||||
face.mNumIndices = 3;
|
||||
|
@ -73,6 +73,10 @@ aiFace ReadTriangle(XmlNode &node) {
|
|||
face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
|
||||
face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
|
||||
|
||||
texId0 = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::p1).as_string()));
|
||||
texId1 = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::p2).as_string()));
|
||||
texId2 = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::p3).as_string()));
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
|
@ -412,6 +416,8 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
|
|||
bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
|
||||
bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
|
||||
|
||||
unsigned int texId[3];
|
||||
aiFace face = ReadTriangle(currentNode, texId[0], texId[1], texId[2]);
|
||||
if (hasPid && hasP1) {
|
||||
auto it = mResourcesDictionnary.find(pid);
|
||||
if (it != mResourcesDictionnary.end()) {
|
||||
|
@ -420,6 +426,11 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
|
|||
mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
|
||||
} else if (it->second->getType() == ResourceType::RT_Texture2DGroup) {
|
||||
if (mesh->mTextureCoords[0] == nullptr) {
|
||||
mesh->mNumUVComponents[0] = 2;
|
||||
for (unsigned int i = 1; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
|
||||
mesh->mNumUVComponents[i] = 0;
|
||||
}
|
||||
|
||||
Texture2DGroup *group = static_cast<Texture2DGroup *>(it->second);
|
||||
const std::string name = ai_to_string(group->mTexId);
|
||||
for (size_t i = 0; i < mMaterials.size(); ++i) {
|
||||
|
@ -427,8 +438,9 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
|
|||
mesh->mMaterialIndex = static_cast<unsigned int>(i);
|
||||
}
|
||||
}
|
||||
mesh->mTextureCoords[0] = new aiVector3D[group->mTex2dCoords.size()];
|
||||
for (unsigned int i = 0; i < group->mTex2dCoords.size(); ++i) {
|
||||
mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
|
||||
mesh->mTextureCoords[0][i] = aiVector3D(group->mTex2dCoords[i].x, group->mTex2dCoords[i].y, 0);
|
||||
}
|
||||
}
|
||||
|
@ -436,7 +448,6 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
|
|||
}
|
||||
}
|
||||
|
||||
aiFace face = ReadTriangle(currentNode);
|
||||
faces.push_back(face);
|
||||
}
|
||||
}
|
||||
|
@ -578,11 +589,15 @@ aiMaterial *XmlSerializer::readMaterialDef(XmlNode &node, unsigned int basemater
|
|||
}
|
||||
|
||||
void XmlSerializer::StoreMaterialsInScene(aiScene *scene) {
|
||||
if (nullptr == scene || mMaterials.empty()) {
|
||||
if (nullptr == scene) {
|
||||
return;
|
||||
}
|
||||
|
||||
scene->mNumMaterials = static_cast<unsigned int>(mMaterials.size());
|
||||
if (scene->mNumMaterials == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
|
||||
for (size_t i = 0; i < mMaterials.size(); ++i) {
|
||||
scene->mMaterials[i] = mMaterials[i];
|
||||
|
|
|
@ -621,6 +621,11 @@ struct Animation {
|
|||
|
||||
for (std::vector<Animation *>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) {
|
||||
Animation *anim = *it;
|
||||
// Assign the first animation name to the parent if empty.
|
||||
// This prevents the animation name from being lost when animations are combined
|
||||
if (mName.empty()) {
|
||||
mName = anim->mName;
|
||||
}
|
||||
CombineSingleChannelAnimationsRecursively(anim);
|
||||
|
||||
if (childrenAnimationsHaveDifferentChannels && anim->mChannels.size() == 1 &&
|
||||
|
|
|
@ -102,6 +102,7 @@ ColladaLoader::ColladaLoader() :
|
|||
mTextures(),
|
||||
mAnims(),
|
||||
noSkeletonMesh(false),
|
||||
removeEmptyBones(false),
|
||||
ignoreUpDirection(false),
|
||||
useColladaName(false),
|
||||
mNodeNameCounter(0) {
|
||||
|
@ -130,6 +131,7 @@ bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
void ColladaLoader::SetupProperties(const Importer *pImp) {
|
||||
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, 0) != 0;
|
||||
removeEmptyBones = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true) != 0;
|
||||
ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION, 0) != 0;
|
||||
useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES, 0) != 0;
|
||||
}
|
||||
|
@ -798,9 +800,10 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
|
|||
// count the number of bones which influence vertices of the current submesh
|
||||
size_t numRemainingBones = 0;
|
||||
for (const auto & dstBone : dstBones) {
|
||||
if (!dstBone.empty()) {
|
||||
++numRemainingBones;
|
||||
if (dstBone.empty() && removeEmptyBones) {
|
||||
continue;
|
||||
}
|
||||
++numRemainingBones;
|
||||
}
|
||||
|
||||
// create bone array and copy bone weights one by one
|
||||
|
@ -809,7 +812,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
|
|||
size_t boneCount = 0;
|
||||
for (size_t a = 0; a < numBones; ++a) {
|
||||
// omit bones without weights
|
||||
if (dstBones[a].empty()) {
|
||||
if (dstBones[a].empty() && removeEmptyBones) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -237,6 +237,7 @@ protected:
|
|||
std::vector<aiAnimation *> mAnims;
|
||||
|
||||
bool noSkeletonMesh;
|
||||
bool removeEmptyBones;
|
||||
bool ignoreUpDirection;
|
||||
bool useColladaName;
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
|||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
@ -87,11 +86,6 @@ AnimationCurve::AnimationCurve(uint64_t id, const Element &element, const std::s
|
|||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AnimationCurve::~AnimationCurve() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element &element, const std::string &name,
|
||||
const Document &doc, const char *const *target_prop_whitelist /*= nullptr*/,
|
||||
|
@ -147,11 +141,6 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element &element, cons
|
|||
props = GetPropertyTable(doc, "AnimationCurveNode.FbxAnimCurveNode", element, sc, false);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AnimationCurveNode::~AnimationCurveNode() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const AnimationCurveMap &AnimationCurveNode::Curves() const {
|
||||
if (curves.empty()) {
|
||||
|
@ -193,11 +182,6 @@ AnimationLayer::AnimationLayer(uint64_t id, const Element &element, const std::s
|
|||
props = GetPropertyTable(doc, "AnimationLayer.FbxAnimLayer", element, sc, true);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AnimationLayer::~AnimationLayer() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AnimationCurveNodeList AnimationLayer::Nodes(const char *const *target_prop_whitelist /*= nullptr*/,
|
||||
size_t whitelist_size /*= 0*/) const {
|
||||
|
@ -279,11 +263,6 @@ AnimationStack::AnimationStack(uint64_t id, const Element &element, const std::s
|
|||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AnimationStack::~AnimationStack() {
|
||||
// empty
|
||||
}
|
||||
|
||||
} // namespace FBX
|
||||
} // namespace Assimp
|
||||
|
||||
|
|
|
@ -50,7 +50,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace Assimp {
|
||||
namespace FBX {
|
||||
|
||||
const std::string NULL_RECORD = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit
|
||||
static constexpr size_t NumNullRecords = 25;
|
||||
const char NULL_RECORD[NumNullRecords] = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
|
||||
}; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?)
|
||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
|||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
|
|
@ -65,12 +65,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <stdlib.h>
|
||||
#include <cstdint>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
namespace Assimp {
|
||||
namespace FBX {
|
||||
|
@ -187,8 +184,7 @@ std::string FBXConverter::MakeUniqueNodeName(const Model *const model, const aiN
|
|||
|
||||
/// This struct manages nodes which may or may not end up in the node hierarchy.
|
||||
/// When a node becomes a child of another node, that node becomes its owner and mOwnership should be released.
|
||||
struct FBXConverter::PotentialNode
|
||||
{
|
||||
struct FBXConverter::PotentialNode {
|
||||
PotentialNode() : mOwnership(new aiNode), mNode(mOwnership.get()) {}
|
||||
PotentialNode(const std::string& name) : mOwnership(new aiNode(name)), mNode(mOwnership.get()) {}
|
||||
aiNode* operator->() { return mNode; }
|
||||
|
@ -231,7 +227,7 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
|
|||
if (nullptr != model) {
|
||||
nodes_chain.clear();
|
||||
post_nodes_chain.clear();
|
||||
|
||||
aiMatrix4x4 new_abs_transform = parent->mTransformation;
|
||||
std::string node_name = FixNodeName(model->Name());
|
||||
// even though there is only a single input node, the design of
|
||||
// assimp (or rather: the complicated transformation chain that
|
||||
|
@ -268,7 +264,7 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
|
|||
}
|
||||
|
||||
// attach geometry
|
||||
ConvertModel(*model, nodes_chain.back().mNode, root_node);
|
||||
ConvertModel(*model, nodes_chain.back().mNode, root_node, new_abs_transform);
|
||||
|
||||
// check if there will be any child nodes
|
||||
const std::vector<const Connection *> &child_conns = doc.GetConnectionsByDestinationSequenced(model->ID(), "Model");
|
||||
|
@ -447,7 +443,7 @@ void FBXConverter::GetUniqueName(const std::string &name, std::string &uniqueNam
|
|||
auto it_pair = mNodeNames.insert({ name, 0 }); // duplicate node name instance count
|
||||
unsigned int &i = it_pair.first->second;
|
||||
while (!it_pair.second) {
|
||||
i++;
|
||||
++i;
|
||||
std::ostringstream ext;
|
||||
ext << name << std::setfill('0') << std::setw(3) << i;
|
||||
uniqueName = ext.str();
|
||||
|
@ -646,9 +642,8 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot
|
|||
|
||||
bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
|
||||
const PropertyTable &props = model.Props();
|
||||
bool ok;
|
||||
|
||||
const float zero_epsilon = ai_epsilon;
|
||||
const auto zero_epsilon = ai_epsilon;
|
||||
const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
|
||||
for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
|
||||
const TransformationComp comp = static_cast<TransformationComp>(i);
|
||||
|
@ -660,6 +655,7 @@ bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
|
|||
|
||||
bool scale_compare = (comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling);
|
||||
|
||||
bool ok = true;
|
||||
const aiVector3D &v = PropertyGet<aiVector3D>(props, NameTransformationCompProperty(comp), ok);
|
||||
if (ok && scale_compare) {
|
||||
if ((v - all_ones).SquareLength() > zero_epsilon) {
|
||||
|
@ -894,18 +890,17 @@ void FBXConverter::SetupNodeMetadata(const Model &model, aiNode &nd) {
|
|||
}
|
||||
}
|
||||
|
||||
void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root_node) {
|
||||
void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform) {
|
||||
const std::vector<const Geometry *> &geos = model.GetGeometry();
|
||||
|
||||
std::vector<unsigned int> meshes;
|
||||
meshes.reserve(geos.size());
|
||||
|
||||
for (const Geometry *geo : geos) {
|
||||
|
||||
const MeshGeometry *const mesh = dynamic_cast<const MeshGeometry *>(geo);
|
||||
const LineGeometry *const line = dynamic_cast<const LineGeometry *>(geo);
|
||||
if (mesh) {
|
||||
const std::vector<unsigned int> &indices = ConvertMesh(*mesh, model, parent, root_node);
|
||||
const std::vector<unsigned int> &indices = ConvertMesh(*mesh, model, parent, root_node, absolute_transform);
|
||||
std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
|
||||
} else if (line) {
|
||||
const std::vector<unsigned int> &indices = ConvertLine(*line, root_node);
|
||||
|
@ -926,7 +921,7 @@ void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root
|
|||
}
|
||||
|
||||
std::vector<unsigned int>
|
||||
FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node) {
|
||||
FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform) {
|
||||
std::vector<unsigned int> temp;
|
||||
|
||||
MeshMap::const_iterator it = meshes_converted.find(&mesh);
|
||||
|
@ -949,13 +944,13 @@ FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *
|
|||
const MatIndexArray::value_type base = mindices[0];
|
||||
for (MatIndexArray::value_type index : mindices) {
|
||||
if (index != base) {
|
||||
return ConvertMeshMultiMaterial(mesh, model, parent, root_node);
|
||||
return ConvertMeshMultiMaterial(mesh, model, absolute_transform, parent, root_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// faster code-path, just copy the data
|
||||
temp.push_back(ConvertMeshSingleMaterial(mesh, model, parent, root_node));
|
||||
temp.push_back(ConvertMeshSingleMaterial(mesh, model, absolute_transform, parent, root_node));
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
@ -1023,7 +1018,35 @@ aiMesh *FBXConverter::SetupEmptyMesh(const Geometry &mesh, aiNode *parent) {
|
|||
return out_mesh;
|
||||
}
|
||||
|
||||
unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model,
|
||||
static aiSkeleton *createAiSkeleton(SkeletonBoneContainer &sbc) {
|
||||
if (sbc.MeshArray.empty() || sbc.SkeletonBoneToMeshLookup.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
aiSkeleton *skeleton = new aiSkeleton;
|
||||
for (auto *mesh : sbc.MeshArray) {
|
||||
auto it = sbc.SkeletonBoneToMeshLookup.find(mesh);
|
||||
if (it == sbc.SkeletonBoneToMeshLookup.end()) {
|
||||
continue;
|
||||
}
|
||||
SkeletonBoneArray *ba = it->second;
|
||||
if (ba == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
skeleton->mNumBones = static_cast<unsigned int>(ba->size());
|
||||
skeleton->mBones = new aiSkeletonBone*[skeleton->mNumBones];
|
||||
size_t index = 0;
|
||||
for (auto bone : (* ba)) {
|
||||
skeleton->mBones[index] = bone;
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
return skeleton;
|
||||
}
|
||||
|
||||
unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform,
|
||||
aiNode *parent, aiNode *) {
|
||||
const MatIndexArray &mindices = mesh.GetMaterialIndices();
|
||||
aiMesh *const out_mesh = SetupEmptyMesh(mesh, parent);
|
||||
|
@ -1142,8 +1165,15 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
|
|||
ConvertMaterialForMesh(out_mesh, model, mesh, mindices[0]);
|
||||
}
|
||||
|
||||
if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr) {
|
||||
ConvertWeights(out_mesh, mesh, parent, NO_MATERIAL_SEPARATION, nullptr);
|
||||
if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr && !doc.Settings().useSkeleton) {
|
||||
ConvertWeights(out_mesh, mesh, absolute_transform, parent, NO_MATERIAL_SEPARATION, nullptr);
|
||||
} else if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr && doc.Settings().useSkeleton) {
|
||||
SkeletonBoneContainer sbc;
|
||||
ConvertWeightsToSkeleton(out_mesh, mesh, absolute_transform, parent, NO_MATERIAL_SEPARATION, nullptr, sbc);
|
||||
aiSkeleton *skeleton = createAiSkeleton(sbc);
|
||||
if (skeleton != nullptr) {
|
||||
mSkeletons.emplace_back(skeleton);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<aiAnimMesh *> animMeshes;
|
||||
|
@ -1190,7 +1220,7 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
|
|||
}
|
||||
|
||||
std::vector<unsigned int>
|
||||
FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent,
|
||||
FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform, aiNode *parent,
|
||||
aiNode *root_node) {
|
||||
const MatIndexArray &mindices = mesh.GetMaterialIndices();
|
||||
ai_assert(mindices.size());
|
||||
|
@ -1201,7 +1231,7 @@ FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &mo
|
|||
for (MatIndexArray::value_type index : mindices) {
|
||||
if (had.find(index) == had.end()) {
|
||||
|
||||
indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, parent, root_node));
|
||||
indices.push_back(ConvertMeshMultiMaterial(mesh, model, absolute_transform, index, parent, root_node));
|
||||
had.insert(index);
|
||||
}
|
||||
}
|
||||
|
@ -1209,9 +1239,8 @@ FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &mo
|
|||
return indices;
|
||||
}
|
||||
|
||||
unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model,
|
||||
MatIndexArray::value_type index,
|
||||
aiNode *parent, aiNode *) {
|
||||
unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform,
|
||||
MatIndexArray::value_type index, aiNode *parent, aiNode *) {
|
||||
aiMesh *const out_mesh = SetupEmptyMesh(mesh, parent);
|
||||
|
||||
const MatIndexArray &mindices = mesh.GetMaterialIndices();
|
||||
|
@ -1374,7 +1403,7 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
|
|||
ConvertMaterialForMesh(out_mesh, model, mesh, index);
|
||||
|
||||
if (process_weights) {
|
||||
ConvertWeights(out_mesh, mesh, parent, index, &reverseMapping);
|
||||
ConvertWeights(out_mesh, mesh, absolute_transform, parent, index, &reverseMapping);
|
||||
}
|
||||
|
||||
std::vector<aiAnimMesh *> animMeshes;
|
||||
|
@ -1424,19 +1453,47 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
|
|||
return static_cast<unsigned int>(mMeshes.size() - 1);
|
||||
}
|
||||
|
||||
void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo,
|
||||
static void copyBoneToSkeletonBone(aiMesh *mesh, aiBone *bone, aiSkeletonBone *skeletonBone ) {
|
||||
skeletonBone->mNumnWeights = bone->mNumWeights;
|
||||
skeletonBone->mWeights = bone->mWeights;
|
||||
skeletonBone->mOffsetMatrix = bone->mOffsetMatrix;
|
||||
skeletonBone->mMeshId = mesh;
|
||||
skeletonBone->mNode = bone->mNode;
|
||||
skeletonBone->mParent = -1;
|
||||
}
|
||||
|
||||
void FBXConverter::ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, aiNode *parent, unsigned int materialIndex,
|
||||
std::vector<unsigned int> *outputVertStartIndices, SkeletonBoneContainer &skeletonContainer) {
|
||||
|
||||
if (skeletonContainer.SkeletonBoneToMeshLookup.find(out) != skeletonContainer.SkeletonBoneToMeshLookup.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConvertWeights(out, geo, absolute_transform, parent, materialIndex, outputVertStartIndices);
|
||||
skeletonContainer.MeshArray.emplace_back(out);
|
||||
SkeletonBoneArray *ba = new SkeletonBoneArray;
|
||||
for (size_t i = 0; i < out->mNumBones; ++i) {
|
||||
aiBone *bone = out->mBones[i];
|
||||
if (bone == nullptr) {
|
||||
continue;
|
||||
}
|
||||
aiSkeletonBone *skeletonBone = new aiSkeletonBone;
|
||||
copyBoneToSkeletonBone(out, bone, skeletonBone);
|
||||
ba->emplace_back(skeletonBone);
|
||||
}
|
||||
skeletonContainer.SkeletonBoneToMeshLookup[out] = ba;
|
||||
}
|
||||
|
||||
void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
|
||||
aiNode *parent, unsigned int materialIndex,
|
||||
std::vector<unsigned int> *outputVertStartIndices) {
|
||||
ai_assert(geo.DeformerSkin());
|
||||
|
||||
std::vector<size_t> out_indices;
|
||||
std::vector<size_t> index_out_indices;
|
||||
std::vector<size_t> count_out_indices;
|
||||
std::vector<size_t> out_indices, index_out_indices, count_out_indices;
|
||||
|
||||
const Skin &sk = *geo.DeformerSkin();
|
||||
|
||||
std::vector<aiBone *> bones;
|
||||
|
||||
std::vector<aiBone*> bones;
|
||||
const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION;
|
||||
ai_assert(no_mat_check || outputVertStartIndices);
|
||||
|
||||
|
@ -1496,7 +1553,7 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo,
|
|||
// XXX this could be heavily simplified by collecting the bone
|
||||
// data in a single step.
|
||||
ConvertCluster(bones, cluster, out_indices, index_out_indices,
|
||||
count_out_indices, parent);
|
||||
count_out_indices, absolute_transform, parent);
|
||||
}
|
||||
|
||||
bone_map.clear();
|
||||
|
@ -1509,25 +1566,20 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo,
|
|||
out->mBones = nullptr;
|
||||
out->mNumBones = 0;
|
||||
return;
|
||||
} else {
|
||||
out->mBones = new aiBone *[bones.size()]();
|
||||
out->mNumBones = static_cast<unsigned int>(bones.size());
|
||||
}
|
||||
|
||||
std::swap_ranges(bones.begin(), bones.end(), out->mBones);
|
||||
}
|
||||
out->mBones = new aiBone *[bones.size()]();
|
||||
out->mNumBones = static_cast<unsigned int>(bones.size());
|
||||
std::swap_ranges(bones.begin(), bones.end(), out->mBones);
|
||||
}
|
||||
|
||||
const aiNode *GetNodeByName(aiNode *current_node) {
|
||||
aiNode *iter = current_node;
|
||||
//printf("Child count: %d", iter->mNumChildren);
|
||||
return iter;
|
||||
}
|
||||
|
||||
void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
|
||||
void FBXConverter::ConvertCluster(std::vector<aiBone*> &local_mesh_bones, const Cluster *cluster,
|
||||
std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
|
||||
std::vector<size_t> &count_out_indices, aiNode *) {
|
||||
ai_assert(cl); // make sure cluster valid
|
||||
std::string deformer_name = cl->TargetNode()->Name();
|
||||
std::vector<size_t> &count_out_indices, const aiMatrix4x4 & /* absolute_transform*/,
|
||||
aiNode *) {
|
||||
ai_assert(cluster != nullptr); // make sure cluster valid
|
||||
|
||||
std::string deformer_name = cluster->TargetNode()->Name();
|
||||
aiString bone_name = aiString(FixNodeName(deformer_name));
|
||||
|
||||
aiBone *bone = nullptr;
|
||||
|
@ -1540,10 +1592,10 @@ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const
|
|||
bone = new aiBone();
|
||||
bone->mName = bone_name;
|
||||
|
||||
bone->mOffsetMatrix = cl->Transform();
|
||||
bone->mOffsetMatrix = cluster->Transform();
|
||||
// store local transform link for post processing
|
||||
/*
|
||||
bone->mOffsetMatrix = cl->TransformLink();
|
||||
bone->mOffsetMatrix = cluster->TransformLink();
|
||||
bone->mOffsetMatrix.Inverse();
|
||||
|
||||
aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform;
|
||||
|
@ -1560,7 +1612,7 @@ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const
|
|||
cursor = bone->mWeights = new aiVertexWeight[out_indices.size()];
|
||||
|
||||
const size_t no_index_sentinel = std::numeric_limits<size_t>::max();
|
||||
const WeightArray &weights = cl->GetWeights();
|
||||
const WeightArray &weights = cluster->GetWeights();
|
||||
|
||||
const size_t c = index_out_indices.size();
|
||||
for (size_t i = 0; i < c; ++i) {
|
||||
|
@ -2605,7 +2657,7 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) {
|
|||
meshMorphAnim->mNumKeys = numKeys;
|
||||
meshMorphAnim->mKeys = new aiMeshMorphKey[numKeys];
|
||||
unsigned int j = 0;
|
||||
for (auto animIt : *animData) {
|
||||
for (auto &animIt : *animData) {
|
||||
morphKeyData *keyData = animIt.second;
|
||||
unsigned int numValuesAndWeights = static_cast<unsigned int>(keyData->values.size());
|
||||
meshMorphAnim->mKeys[j].mNumValuesAndWeights = numValuesAndWeights;
|
||||
|
@ -3180,7 +3232,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
|
|||
|
||||
bool ok = false;
|
||||
|
||||
const float zero_epsilon = ai_epsilon;
|
||||
const auto zero_epsilon = ai_epsilon;
|
||||
|
||||
const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
|
||||
if (ok && preRotation.SquareLength() > zero_epsilon) {
|
||||
|
@ -3325,6 +3377,10 @@ FBXConverter::KeyFrameListList FBXConverter::GetRotationKeyframeList(const std::
|
|||
Keys->push_back(tnew);
|
||||
Values->push_back(vnew);
|
||||
}
|
||||
else {
|
||||
// Something broke
|
||||
break;
|
||||
}
|
||||
tp = tnew;
|
||||
vp = vnew;
|
||||
}
|
||||
|
@ -3625,6 +3681,12 @@ void FBXConverter::TransferDataToScene() {
|
|||
|
||||
std::swap_ranges(textures.begin(), textures.end(), mSceneOut->mTextures);
|
||||
}
|
||||
|
||||
if (!mSkeletons.empty()) {
|
||||
mSceneOut->mSkeletons = new aiSkeleton *[mSkeletons.size()];
|
||||
mSceneOut->mNumSkeletons = static_cast<unsigned int>(mSkeletons.size());
|
||||
std::swap_ranges(mSkeletons.begin(), mSkeletons.end(), mSceneOut->mSkeletons);
|
||||
}
|
||||
}
|
||||
|
||||
void FBXConverter::ConvertOrphanedEmbeddedTextures() {
|
||||
|
|
|
@ -75,7 +75,18 @@ typedef std::map<int64_t, morphKeyData*> morphAnimData;
|
|||
namespace Assimp {
|
||||
namespace FBX {
|
||||
|
||||
class MeshGeometry;
|
||||
|
||||
using SkeletonBoneArray = std::vector<aiSkeletonBone *>;
|
||||
using SkeletonBoneToMesh = std::map<aiMesh*, SkeletonBoneArray*>;
|
||||
|
||||
struct SkeletonBoneContainer {
|
||||
std::vector<aiMesh *> MeshArray;
|
||||
SkeletonBoneToMesh SkeletonBoneToMeshLookup;
|
||||
};
|
||||
|
||||
class Document;
|
||||
|
||||
/**
|
||||
* Convert a FBX #Document to #aiScene
|
||||
* @param out Empty scene to be populated
|
||||
|
@ -180,12 +191,12 @@ private:
|
|||
void SetupNodeMetadata(const Model& model, aiNode& nd);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConvertModel(const Model &model, aiNode *parent, aiNode *root_node);
|
||||
void ConvertModel(const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
|
||||
std::vector<unsigned int>
|
||||
ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node);
|
||||
ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::vector<unsigned int> ConvertLine(const LineGeometry& line, aiNode *root_node);
|
||||
|
@ -194,15 +205,15 @@ private:
|
|||
aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode *parent);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
unsigned int ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model,
|
||||
unsigned int ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform,
|
||||
aiNode *parent, aiNode *root_node);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::vector<unsigned int>
|
||||
ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node);
|
||||
ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform, aiNode *parent, aiNode *root_node);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
unsigned int ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, MatIndexArray::value_type index,
|
||||
unsigned int ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform, MatIndexArray::value_type index,
|
||||
aiNode *parent, aiNode *root_node);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -216,14 +227,19 @@ private:
|
|||
* - outputVertStartIndices is only used when a material index is specified, it gives for
|
||||
* each output vertex the DOM index it maps to.
|
||||
*/
|
||||
void ConvertWeights(aiMesh *out, const MeshGeometry &geo, aiNode *parent = nullptr,
|
||||
void ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, aiNode *parent = nullptr,
|
||||
unsigned int materialIndex = NO_MATERIAL_SEPARATION,
|
||||
std::vector<unsigned int> *outputVertStartIndices = nullptr);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
|
||||
aiNode *parent, unsigned int materialIndex, std::vector<unsigned int> *outputVertStartIndices,
|
||||
SkeletonBoneContainer &skeletonContainer);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
|
||||
std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
|
||||
std::vector<size_t> &count_out_indices, aiNode *parent );
|
||||
std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform, aiNode *parent);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
|
||||
|
@ -296,7 +312,8 @@ private:
|
|||
void ConvertAnimationStack(const AnimationStack& st);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ProcessMorphAnimDatas(std::map<std::string, morphAnimData*>* morphAnimDatas, const BlendShapeChannel* bsc, const AnimationCurveNode* node);
|
||||
void ProcessMorphAnimDatas(std::map<std::string, morphAnimData*>* morphAnimDatas,
|
||||
const BlendShapeChannel* bsc, const AnimationCurveNode* node);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void GenerateNodeAnimations(std::vector<aiNodeAnim*>& node_anims,
|
||||
|
@ -445,6 +462,7 @@ private:
|
|||
|
||||
double anim_fps;
|
||||
|
||||
std::vector<aiSkeleton *> mSkeletons;
|
||||
aiScene* const mSceneOut;
|
||||
const FBX::Document& doc;
|
||||
bool mRemoveEmptyBones;
|
||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
|||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
@ -58,16 +57,14 @@ namespace FBX {
|
|||
using namespace Util;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Deformer::Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
||||
: Object(id,element,name)
|
||||
{
|
||||
Deformer::Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
|
||||
Object(id,element,name) {
|
||||
const Scope& sc = GetRequiredScope(element);
|
||||
|
||||
const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
|
||||
props = GetPropertyTable(doc,"Deformer.Fbx" + classname,element,sc,true);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Deformer::~Deformer()
|
||||
{
|
||||
|
|
|
@ -67,7 +67,7 @@ namespace FBX {
|
|||
using namespace Util;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc) :
|
||||
LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc) :
|
||||
doc(doc), element(element), id(id), flags() {
|
||||
// empty
|
||||
}
|
||||
|
@ -544,7 +544,7 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
|
|||
ai_assert( count != 0 );
|
||||
ai_assert( count <= MAX_CLASSNAMES);
|
||||
|
||||
size_t lengths[MAX_CLASSNAMES];
|
||||
size_t lengths[MAX_CLASSNAMES] = {};
|
||||
|
||||
const size_t c = count;
|
||||
for (size_t i = 0; i < c; ++i) {
|
||||
|
|
|
@ -164,7 +164,7 @@ class NodeAttribute : public Object {
|
|||
public:
|
||||
NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||
|
||||
virtual ~NodeAttribute();
|
||||
virtual ~NodeAttribute() = default;
|
||||
|
||||
const PropertyTable& Props() const {
|
||||
ai_assert(props.get());
|
||||
|
@ -180,7 +180,7 @@ class CameraSwitcher : public NodeAttribute {
|
|||
public:
|
||||
CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||
|
||||
virtual ~CameraSwitcher();
|
||||
virtual ~CameraSwitcher() = default;
|
||||
|
||||
int CameraID() const {
|
||||
return cameraId;
|
||||
|
@ -225,7 +225,7 @@ class Camera : public NodeAttribute {
|
|||
public:
|
||||
Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||
|
||||
virtual ~Camera();
|
||||
virtual ~Camera() = default;
|
||||
|
||||
fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0))
|
||||
fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0))
|
||||
|
@ -250,21 +250,21 @@ public:
|
|||
class Null : public NodeAttribute {
|
||||
public:
|
||||
Null(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||
virtual ~Null();
|
||||
virtual ~Null() = default;
|
||||
};
|
||||
|
||||
/** DOM base class for FBX limb node markers attached to a node */
|
||||
class LimbNode : public NodeAttribute {
|
||||
public:
|
||||
LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||
virtual ~LimbNode();
|
||||
virtual ~LimbNode() = default;
|
||||
};
|
||||
|
||||
/** DOM base class for FBX lights attached to a node */
|
||||
class Light : public NodeAttribute {
|
||||
public:
|
||||
Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||
virtual ~Light();
|
||||
virtual ~Light() = default;
|
||||
|
||||
enum Type {
|
||||
Type_Point,
|
||||
|
@ -690,7 +690,7 @@ using KeyValueList = std::vector<float>;
|
|||
class AnimationCurve : public Object {
|
||||
public:
|
||||
AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc);
|
||||
virtual ~AnimationCurve();
|
||||
virtual ~AnimationCurve() = default;
|
||||
|
||||
/** get list of keyframe positions (time).
|
||||
* Invariant: |GetKeys()| > 0 */
|
||||
|
@ -731,7 +731,7 @@ public:
|
|||
AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
|
||||
const char *const *target_prop_whitelist = nullptr, size_t whitelist_size = 0);
|
||||
|
||||
virtual ~AnimationCurveNode();
|
||||
virtual ~AnimationCurveNode() = default;
|
||||
|
||||
const PropertyTable& Props() const {
|
||||
ai_assert(props.get());
|
||||
|
@ -776,7 +776,7 @@ using AnimationCurveNodeList = std::vector<const AnimationCurveNode*>;
|
|||
class AnimationLayer : public Object {
|
||||
public:
|
||||
AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
|
||||
virtual ~AnimationLayer();
|
||||
virtual ~AnimationLayer() = default;
|
||||
|
||||
const PropertyTable& Props() const {
|
||||
ai_assert(props.get());
|
||||
|
@ -799,7 +799,7 @@ using AnimationLayerList = std::vector<const AnimationLayer*>;
|
|||
class AnimationStack : public Object {
|
||||
public:
|
||||
AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
|
||||
virtual ~AnimationStack();
|
||||
virtual ~AnimationStack() = default;
|
||||
|
||||
fbx_simple_property(LocalStart, int64_t, 0L)
|
||||
fbx_simple_property(LocalStop, int64_t, 0L)
|
||||
|
|
|
@ -59,14 +59,12 @@ namespace Util {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError.
|
||||
void DOMError(const std::string& message, const Token& token)
|
||||
{
|
||||
void DOMError(const std::string& message, const Token& token) {
|
||||
throw DeadlyImportError("FBX-DOM", Util::GetTokenText(&token), message);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DOMError(const std::string& message, const Element* element /*= nullptr*/)
|
||||
{
|
||||
void DOMError(const std::string& message, const Element* element /*= nullptr*/) {
|
||||
if(element) {
|
||||
DOMError(message,element->KeyToken());
|
||||
}
|
||||
|
@ -76,8 +74,7 @@ void DOMError(const std::string& message, const Element* element /*= nullptr*/)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// print warning, do return
|
||||
void DOMWarning(const std::string& message, const Token& token)
|
||||
{
|
||||
void DOMWarning(const std::string& message, const Token& token) {
|
||||
if(DefaultLogger::get()) {
|
||||
ASSIMP_LOG_WARN("FBX-DOM", Util::GetTokenText(&token), message);
|
||||
}
|
||||
|
|
|
@ -74,13 +74,11 @@ std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
inline
|
||||
const T* ProcessSimpleConnection(const Connection& con,
|
||||
bool is_object_property_conn,
|
||||
const char* name,
|
||||
const Element& element,
|
||||
const char** propNameOut = nullptr)
|
||||
{
|
||||
inline const T* ProcessSimpleConnection(const Connection& con,
|
||||
bool is_object_property_conn,
|
||||
const char* name,
|
||||
const Element& element,
|
||||
const char** propNameOut = nullptr) {
|
||||
if (is_object_property_conn && !con.PropertyName().length()) {
|
||||
DOMWarning("expected incoming " + std::string(name) +
|
||||
" link to be an object-object connection, ignoring",
|
||||
|
|
|
@ -255,7 +255,7 @@ void FBXExporter::WriteBinaryHeader()
|
|||
|
||||
void FBXExporter::WriteBinaryFooter()
|
||||
{
|
||||
outfile->Write(NULL_RECORD.c_str(), NULL_RECORD.size(), 1);
|
||||
outfile->Write(NULL_RECORD, NumNullRecords, 1);
|
||||
|
||||
outfile->Write(GENERIC_FOOTID.c_str(), GENERIC_FOOTID.size(), 1);
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ struct ImportSettings {
|
|||
readLights(true),
|
||||
readAnimations(true),
|
||||
readWeights(true),
|
||||
useSkeleton(false),
|
||||
preservePivots(true),
|
||||
optimizeEmptyAnimationCurves(true),
|
||||
useLegacyEmbeddedTextureNaming(false),
|
||||
|
@ -112,6 +113,11 @@ struct ImportSettings {
|
|||
* Default value is true. */
|
||||
bool readWeights;
|
||||
|
||||
/** will convert all animation data into a skeleton (experimental)
|
||||
* Default value is false.
|
||||
*/
|
||||
bool useSkeleton;
|
||||
|
||||
/** preserve transformation pivots and offsets. Since these can
|
||||
* not directly be represented in assimp, additional dummy
|
||||
* nodes will be generated. Note that settings this to false
|
||||
|
|
|
@ -90,12 +90,9 @@ static const aiImporterDesc desc = {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by #Importer
|
||||
FBXImporter::FBXImporter() {
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
FBXImporter::~FBXImporter() {
|
||||
FBXImporter::FBXImporter() :
|
||||
mSettings() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -115,20 +112,21 @@ const aiImporterDesc *FBXImporter::GetInfo() const {
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup configuration properties for the loader
|
||||
void FBXImporter::SetupProperties(const Importer *pImp) {
|
||||
settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
|
||||
settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
|
||||
settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
|
||||
settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
|
||||
settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
|
||||
settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
|
||||
settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
|
||||
settings.readWeights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_WEIGHTS, true);
|
||||
settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
|
||||
settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
|
||||
settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
|
||||
settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
|
||||
settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
|
||||
settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
|
||||
mSettings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
|
||||
mSettings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
|
||||
mSettings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
|
||||
mSettings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
|
||||
mSettings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
|
||||
mSettings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
|
||||
mSettings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
|
||||
mSettings.readWeights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_WEIGHTS, true);
|
||||
mSettings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
|
||||
mSettings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
|
||||
mSettings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
|
||||
mSettings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
|
||||
mSettings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
|
||||
mSettings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
|
||||
mSettings.useSkeleton = pImp->GetPropertyBool(AI_CONFIG_FBX_USE_SKELETON_BONE_CONTAINER, false);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -155,7 +153,7 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
|||
contents[contents.size() - 1] = 0;
|
||||
const char *const begin = &*contents.begin();
|
||||
|
||||
// broadphase tokenizing pass in which we identify the core
|
||||
// broad-phase tokenized pass in which we identify the core
|
||||
// syntax elements of FBX (brackets, commas, key:value mappings)
|
||||
TokenList tokens;
|
||||
try {
|
||||
|
@ -173,15 +171,14 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
|||
Parser parser(tokens, is_binary);
|
||||
|
||||
// take the raw parse-tree and convert it to a FBX DOM
|
||||
Document doc(parser, settings);
|
||||
Document doc(parser, mSettings);
|
||||
|
||||
// convert the FBX DOM to aiScene
|
||||
ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones);
|
||||
ConvertToAssimpScene(pScene, doc, mSettings.removeEmptyBones);
|
||||
|
||||
// size relative to cm
|
||||
float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
|
||||
if (size_relative_to_cm == 0.0)
|
||||
{
|
||||
if (size_relative_to_cm == 0.0) {
|
||||
// BaseImporter later asserts that fileScale is non-zero.
|
||||
ThrowException("The UnitScaleFactor must be non-zero");
|
||||
}
|
||||
|
|
|
@ -69,13 +69,14 @@ typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>
|
|||
// -------------------------------------------------------------------------------------------
|
||||
class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
|
||||
public:
|
||||
/// @brief The class constructor.
|
||||
FBXImporter();
|
||||
~FBXImporter() override;
|
||||
|
||||
// --------------------
|
||||
bool CanRead(const std::string &pFile,
|
||||
IOSystem *pIOHandler,
|
||||
bool checkSig) const override;
|
||||
/// @brief The class destructor, default implementation.
|
||||
~FBXImporter() override = default;
|
||||
|
||||
/// @brief Will check the file for readability.
|
||||
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
|
||||
|
||||
protected:
|
||||
// --------------------
|
||||
|
@ -90,7 +91,7 @@ protected:
|
|||
IOSystem *pIOHandler) override;
|
||||
|
||||
private:
|
||||
FBX::ImportSettings settings;
|
||||
FBX::ImportSettings mSettings;
|
||||
}; // !class FBXImporter
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
|||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
@ -54,18 +53,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "FBXImportSettings.h"
|
||||
#include "FBXDocumentUtil.h"
|
||||
|
||||
|
||||
namespace Assimp {
|
||||
namespace FBX {
|
||||
|
||||
using namespace Util;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
|
||||
: Object(id, element, name)
|
||||
, skin()
|
||||
{
|
||||
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
|
||||
Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc) :
|
||||
Object(id, element, name), skin() {
|
||||
const std::vector<const Connection*> &conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
|
||||
for(const Connection* con : conns) {
|
||||
const Skin* const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
|
||||
if(sk) {
|
||||
|
@ -78,12 +74,6 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name,
|
|||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Geometry::~Geometry()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const std::vector<const BlendShape*>& Geometry::GetBlendShapes() const {
|
||||
return blendShapes;
|
||||
|
@ -183,18 +173,12 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
|
|||
if(doc.Settings().readAllLayers || index == 0) {
|
||||
const Scope& layer = GetRequiredScope(*(*it).second);
|
||||
ReadLayer(layer);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
FBXImporter::LogWarn("ignoring additional geometry layers");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
MeshGeometry::~MeshGeometry() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const std::vector<aiVector3D>& MeshGeometry::GetVertices() const {
|
||||
return m_vertices;
|
||||
|
|
|
@ -55,22 +55,25 @@ namespace FBX {
|
|||
/**
|
||||
* DOM base class for all kinds of FBX geometry
|
||||
*/
|
||||
class Geometry : public Object
|
||||
{
|
||||
class Geometry : public Object {
|
||||
public:
|
||||
/// @brief The class constructor with all parameters.
|
||||
/// @param id The id.
|
||||
/// @param element
|
||||
/// @param name
|
||||
/// @param doc
|
||||
Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
|
||||
virtual ~Geometry();
|
||||
virtual ~Geometry() = default;
|
||||
|
||||
/** Get the Skin attached to this geometry or nullptr */
|
||||
/// Get the Skin attached to this geometry or nullptr
|
||||
const Skin* DeformerSkin() const;
|
||||
|
||||
/** Get the BlendShape attached to this geometry or nullptr */
|
||||
/// Get the BlendShape attached to this geometry or nullptr
|
||||
const std::vector<const BlendShape*>& GetBlendShapes() const;
|
||||
|
||||
private:
|
||||
const Skin* skin;
|
||||
std::vector<const BlendShape*> blendShapes;
|
||||
|
||||
};
|
||||
|
||||
typedef std::vector<int> MatIndexArray;
|
||||
|
@ -79,14 +82,13 @@ typedef std::vector<int> MatIndexArray;
|
|||
/**
|
||||
* DOM class for FBX geometry of type "Mesh"
|
||||
*/
|
||||
class MeshGeometry : public Geometry
|
||||
{
|
||||
class MeshGeometry : public Geometry {
|
||||
public:
|
||||
/** The class constructor */
|
||||
MeshGeometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
|
||||
|
||||
/** The class destructor */
|
||||
virtual ~MeshGeometry();
|
||||
virtual ~MeshGeometry() = default;
|
||||
|
||||
/** Get a list of all vertex points, non-unique*/
|
||||
const std::vector<aiVector3D>& GetVertices() const;
|
||||
|
@ -130,6 +132,7 @@ public:
|
|||
/** Determine the face to which a particular output vertex index belongs.
|
||||
* This mapping is always unique. */
|
||||
unsigned int FaceForVertexIndex( unsigned int in_index ) const;
|
||||
|
||||
private:
|
||||
void ReadLayer( const Scope& layer );
|
||||
void ReadLayerElement( const Scope& layerElement );
|
||||
|
|
|
@ -57,114 +57,65 @@ namespace FBX {
|
|||
using namespace Util;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
||||
: Object(id,element,name)
|
||||
, props()
|
||||
{
|
||||
const Scope& sc = GetRequiredScope(element);
|
||||
NodeAttribute::NodeAttribute(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
|
||||
Object(id, element, name), props() {
|
||||
const Scope &sc = GetRequiredScope(element);
|
||||
|
||||
const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
|
||||
const std::string &classname = ParseTokenAsString(GetRequiredToken(element, 2));
|
||||
|
||||
// hack on the deriving type but Null/LimbNode attributes are the only case in which
|
||||
// the property table is by design absent and no warning should be generated
|
||||
// for it.
|
||||
const bool is_null_or_limb = !strcmp(classname.c_str(), "Null") || !strcmp(classname.c_str(), "LimbNode");
|
||||
props = GetPropertyTable(doc,"NodeAttribute.Fbx" + classname,element,sc, is_null_or_limb);
|
||||
props = GetPropertyTable(doc, "NodeAttribute.Fbx" + classname, element, sc, is_null_or_limb);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
NodeAttribute::~NodeAttribute()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
CameraSwitcher::CameraSwitcher(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
|
||||
NodeAttribute(id, element, doc, name) {
|
||||
const Scope &sc = GetRequiredScope(element);
|
||||
const Element *const CameraId = sc["CameraId"];
|
||||
const Element *const CameraName = sc["CameraName"];
|
||||
const Element *const CameraIndexName = sc["CameraIndexName"];
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CameraSwitcher::CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
||||
: NodeAttribute(id,element,doc,name)
|
||||
{
|
||||
const Scope& sc = GetRequiredScope(element);
|
||||
const Element* const CameraId = sc["CameraId"];
|
||||
const Element* const CameraName = sc["CameraName"];
|
||||
const Element* const CameraIndexName = sc["CameraIndexName"];
|
||||
|
||||
if(CameraId) {
|
||||
cameraId = ParseTokenAsInt(GetRequiredToken(*CameraId,0));
|
||||
if (CameraId) {
|
||||
cameraId = ParseTokenAsInt(GetRequiredToken(*CameraId, 0));
|
||||
}
|
||||
|
||||
if(CameraName) {
|
||||
cameraName = GetRequiredToken(*CameraName,0).StringContents();
|
||||
if (CameraName) {
|
||||
cameraName = GetRequiredToken(*CameraName, 0).StringContents();
|
||||
}
|
||||
|
||||
if(CameraIndexName && CameraIndexName->Tokens().size()) {
|
||||
cameraIndexName = GetRequiredToken(*CameraIndexName,0).StringContents();
|
||||
if (CameraIndexName && CameraIndexName->Tokens().size()) {
|
||||
cameraIndexName = GetRequiredToken(*CameraIndexName, 0).StringContents();
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CameraSwitcher::~CameraSwitcher()
|
||||
{
|
||||
Camera::Camera(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
|
||||
NodeAttribute(id, element, doc, name) {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Camera::Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
||||
: NodeAttribute(id,element,doc,name)
|
||||
{
|
||||
Light::Light(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
|
||||
NodeAttribute(id, element, doc, name) {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Camera::~Camera()
|
||||
{
|
||||
Null::Null(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
|
||||
NodeAttribute(id, element, doc, name) {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Light::Light(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
||||
: NodeAttribute(id,element,doc,name)
|
||||
{
|
||||
LimbNode::LimbNode(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
|
||||
NodeAttribute(id, element, doc, name) {
|
||||
// empty
|
||||
}
|
||||
|
||||
} // namespace FBX
|
||||
} // namespace Assimp
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Light::~Light()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Null::Null(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
||||
: NodeAttribute(id,element,doc,name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Null::~Null()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LimbNode::LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
||||
: NodeAttribute(id,element,doc,name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LimbNode::~LimbNode()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // ASSIMP_BUILD_NO_FBX_IMPORTER
|
||||
|
|
|
@ -162,12 +162,6 @@ Element::Element(const Token& key_token, Parser& parser) : key_token(key_token)
|
|||
while(n->Type() != TokenType_KEY && n->Type() != TokenType_CLOSE_BRACKET);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Element::~Element()
|
||||
{
|
||||
// no need to delete tokens, they are owned by the parser
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Scope::Scope(Parser& parser,bool topLevel)
|
||||
{
|
||||
|
@ -226,12 +220,6 @@ Parser::Parser (const TokenList& tokens, bool is_binary)
|
|||
root.reset(new Scope(*this,true));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Parser::~Parser()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
TokenPtr Parser::AdvanceToNextToken()
|
||||
{
|
||||
|
@ -961,8 +949,7 @@ void ParseVectorDataArray(std::vector<float>& out, const Element& el)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// read an array of uints
|
||||
void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
|
||||
{
|
||||
void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el) {
|
||||
out.resize( 0 );
|
||||
const TokenList& tok = el.Tokens();
|
||||
if(tok.empty()) {
|
||||
|
@ -1186,7 +1173,6 @@ aiMatrix4x4 ReadMatrix(const Element& element)
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// wrapper around ParseTokenAsString() with ParseError handling
|
||||
std::string ParseTokenAsString(const Token& t)
|
||||
|
|
|
@ -87,7 +87,7 @@ class Element
|
|||
{
|
||||
public:
|
||||
Element(const Token& key_token, Parser& parser);
|
||||
~Element();
|
||||
~Element() = default;
|
||||
|
||||
const Scope* Compound() const {
|
||||
return compound.get();
|
||||
|
@ -160,7 +160,7 @@ public:
|
|||
/** Parse given a token list. Does not take ownership of the tokens -
|
||||
* the objects must persist during the entire parser lifetime */
|
||||
Parser (const TokenList& tokens,bool is_binary);
|
||||
~Parser();
|
||||
~Parser() = default;
|
||||
|
||||
const Scope& GetRootScope() const {
|
||||
return *root.get();
|
||||
|
|
|
@ -874,7 +874,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
|||
|
||||
// Batch loader used to load external models
|
||||
BatchLoader batch(pIOHandler);
|
||||
// batch.SetBasePath(pFile);
|
||||
//batch.SetBasePath(pFile);
|
||||
|
||||
cameras.reserve(5);
|
||||
lights.reserve(5);
|
||||
|
|
|
@ -287,7 +287,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
|
|||
if (UINT_MAX == iDefaultSurface) {
|
||||
pSorted.erase(pSorted.end() - 1);
|
||||
}
|
||||
for (unsigned int p = 0, j = 0; j < mSurfaces->size(); ++j) {
|
||||
for (unsigned int j = 0; j < mSurfaces->size(); ++j) {
|
||||
SortedRep &sorted = pSorted[j];
|
||||
if (sorted.empty())
|
||||
continue;
|
||||
|
@ -425,7 +425,6 @@ void LWOImporter::InternReadFile(const std::string &pFile,
|
|||
} else {
|
||||
ASSIMP_LOG_VERBOSE_DEBUG("LWO2: No need to compute normals, they're already there");
|
||||
}
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -449,6 +449,9 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
|
|||
unsigned int iWidth,
|
||||
unsigned int iHeight) {
|
||||
std::unique_ptr<aiTexture> pcNew;
|
||||
if (szCurrent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get the type of the skin
|
||||
unsigned int iMasked = (unsigned int)(iType & 0xF);
|
||||
|
|
|
@ -151,45 +151,46 @@ namespace Grammar {
|
|||
}
|
||||
|
||||
static TokenType matchTokenType(const char *tokenType) {
|
||||
if (MetricType == tokenType) {
|
||||
const size_t len = std::strlen(tokenType);
|
||||
if (0 == strncmp(MetricType, tokenType, len)) {
|
||||
return MetricToken;
|
||||
} else if (NameType == tokenType) {
|
||||
} else if (0 == strncmp(NameType, tokenType, len)) {
|
||||
return NameToken;
|
||||
} else if (ObjectRefType == tokenType) {
|
||||
} else if (0 == strncmp(ObjectRefType, tokenType, len)) {
|
||||
return ObjectRefToken;
|
||||
} else if (MaterialRefType == tokenType) {
|
||||
} else if (0 == strncmp(MaterialRefType, tokenType, len)) {
|
||||
return MaterialRefToken;
|
||||
} else if (MetricKeyType == tokenType) {
|
||||
} else if (0 == strncmp(MetricKeyType, tokenType, len)) {
|
||||
return MetricKeyToken;
|
||||
} else if (GeometryNodeType == tokenType) {
|
||||
} else if (0 == strncmp(GeometryNodeType, tokenType, len)) {
|
||||
return GeometryNodeToken;
|
||||
} else if (CameraNodeType == tokenType) {
|
||||
} else if (0 == strncmp(CameraNodeType, tokenType, len)) {
|
||||
return CameraNodeToken;
|
||||
} else if (LightNodeType == tokenType) {
|
||||
} else if (0 == strncmp(LightNodeType, tokenType, len)) {
|
||||
return LightNodeToken;
|
||||
} else if (GeometryObjectType == tokenType) {
|
||||
} else if (0 == strncmp(GeometryObjectType, tokenType, len)) {
|
||||
return GeometryObjectToken;
|
||||
} else if (CameraObjectType == tokenType) {
|
||||
} else if (0 == strncmp(CameraObjectType, tokenType, len)) {
|
||||
return CameraObjectToken;
|
||||
} else if (LightObjectType == tokenType) {
|
||||
} else if (0 == strncmp(LightObjectType, tokenType, len)) {
|
||||
return LightObjectToken;
|
||||
} else if (TransformType == tokenType) {
|
||||
} else if (0 == strncmp(TransformType, tokenType, len)) {
|
||||
return TransformToken;
|
||||
} else if (MeshType == tokenType) {
|
||||
} else if (0 == strncmp(MeshType, tokenType, len)) {
|
||||
return MeshToken;
|
||||
} else if (VertexArrayType == tokenType) {
|
||||
} else if (0 == strncmp(VertexArrayType, tokenType, len)) {
|
||||
return VertexArrayToken;
|
||||
} else if (IndexArrayType == tokenType) {
|
||||
} else if (0 == strncmp(IndexArrayType, tokenType, len)) {
|
||||
return IndexArrayToken;
|
||||
} else if (MaterialType == tokenType) {
|
||||
} else if (0 == strncmp(MaterialType, tokenType, len)) {
|
||||
return MaterialToken;
|
||||
} else if (ColorType == tokenType) {
|
||||
} else if (0 == strncmp(ColorType, tokenType, len)) {
|
||||
return ColorToken;
|
||||
} else if (ParamType == tokenType) {
|
||||
} else if (0 == strncmp(ParamType, tokenType, len)) {
|
||||
return ParamToken;
|
||||
} else if (TextureType == tokenType) {
|
||||
} else if (0 == strncmp(TextureType, tokenType, len)) {
|
||||
return TextureToken;
|
||||
} else if (AttenType == tokenType) {
|
||||
} else if (0 == strncmp(AttenType, tokenType, len)) {
|
||||
return AttenToken;
|
||||
}
|
||||
|
||||
|
@ -256,11 +257,6 @@ OpenGEXImporter::RefInfo::RefInfo(aiNode *node, Type type, std::vector<std::stri
|
|||
// empty
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
OpenGEXImporter::RefInfo::~RefInfo() {
|
||||
// empty
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
OpenGEXImporter::OpenGEXImporter() :
|
||||
m_root(nullptr),
|
||||
|
@ -285,10 +281,6 @@ OpenGEXImporter::OpenGEXImporter() :
|
|||
// empty
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
OpenGEXImporter::~OpenGEXImporter() {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
bool OpenGEXImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool /*checkSig*/) const {
|
||||
static const char *tokens[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" };
|
||||
|
|
|
@ -79,12 +79,7 @@ struct MetricInfo {
|
|||
float m_floatValue;
|
||||
int m_intValue;
|
||||
|
||||
MetricInfo()
|
||||
: m_stringValue( )
|
||||
, m_floatValue( 0.0f )
|
||||
, m_intValue( -1 ) {
|
||||
// empty
|
||||
}
|
||||
MetricInfo(): m_stringValue( ), m_floatValue( 0.0f ), m_intValue( -1 ) {}
|
||||
};
|
||||
|
||||
/** @brief This class is used to implement the OpenGEX importer
|
||||
|
@ -97,7 +92,7 @@ public:
|
|||
OpenGEXImporter();
|
||||
|
||||
/// The class destructor.
|
||||
~OpenGEXImporter() override;
|
||||
~OpenGEXImporter() override = default;
|
||||
|
||||
/// BaseImporter override.
|
||||
bool CanRead( const std::string &file, IOSystem *pIOHandler, bool checkSig ) const override;
|
||||
|
@ -170,7 +165,7 @@ private:
|
|||
std::vector<std::string> m_Names;
|
||||
|
||||
RefInfo( aiNode *node, Type type, std::vector<std::string> &names );
|
||||
~RefInfo();
|
||||
~RefInfo() = default;
|
||||
|
||||
RefInfo( const RefInfo & ) = delete;
|
||||
RefInfo &operator = ( const RefInfo & ) = delete;
|
||||
|
|
|
@ -683,7 +683,7 @@ bool glTF2Exporter::GetMatSheen(const aiMaterial &mat, glTF2::MaterialSheen &she
|
|||
}
|
||||
|
||||
// Default Sheen color factor {0,0,0} disables Sheen, so do not export
|
||||
if (sheen.sheenColorFactor == defaultSheenFactor) {
|
||||
if (sheen.sheenColorFactor[0] == defaultSheenFactor[0] && sheen.sheenColorFactor[1] == defaultSheenFactor[1] && sheen.sheenColorFactor[2] == defaultSheenFactor[2]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -908,7 +908,7 @@ Ref<Node> FindSkeletonRootJoint(Ref<Skin> &skinRef) {
|
|||
do {
|
||||
startNodeRef = parentNodeRef;
|
||||
parentNodeRef = startNodeRef->parent;
|
||||
} while (!parentNodeRef->jointName.empty());
|
||||
} while (parentNodeRef && !parentNodeRef->jointName.empty());
|
||||
|
||||
return parentNodeRef;
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ inline int select_fseek(FILE *file, int64_t offset, int origin) {
|
|||
|
||||
|
||||
|
||||
#if defined _WIN64 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601)
|
||||
#if defined _WIN32 && (!defined __GNUC__ || !defined __CLANG__ && __MSVCRT_VERSION__ >= 0x0601)
|
||||
template <>
|
||||
inline size_t select_ftell<8>(FILE *file) {
|
||||
return (size_t)::_ftelli64(file);
|
||||
|
@ -74,7 +74,7 @@ inline int select_fseek<8>(FILE *file, int64_t offset, int origin) {
|
|||
return ::_fseeki64(file, offset, origin);
|
||||
}
|
||||
|
||||
#endif // #if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601)
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
|
@ -149,13 +149,20 @@ size_t DefaultIOStream::FileSize() const {
|
|||
//
|
||||
// See here for details:
|
||||
// https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file
|
||||
#if defined _WIN64 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601)
|
||||
#if defined _WIN32 && (!defined __GNUC__ || !defined __CLANG__ && __MSVCRT_VERSION__ >= 0x0601)
|
||||
struct __stat64 fileStat;
|
||||
//using fileno + fstat avoids having to handle the filename
|
||||
int err = _fstat64(_fileno(mFile), &fileStat);
|
||||
if (0 != err)
|
||||
return 0;
|
||||
mCachedSize = (size_t)(fileStat.st_size);
|
||||
#elif defined _WIN32
|
||||
struct _stat32 fileStat;
|
||||
//using fileno + fstat avoids having to handle the filename
|
||||
int err = _fstat32(_fileno(mFile), &fileStat);
|
||||
if (0 != err)
|
||||
return 0;
|
||||
mCachedSize = (size_t)(fileStat.st_size);
|
||||
#elif defined __GNUC__ || defined __APPLE__ || defined __MACH__ || defined __FreeBSD__
|
||||
struct stat fileStat;
|
||||
int err = stat(mFilename.c_str(), &fileStat);
|
||||
|
|
|
@ -105,36 +105,39 @@ void ScenePreprocessor::ProcessMesh(aiMesh *mesh) {
|
|||
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
|
||||
if (!mesh->mTextureCoords[i]) {
|
||||
mesh->mNumUVComponents[i] = 0;
|
||||
} else {
|
||||
if (!mesh->mNumUVComponents[i]) {
|
||||
mesh->mNumUVComponents[i] = 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!mesh->mNumUVComponents[i]) {
|
||||
mesh->mNumUVComponents[i] = 2;
|
||||
}
|
||||
|
||||
aiVector3D *p = mesh->mTextureCoords[i], *end = p + mesh->mNumVertices;
|
||||
|
||||
// Ensure unused components are zeroed. This will make 1D texture channels work
|
||||
// as if they were 2D channels .. just in case an application doesn't handle
|
||||
// this case
|
||||
if (2 == mesh->mNumUVComponents[i]) {
|
||||
size_t num = 0;
|
||||
for (; p != end; ++p) {
|
||||
p->z = 0.f;
|
||||
num++;
|
||||
}
|
||||
|
||||
aiVector3D *p = mesh->mTextureCoords[i], *end = p + mesh->mNumVertices;
|
||||
|
||||
// Ensure unused components are zeroed. This will make 1D texture channels work
|
||||
// as if they were 2D channels .. just in case an application doesn't handle
|
||||
// this case
|
||||
if (2 == mesh->mNumUVComponents[i]) {
|
||||
for (; p != end; ++p) {
|
||||
p->z = 0.f;
|
||||
}
|
||||
} else if (1 == mesh->mNumUVComponents[i]) {
|
||||
for (; p != end; ++p) {
|
||||
p->z = p->y = 0.f;
|
||||
}
|
||||
} else if (3 == mesh->mNumUVComponents[i]) {
|
||||
// Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element
|
||||
for (; p != end; ++p) {
|
||||
if (p->z != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (p == end) {
|
||||
ASSIMP_LOG_WARN("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D.");
|
||||
mesh->mNumUVComponents[i] = 2;
|
||||
} else if (1 == mesh->mNumUVComponents[i]) {
|
||||
for (; p != end; ++p) {
|
||||
p->z = p->y = 0.f;
|
||||
}
|
||||
} else if (3 == mesh->mNumUVComponents[i]) {
|
||||
// Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element
|
||||
for (; p != end; ++p) {
|
||||
if (p->z != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (p == end) {
|
||||
ASSIMP_LOG_WARN("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D.");
|
||||
mesh->mNumUVComponents[i] = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
|||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
@ -97,13 +96,14 @@ void SkeletonMeshBuilder::CreateGeometry(const aiNode *pNode) {
|
|||
const aiMatrix4x4 &childTransform = pNode->mChildren[a]->mTransformation;
|
||||
aiVector3D childpos(childTransform.a4, childTransform.b4, childTransform.c4);
|
||||
ai_real distanceToChild = childpos.Length();
|
||||
if (distanceToChild < 0.0001)
|
||||
if (distanceToChild < ai_epsilon) {
|
||||
continue;
|
||||
}
|
||||
aiVector3D up = aiVector3D(childpos).Normalize();
|
||||
|
||||
aiVector3D orth(1.0, 0.0, 0.0);
|
||||
if (std::fabs(orth * up) > 0.99)
|
||||
if (std::fabs(orth * up) > 0.99) {
|
||||
orth.Set(0.0, 1.0, 0.0);
|
||||
}
|
||||
|
||||
aiVector3D front = (up ^ orth).Normalize();
|
||||
aiVector3D side = (front ^ up).Normalize();
|
||||
|
@ -183,8 +183,9 @@ void SkeletonMeshBuilder::CreateGeometry(const aiNode *pNode) {
|
|||
// add all the vertices to the bone's influences
|
||||
bone->mNumWeights = numVertices;
|
||||
bone->mWeights = new aiVertexWeight[numVertices];
|
||||
for (unsigned int a = 0; a < numVertices; a++)
|
||||
for (unsigned int a = 0; a < numVertices; ++a) {
|
||||
bone->mWeights[a] = aiVertexWeight(vertexStartIndex + a, 1.0);
|
||||
}
|
||||
|
||||
// HACK: (thom) transform all vertices to the bone's local space. Should be done before adding
|
||||
// them to the array, but I'm tired now and I'm annoyed.
|
||||
|
@ -194,8 +195,9 @@ void SkeletonMeshBuilder::CreateGeometry(const aiNode *pNode) {
|
|||
}
|
||||
|
||||
// and finally recurse into the children list
|
||||
for (unsigned int a = 0; a < pNode->mNumChildren; a++)
|
||||
for (unsigned int a = 0; a < pNode->mNumChildren; ++a) {
|
||||
CreateGeometry(pNode->mChildren[a]);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -135,6 +135,9 @@ ASSIMP_API aiScene::aiScene() :
|
|||
mNumCameras(0),
|
||||
mCameras(nullptr),
|
||||
mMetaData(nullptr),
|
||||
mName(),
|
||||
mNumSkeletons(0),
|
||||
mSkeletons(nullptr),
|
||||
mPrivate(new Assimp::ScenePrivateData()) {
|
||||
// empty
|
||||
}
|
||||
|
@ -180,7 +183,8 @@ ASSIMP_API aiScene::~aiScene() {
|
|||
delete[] mCameras;
|
||||
|
||||
aiMetadata::Dealloc(mMetaData);
|
||||
mMetaData = nullptr;
|
||||
|
||||
delete[] mSkeletons;
|
||||
|
||||
delete static_cast<Assimp::ScenePrivateData *>(mPrivate);
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ bool EmbedTexturesProcess::addTexture(aiScene *pScene, const std::string &path)
|
|||
|
||||
aiTexel* imageContent = new aiTexel[ 1ul + static_cast<unsigned long>( imageSize ) / sizeof(aiTexel)];
|
||||
pFile->Seek(0, aiOrigin_SET);
|
||||
pFile->Read(reinterpret_cast<char*>(imageContent), imageSize, 1);
|
||||
pFile->Read(reinterpret_cast<char*>(imageContent), static_cast<size_t>(imageSize), 1);
|
||||
mIOHandler->Close(pFile);
|
||||
|
||||
// Enlarging the textures table
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#include "revision.h"
|
||||
#ifdef __GNUC__
|
||||
#include "winresrc.h"
|
||||
#else
|
||||
#include "winres.h"
|
||||
#endif
|
||||
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
#pragma code_page(1252)
|
||||
|
|
|
@ -43,10 +43,10 @@
|
|||
|
||||
#include "crypt.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4244)
|
||||
#endif // _WIN32
|
||||
#endif // _MSC_VER
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
|
@ -164,8 +164,8 @@ int crypthead(const char *passwd, uint8_t *buf, int buf_size, uint32_t *pkeys,
|
|||
return n;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif // _WIN32
|
||||
#endif // _MSC_VER
|
||||
|
||||
/***************************************************************************/
|
||||
|
|
|
@ -23,8 +23,10 @@
|
|||
|
||||
#ifdef _WIN32
|
||||
# define snprintf _snprintf
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4131 4100)
|
||||
#endif
|
||||
# ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wunused-parameter"
|
||||
|
@ -357,9 +359,9 @@ void fill_fopen64_filefunc(zlib_filefunc64_def *pzlib_filefunc_def)
|
|||
pzlib_filefunc_def->opaque = NULL;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
# ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
# endif
|
||||
#endif // _WIN32
|
||||
#endif // _MSC_VER
|
||||
|
|
|
@ -73,10 +73,10 @@
|
|||
# define TRYFREE(p) {if (p) free(p);}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4131 4244 4189 4245)
|
||||
#endif // _WIN32
|
||||
#endif // _MSC_VER
|
||||
|
||||
const char unz_copyright[] =
|
||||
" unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
|
||||
|
@ -1995,6 +1995,6 @@ extern int ZEXPORT unzEndOfFile(unzFile file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif // _WIN32
|
||||
#endif // _MSC_VER
|
|
@ -99,295 +99,129 @@ template <class TNodeType>
|
|||
class TXmlParser {
|
||||
public:
|
||||
/// @brief The default class constructor.
|
||||
TXmlParser() :
|
||||
mDoc(nullptr),
|
||||
mData() {
|
||||
// empty
|
||||
}
|
||||
TXmlParser();
|
||||
|
||||
/// @brief The class destructor.
|
||||
~TXmlParser() {
|
||||
clear();
|
||||
}
|
||||
~TXmlParser();
|
||||
|
||||
/// @brief Will clear the parsed xml-file.
|
||||
void clear() {
|
||||
if (mData.empty()) {
|
||||
mDoc = nullptr;
|
||||
return;
|
||||
}
|
||||
mData.clear();
|
||||
delete mDoc;
|
||||
mDoc = nullptr;
|
||||
}
|
||||
void clear();
|
||||
|
||||
/// @brief Will search for a child-node by its name
|
||||
/// @param name [in] The name of the child-node.
|
||||
/// @return The node instance or nullptr, if nothing was found.
|
||||
TNodeType *findNode(const std::string &name) {
|
||||
if (name.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (nullptr == mDoc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
find_node_by_name_predicate predicate(name);
|
||||
mCurrent = mDoc->find_node(predicate);
|
||||
if (mCurrent.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &mCurrent;
|
||||
}
|
||||
TNodeType *findNode(const std::string &name);
|
||||
|
||||
/// @brief Will return true, if the node is a child-node.
|
||||
/// @param name [in] The name of the child node to look for.
|
||||
/// @return true, if the node is a child-node or false if not.
|
||||
bool hasNode(const std::string &name) {
|
||||
return nullptr != findNode(name);
|
||||
}
|
||||
bool hasNode(const std::string &name);
|
||||
|
||||
/// @brief Will parse an xml-file from a given stream.
|
||||
/// @param stream The input stream.
|
||||
/// @return true, if the parsing was successful, false if not.
|
||||
bool parse(IOStream *stream) {
|
||||
if (nullptr == stream) {
|
||||
ASSIMP_LOG_DEBUG("Stream is nullptr.");
|
||||
return false;
|
||||
}
|
||||
bool parse(IOStream *stream);
|
||||
|
||||
const size_t len = stream->FileSize();
|
||||
mData.resize(len + 1);
|
||||
memset(&mData[0], '\0', len + 1);
|
||||
stream->Read(&mData[0], 1, len);
|
||||
|
||||
mDoc = new pugi::xml_document();
|
||||
pugi::xml_parse_result parse_result = mDoc->load_string(&mData[0], pugi::parse_full);
|
||||
if (parse_result.status == pugi::status_ok) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ASSIMP_LOG_DEBUG("Error while parse xml.", std::string(parse_result.description()), " @ ", parse_result.offset);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @brief Will return truem if a root node is there.
|
||||
/// @brief Will return true if a root node is there.
|
||||
/// @return true in case of an existing root.
|
||||
bool hasRoot() const {
|
||||
return nullptr != mDoc;
|
||||
}
|
||||
bool hasRoot() const;
|
||||
|
||||
/// @brief Will return the document pointer, is nullptr if no xml-file was parsed.
|
||||
/// @return The pointer showing to the document.
|
||||
pugi::xml_document *getDocument() const {
|
||||
return mDoc;
|
||||
}
|
||||
pugi::xml_document *getDocument() const;
|
||||
|
||||
/// @brief Will return the root node, const version.
|
||||
/// @return The root node.
|
||||
const TNodeType getRootNode() const {
|
||||
static pugi::xml_node none;
|
||||
if (nullptr == mDoc) {
|
||||
return none;
|
||||
}
|
||||
return mDoc->root();
|
||||
}
|
||||
const TNodeType getRootNode() const;
|
||||
|
||||
/// @brief Will return the root node, non-const version.
|
||||
/// @return The root node.
|
||||
TNodeType getRootNode() {
|
||||
static pugi::xml_node none;
|
||||
if (nullptr == mDoc) {
|
||||
return none;
|
||||
}
|
||||
return mDoc->root();
|
||||
}
|
||||
TNodeType getRootNode();
|
||||
|
||||
/// @brief Will check if a node with the given name is in.
|
||||
/// @param node [in] The node to look in.
|
||||
/// @param name [in] The name of the child-node.
|
||||
/// @return true, if node was found, false if not.
|
||||
static inline bool hasNode(XmlNode &node, const char *name) {
|
||||
pugi::xml_node child = node.find_child(find_node_by_name_predicate(name));
|
||||
return !child.empty();
|
||||
}
|
||||
static inline bool hasNode(XmlNode &node, const char *name);
|
||||
|
||||
/// @brief Will check if an attribute is part of the XmlNode.
|
||||
/// @param xmlNode [in] The node to search in.
|
||||
/// @param name [in} The attribute name to look for.
|
||||
/// @return true, if the was found, false if not.
|
||||
static inline bool hasAttribute(XmlNode &xmlNode, const char *name) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
return !attr.empty();
|
||||
}
|
||||
static inline bool hasAttribute(XmlNode &xmlNode, const char *name);
|
||||
|
||||
/// @brief Will try to get an unsigned int attribute value.
|
||||
/// @param xmlNode [in] The node to search in.
|
||||
/// @param name [in] The attribute name to look for.
|
||||
/// @param val [out] The unsigned int value from the attribute.
|
||||
/// @return true, if the node contains an attribute with the given name and if the value is an unsigned int.
|
||||
static inline bool getUIntAttribute(XmlNode &xmlNode, const char *name, unsigned int &val) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
if (attr.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = attr.as_uint();
|
||||
return true;
|
||||
}
|
||||
static inline bool getUIntAttribute(XmlNode &xmlNode, const char *name, unsigned int &val);
|
||||
|
||||
/// @brief Will try to get an int attribute value.
|
||||
/// @param xmlNode [in] The node to search in.
|
||||
/// @param name [in] The attribute name to look for.
|
||||
/// @param val [out] The int value from the attribute.
|
||||
/// @return true, if the node contains an attribute with the given name and if the value is an int.
|
||||
static inline bool getIntAttribute(XmlNode &xmlNode, const char *name, int &val) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
if (attr.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = attr.as_int();
|
||||
return true;
|
||||
}
|
||||
static inline bool getIntAttribute(XmlNode &xmlNode, const char *name, int &val);
|
||||
|
||||
/// @brief Will try to get a real attribute value.
|
||||
/// @param xmlNode [in] The node to search in.
|
||||
/// @param name [in] The attribute name to look for.
|
||||
/// @param val [out] The real value from the attribute.
|
||||
/// @return true, if the node contains an attribute with the given name and if the value is a real.
|
||||
static inline bool getRealAttribute(XmlNode &xmlNode, const char *name, ai_real &val) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
if (attr.empty()) {
|
||||
return false;
|
||||
}
|
||||
#ifdef ASSIMP_DOUBLE_PRECISION
|
||||
val = attr.as_double();
|
||||
#else
|
||||
val = attr.as_float();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
static inline bool getRealAttribute(XmlNode &xmlNode, const char *name, ai_real &val);
|
||||
|
||||
/// @brief Will try to get a float attribute value.
|
||||
/// @param xmlNode [in] The node to search in.
|
||||
/// @param name [in] The attribute name to look for.
|
||||
/// @param val [out] The float value from the attribute.
|
||||
/// @return true, if the node contains an attribute with the given name and if the value is a float.
|
||||
static inline bool getFloatAttribute(XmlNode &xmlNode, const char *name, float &val) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
if (attr.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = attr.as_float();
|
||||
return true;
|
||||
}
|
||||
static inline bool getFloatAttribute(XmlNode &xmlNode, const char *name, float &val);
|
||||
|
||||
/// @brief Will try to get a double attribute value.
|
||||
/// @param xmlNode [in] The node to search in.
|
||||
/// @param name [in] The attribute name to look for.
|
||||
/// @param val [out] The double value from the attribute.
|
||||
/// @return true, if the node contains an attribute with the given name and if the value is a double.
|
||||
static inline bool getDoubleAttribute(XmlNode &xmlNode, const char *name, double &val) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
if (attr.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = attr.as_double();
|
||||
return true;
|
||||
}
|
||||
static inline bool getDoubleAttribute(XmlNode &xmlNode, const char *name, double &val);
|
||||
|
||||
/// @brief Will try to get a std::string attribute value.
|
||||
/// @param xmlNode [in] The node to search in.
|
||||
/// @param name [in] The attribute name to look for.
|
||||
/// @param val [out] The std::string value from the attribute.
|
||||
/// @return true, if the node contains an attribute with the given name and if the value is a std::string.
|
||||
static inline bool getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
if (attr.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = attr.as_string();
|
||||
return true;
|
||||
}
|
||||
static inline bool getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val);
|
||||
|
||||
/// @brief Will try to get a bool attribute value.
|
||||
/// @param xmlNode [in] The node to search in.
|
||||
/// @param name [in] The attribute name to look for.
|
||||
/// @param val [out] The bool value from the attribute.
|
||||
/// @return true, if the node contains an attribute with the given name and if the value is a bool.
|
||||
static inline bool getBoolAttribute(XmlNode &xmlNode, const char *name, bool &val) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
if (attr.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = attr.as_bool();
|
||||
return true;
|
||||
}
|
||||
static inline bool getBoolAttribute(XmlNode &xmlNode, const char *name, bool &val);
|
||||
|
||||
/// @brief Will try to get the value of the node as a string.
|
||||
/// @param node [in] The node to search in.
|
||||
/// @param text [out] The value as a text.
|
||||
/// @return true, if the value can be read out.
|
||||
static inline bool getValueAsString(XmlNode &node, std::string &text) {
|
||||
text = std::string();
|
||||
if (node.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
text = node.text().as_string();
|
||||
|
||||
return true;
|
||||
}
|
||||
static inline bool getValueAsString(XmlNode &node, std::string &text);
|
||||
|
||||
/// @brief Will try to get the value of the node as a float.
|
||||
/// @param node [in] The node to search in.
|
||||
/// @param text [out] The value as a float.
|
||||
/// @return true, if the value can be read out.
|
||||
static inline bool getValueAsFloat(XmlNode &node, ai_real &v) {
|
||||
if (node.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
v = node.text().as_float();
|
||||
|
||||
return true;
|
||||
}
|
||||
static inline bool getValueAsFloat(XmlNode &node, ai_real &v);
|
||||
|
||||
/// @brief Will try to get the value of the node as an integer.
|
||||
/// @param node [in] The node to search in.
|
||||
/// @param text [out] The value as a int.
|
||||
/// @return true, if the value can be read out.
|
||||
static inline bool getValueAsInt(XmlNode &node, int &v) {
|
||||
if (node.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
v = node.text().as_int();
|
||||
|
||||
return true;
|
||||
}
|
||||
static inline bool getValueAsInt(XmlNode &node, int &v);
|
||||
|
||||
/// @brief Will try to get the value of the node as an bool.
|
||||
/// @param node [in] The node to search in.
|
||||
/// @param text [out] The value as a bool.
|
||||
/// @return true, if the value can be read out.
|
||||
static inline bool getValueAsBool(XmlNode& node, bool& v)
|
||||
{
|
||||
if (node.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
v = node.text().as_bool();
|
||||
|
||||
return true;
|
||||
}
|
||||
static inline bool getValueAsBool(XmlNode &node, bool &v);
|
||||
|
||||
private:
|
||||
pugi::xml_document *mDoc;
|
||||
|
@ -395,6 +229,254 @@ private:
|
|||
std::vector<char> mData;
|
||||
};
|
||||
|
||||
template <class TNodeType>
|
||||
inline TXmlParser<TNodeType>::TXmlParser() :
|
||||
mDoc(nullptr),
|
||||
mData() {
|
||||
// empty
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline TXmlParser<TNodeType>::~TXmlParser() {
|
||||
clear();
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline void TXmlParser<TNodeType>::clear() {
|
||||
if (mData.empty()) {
|
||||
if (mDoc) {
|
||||
delete mDoc;
|
||||
}
|
||||
mDoc = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
mData.clear();
|
||||
delete mDoc;
|
||||
mDoc = nullptr;
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline TNodeType *TXmlParser<TNodeType>::findNode(const std::string &name) {
|
||||
if (name.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (nullptr == mDoc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
find_node_by_name_predicate predicate(name);
|
||||
mCurrent = mDoc->find_node(predicate);
|
||||
if (mCurrent.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &mCurrent;
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
bool TXmlParser<TNodeType>::hasNode(const std::string &name) {
|
||||
return nullptr != findNode(name);
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
bool TXmlParser<TNodeType>::parse(IOStream *stream) {
|
||||
if (hasRoot()) {
|
||||
clear();
|
||||
}
|
||||
|
||||
if (nullptr == stream) {
|
||||
ASSIMP_LOG_DEBUG("Stream is nullptr.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t len = stream->FileSize();
|
||||
mData.resize(len + 1);
|
||||
memset(&mData[0], '\0', len + 1);
|
||||
stream->Read(&mData[0], 1, len);
|
||||
|
||||
mDoc = new pugi::xml_document();
|
||||
pugi::xml_parse_result parse_result = mDoc->load_string(&mData[0], pugi::parse_full);
|
||||
if (parse_result.status == pugi::status_ok) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ASSIMP_LOG_DEBUG("Error while parse xml.", std::string(parse_result.description()), " @ ", parse_result.offset);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
bool TXmlParser<TNodeType>::hasRoot() const {
|
||||
return nullptr != mDoc;
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
pugi::xml_document *TXmlParser<TNodeType>::getDocument() const {
|
||||
return mDoc;
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
const TNodeType TXmlParser<TNodeType>::getRootNode() const {
|
||||
static pugi::xml_node none;
|
||||
if (nullptr == mDoc) {
|
||||
return none;
|
||||
}
|
||||
return mDoc->root();
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
TNodeType TXmlParser<TNodeType>::getRootNode() {
|
||||
static pugi::xml_node none;
|
||||
if (nullptr == mDoc) {
|
||||
return none;
|
||||
}
|
||||
|
||||
return mDoc->root();
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline bool TXmlParser<TNodeType>::hasNode(XmlNode &node, const char *name) {
|
||||
pugi::xml_node child = node.find_child(find_node_by_name_predicate(name));
|
||||
return !child.empty();
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline bool TXmlParser<TNodeType>::hasAttribute(XmlNode &xmlNode, const char *name) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
return !attr.empty();
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline bool TXmlParser<TNodeType>::getUIntAttribute(XmlNode &xmlNode, const char *name, unsigned int &val) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
if (attr.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = attr.as_uint();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline bool TXmlParser<TNodeType>::getIntAttribute(XmlNode &xmlNode, const char *name, int &val) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
if (attr.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = attr.as_int();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline bool TXmlParser<TNodeType>::getRealAttribute(XmlNode &xmlNode, const char *name, ai_real &val) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
if (attr.empty()) {
|
||||
return false;
|
||||
}
|
||||
#ifdef ASSIMP_DOUBLE_PRECISION
|
||||
val = attr.as_double();
|
||||
#else
|
||||
val = attr.as_float();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline bool TXmlParser<TNodeType>::getFloatAttribute(XmlNode &xmlNode, const char *name, float &val) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
if (attr.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = attr.as_float();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline bool TXmlParser<TNodeType>::getDoubleAttribute(XmlNode &xmlNode, const char *name, double &val) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
if (attr.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = attr.as_double();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline bool TXmlParser<TNodeType>::getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
if (attr.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = attr.as_string();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline bool TXmlParser<TNodeType>::getBoolAttribute(XmlNode &xmlNode, const char *name, bool &val) {
|
||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||
if (attr.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = attr.as_bool();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline bool TXmlParser<TNodeType>::getValueAsString(XmlNode &node, std::string &text) {
|
||||
text = std::string();
|
||||
if (node.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
text = node.text().as_string();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline bool TXmlParser<TNodeType>::getValueAsFloat(XmlNode &node, ai_real &v) {
|
||||
if (node.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
v = node.text().as_float();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline bool TXmlParser<TNodeType>::getValueAsInt(XmlNode &node, int &v) {
|
||||
if (node.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
v = node.text().as_int();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TNodeType>
|
||||
inline bool TXmlParser<TNodeType>::getValueAsBool(XmlNode &node, bool &v) {
|
||||
if (node.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
v = node.text().as_bool();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
using XmlParser = TXmlParser<pugi::xml_node>;
|
||||
|
||||
/// @brief This class declares an iterator to loop through all children of the root node.
|
||||
|
|
|
@ -691,6 +691,15 @@ enum aiComponent
|
|||
#define AI_CONFIG_FBX_CONVERT_TO_M \
|
||||
"AI_CONFIG_FBX_CONVERT_TO_M"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Will enable the skeleton structo to store bone data.
|
||||
*
|
||||
* This will decouple the bone coupling to the mesh. This feature is
|
||||
* experimental.
|
||||
*/
|
||||
#define AI_CONFIG_FBX_USE_SKELETON_BONE_CONTAINER \
|
||||
"AI_CONFIG_FBX_USE_SKELETON_BONE_CONTAINER"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Set the vertex animation keyframe to be imported
|
||||
*
|
||||
|
|
|
@ -120,7 +120,7 @@ extern "C" {
|
|||
* primitive are actually present in a mesh. The #aiProcess_SortByPType flag
|
||||
* executes a special post-processing algorithm which splits meshes with
|
||||
* *different* primitive types mixed up (e.g. lines and triangles) in several
|
||||
* 'clean' submeshes. Furthermore there is a configuration option (
|
||||
* 'clean' sub-meshes. Furthermore there is a configuration option (
|
||||
* #AI_CONFIG_PP_SBP_REMOVE) to force #aiProcess_SortByPType to remove
|
||||
* specific kinds of primitives from the imported scene, completely and forever.
|
||||
* In many cases you'll probably want to set this setting to
|
||||
|
@ -269,12 +269,12 @@ struct aiBone {
|
|||
unsigned int mNumWeights;
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
|
||||
// The bone armature node - used for skeleton conversion
|
||||
// you must enable aiProcess_PopulateArmatureData to populate this
|
||||
/// The bone armature node - used for skeleton conversion
|
||||
/// you must enable aiProcess_PopulateArmatureData to populate this
|
||||
C_STRUCT aiNode *mArmature;
|
||||
|
||||
// The bone node in the scene - used for skeleton conversion
|
||||
// you must enable aiProcess_PopulateArmatureData to populate this
|
||||
/// The bone node in the scene - used for skeleton conversion
|
||||
/// you must enable aiProcess_PopulateArmatureData to populate this
|
||||
C_STRUCT aiNode *mNode;
|
||||
|
||||
#endif
|
||||
|
@ -296,7 +296,7 @@ struct aiBone {
|
|||
|
||||
#ifdef __cplusplus
|
||||
|
||||
//! Default constructor
|
||||
/// @brief Default constructor
|
||||
aiBone() AI_NO_EXCEPT
|
||||
: mName(),
|
||||
mNumWeights(0),
|
||||
|
@ -309,7 +309,7 @@ struct aiBone {
|
|||
// empty
|
||||
}
|
||||
|
||||
//! Copy constructor
|
||||
/// @brief Copy constructor
|
||||
aiBone(const aiBone &other) :
|
||||
mName(other.mName),
|
||||
mNumWeights(other.mNumWeights),
|
||||
|
@ -319,14 +319,27 @@ struct aiBone {
|
|||
#endif
|
||||
mWeights(nullptr),
|
||||
mOffsetMatrix(other.mOffsetMatrix) {
|
||||
if (other.mWeights && other.mNumWeights) {
|
||||
mWeights = new aiVertexWeight[mNumWeights];
|
||||
::memcpy(mWeights, other.mWeights, mNumWeights * sizeof(aiVertexWeight));
|
||||
copyVertexWeights(other);
|
||||
}
|
||||
|
||||
void copyVertexWeights( const aiBone &other ) {
|
||||
if (other.mWeights == nullptr || other.mNumWeights == 0) {
|
||||
mWeights = nullptr;
|
||||
mNumWeights = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
mNumWeights = other.mNumWeights;
|
||||
if (mWeights) {
|
||||
delete[] mWeights;
|
||||
}
|
||||
|
||||
mWeights = new aiVertexWeight[mNumWeights];
|
||||
::memcpy(mWeights, other.mWeights, mNumWeights * sizeof(aiVertexWeight));
|
||||
}
|
||||
|
||||
//! Assignment operator
|
||||
aiBone &operator=(const aiBone &other) {
|
||||
aiBone &operator = (const aiBone &other) {
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
|
@ -334,21 +347,13 @@ struct aiBone {
|
|||
mName = other.mName;
|
||||
mNumWeights = other.mNumWeights;
|
||||
mOffsetMatrix = other.mOffsetMatrix;
|
||||
|
||||
if (other.mWeights && other.mNumWeights) {
|
||||
if (mWeights) {
|
||||
delete[] mWeights;
|
||||
}
|
||||
|
||||
mWeights = new aiVertexWeight[mNumWeights];
|
||||
::memcpy(mWeights, other.mWeights, mNumWeights * sizeof(aiVertexWeight));
|
||||
}
|
||||
copyVertexWeights(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const aiBone &rhs) const {
|
||||
if (mName != rhs.mName || mNumWeights != rhs.mNumWeights) {
|
||||
if (mName != rhs.mName || mNumWeights != rhs.mNumWeights ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -937,6 +942,100 @@ struct aiMesh {
|
|||
#endif // __cplusplus
|
||||
};
|
||||
|
||||
struct aiSkeletonBone {
|
||||
/// The parent bone index, is -1 one if this bone represents the root bone.
|
||||
int mParent;
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
|
||||
/// The bone armature node - used for skeleton conversion
|
||||
/// you must enable aiProcess_PopulateArmatureData to populate this
|
||||
C_STRUCT aiNode *mArmature;
|
||||
|
||||
/// The bone node in the scene - used for skeleton conversion
|
||||
/// you must enable aiProcess_PopulateArmatureData to populate this
|
||||
C_STRUCT aiNode *mNode;
|
||||
|
||||
#endif
|
||||
/// @brief The number of weights
|
||||
unsigned int mNumnWeights;
|
||||
|
||||
/// The mesh index, which will get influenced by the weight.
|
||||
C_STRUCT aiMesh *mMeshId;
|
||||
|
||||
/// The influence weights of this bone, by vertex index.
|
||||
C_STRUCT aiVertexWeight *mWeights;
|
||||
|
||||
/** Matrix that transforms from bone space to mesh space in bind pose.
|
||||
*
|
||||
* This matrix describes the position of the mesh
|
||||
* in the local space of this bone when the skeleton was bound.
|
||||
* Thus it can be used directly to determine a desired vertex position,
|
||||
* given the world-space transform of the bone when animated,
|
||||
* and the position of the vertex in mesh space.
|
||||
*
|
||||
* It is sometimes called an inverse-bind matrix,
|
||||
* or inverse bind pose matrix.
|
||||
*/
|
||||
C_STRUCT aiMatrix4x4 mOffsetMatrix;
|
||||
|
||||
/// Matrix that transforms the locale bone in bind pose.
|
||||
C_STRUCT aiMatrix4x4 mLocalMatrix;
|
||||
|
||||
#ifdef __cplusplus
|
||||
aiSkeletonBone() :
|
||||
mParent(-1),
|
||||
mArmature(nullptr),
|
||||
mNode(nullptr),
|
||||
mNumnWeights(0),
|
||||
mMeshId(nullptr),
|
||||
mWeights(nullptr),
|
||||
mOffsetMatrix(),
|
||||
mLocalMatrix() {
|
||||
// empty
|
||||
}
|
||||
|
||||
~aiSkeletonBone() {
|
||||
delete[] mWeights;
|
||||
mWeights = nullptr;
|
||||
}
|
||||
#endif // __cplusplus
|
||||
};
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
struct aiSkeleton {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
C_STRUCT aiString mName;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
unsigned int mNumBones;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
C_STRUCT aiSkeletonBone **mBones;
|
||||
|
||||
#ifdef __cplusplus
|
||||
/**
|
||||
*
|
||||
*/
|
||||
aiSkeleton() AI_NO_EXCEPT : mName(), mNumBones(0), mBones(nullptr) {
|
||||
// empty
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
~aiSkeleton() {
|
||||
delete[] mBones;
|
||||
}
|
||||
#endif // __cplusplus
|
||||
};
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif //! extern "C"
|
||||
|
|
|
@ -79,8 +79,7 @@ extern "C" {
|
|||
* the imported scene does consist of only a single root node without children.
|
||||
*/
|
||||
// -------------------------------------------------------------------------------
|
||||
struct ASSIMP_API aiNode
|
||||
{
|
||||
struct ASSIMP_API aiNode {
|
||||
/** The name of the node.
|
||||
*
|
||||
* The name might be empty (length of zero) but all nodes which
|
||||
|
@ -343,6 +342,16 @@ struct aiScene
|
|||
*/
|
||||
C_STRUCT aiString mName;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
unsigned int mNumSkeletons;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
C_STRUCT aiSkeleton **mSkeletons;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
//! Default constructor - set everything to 0/nullptr
|
||||
|
@ -383,6 +392,10 @@ struct aiScene
|
|||
return mAnimations != nullptr && mNumAnimations > 0;
|
||||
}
|
||||
|
||||
bool hasSkeletons() const {
|
||||
return mSkeletons != nullptr && mNumSkeletons > 0;
|
||||
}
|
||||
|
||||
//! Returns a short filename from a full path
|
||||
static const char* GetShortFilename(const char* filename) {
|
||||
const char* lastSlash = strrchr(filename, '/');
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<asset>
|
||||
<contributor>
|
||||
<author>Blender User</author>
|
||||
<authoring_tool>Blender 2.80.40 commit date:2019-01-07, commit time:23:37, hash:91a155833e59</authoring_tool>
|
||||
</contributor>
|
||||
<created>2019-01-08T17:44:11</created>
|
||||
<modified>2019-01-08T17:44:11</modified>
|
||||
<unit name="meter" meter="1"/>
|
||||
<up_axis>Z_UP</up_axis>
|
||||
</asset>
|
||||
<library_effects>
|
||||
<effect id="Material-effect">
|
||||
<profile_COMMON>
|
||||
<technique sid="common">
|
||||
<lambert>
|
||||
<diffuse>
|
||||
<color sid="diffuse">0.8 0.8 0.8 1</color>
|
||||
</diffuse>
|
||||
<specular>
|
||||
<color sid="specular">0 0.5 0 1</color>
|
||||
</specular>
|
||||
</lambert>
|
||||
</technique>
|
||||
</profile_COMMON>
|
||||
</effect>
|
||||
</library_effects>
|
||||
<library_images/>
|
||||
<library_materials>
|
||||
<material id="Material-material" name="Material">
|
||||
<instance_effect url="#Material-effect"/>
|
||||
</material>
|
||||
</library_materials>
|
||||
<library_geometries>
|
||||
<geometry id="Cube-mesh" name="Cube">
|
||||
<mesh>
|
||||
<source id="Cube-mesh-positions">
|
||||
<float_array id="Cube-mesh-positions-array" count="24">1 1 1 1 1 -1 1 -1 1 1 -1 -1 -1 1 1 -1 1 -1 -1 -1 1 -1 -1 -1</float_array>
|
||||
<technique_common>
|
||||
<accessor source="#Cube-mesh-positions-array" count="8" stride="3">
|
||||
<param name="X" type="float"/>
|
||||
<param name="Y" type="float"/>
|
||||
<param name="Z" type="float"/>
|
||||
</accessor>
|
||||
</technique_common>
|
||||
</source>
|
||||
<source id="Cube-mesh-normals">
|
||||
<float_array id="Cube-mesh-normals-array" count="18">0 0 1 0 -1 0 -1 0 0 0 0 -1 1 0 0 0 1 0</float_array>
|
||||
<technique_common>
|
||||
<accessor source="#Cube-mesh-normals-array" count="6" stride="3">
|
||||
<param name="X" type="float"/>
|
||||
<param name="Y" type="float"/>
|
||||
<param name="Z" type="float"/>
|
||||
</accessor>
|
||||
</technique_common>
|
||||
</source>
|
||||
<source id="Cube-mesh-map-0">
|
||||
<float_array id="Cube-mesh-map-0-array" count="72">0.625 0 0.375 0.25 0.375 0 0.625 0.25 0.375 0.5 0.375 0.25 0.625 0.5 0.375 0.75 0.375 0.5 0.625 0.75 0.375 1 0.375 0.75 0.375 0.5 0.125 0.75 0.125 0.5 0.875 0.5 0.625 0.75 0.625 0.5 0.625 0 0.625 0.25 0.375 0.25 0.625 0.25 0.625 0.5 0.375 0.5 0.625 0.5 0.625 0.75 0.375 0.75 0.625 0.75 0.625 1 0.375 1 0.375 0.5 0.375 0.75 0.125 0.75 0.875 0.5 0.875 0.75 0.625 0.75</float_array>
|
||||
<technique_common>
|
||||
<accessor source="#Cube-mesh-map-0-array" count="36" stride="2">
|
||||
<param name="S" type="float"/>
|
||||
<param name="T" type="float"/>
|
||||
</accessor>
|
||||
</technique_common>
|
||||
</source>
|
||||
<vertices id="Cube-mesh-vertices">
|
||||
<input semantic="POSITION" source="#Cube-mesh-positions"/>
|
||||
</vertices>
|
||||
<polylist material="Material-material" count="12">
|
||||
<input semantic="VERTEX" source="#Cube-mesh-vertices" offset="0"/>
|
||||
<input semantic="NORMAL" source="#Cube-mesh-normals" offset="1"/>
|
||||
<input semantic="TEXCOORD" source="#Cube-mesh-map-0" offset="2" set="1"/>
|
||||
<vcount>3 3 3 3 3 3 3 3 3 3 3 3 </vcount>
|
||||
<p>4 0 0 2 0 1 0 0 2 2 1 3 7 1 4 3 1 5 6 2 6 5 2 7 7 2 8 1 3 9 7 3 10 5 3 11 0 4 12 3 4 13 1 4 14 4 5 15 1 5 16 5 5 17 4 0 18 6 0 19 2 0 20 2 1 21 6 1 22 7 1 23 6 2 24 4 2 25 5 2 26 1 3 27 3 3 28 7 3 29 0 4 30 2 4 31 3 4 32 4 5 33 0 5 34 1 5 35</p>
|
||||
</polylist>
|
||||
</mesh>
|
||||
</geometry>
|
||||
</library_geometries>
|
||||
<library_controllers>
|
||||
<controller id="Armature_Cube-skin" name="Armature">
|
||||
<skin source="#Cube-mesh">
|
||||
<bind_shape_matrix>1 0 0 -1 0 1 0 1 0 0 1 1 0 0 0 1</bind_shape_matrix>
|
||||
<source id="Armature_Cube-skin-joints">
|
||||
<Name_array id="Armature_Cube-skin-joints-array" count="1">Bone</Name_array>
|
||||
<technique_common>
|
||||
<accessor source="#Armature_Cube-skin-joints-array" count="1" stride="1">
|
||||
<param name="JOINT" type="name"/>
|
||||
</accessor>
|
||||
</technique_common>
|
||||
</source>
|
||||
<source id="Armature_Cube-skin-bind_poses">
|
||||
<float_array id="Armature_Cube-skin-bind_poses-array" count="16">0.7886752 0.2113248 0.5773504 -0.5773504 -0.5773503 0.5773503 0.5773503 1.154701 -0.2113249 -0.7886752 0.5773503 -0.5773502 0 0 0 1</float_array>
|
||||
<technique_common>
|
||||
<accessor source="#Armature_Cube-skin-bind_poses-array" count="1" stride="16">
|
||||
<param name="TRANSFORM" type="float4x4"/>
|
||||
</accessor>
|
||||
</technique_common>
|
||||
</source>
|
||||
<source id="Armature_Cube-skin-weights">
|
||||
<float_array id="Armature_Cube-skin-weights-array" count="8">1 1 1 1 1 1 1 1</float_array>
|
||||
<technique_common>
|
||||
<accessor source="#Armature_Cube-skin-weights-array" count="8" stride="1">
|
||||
<param name="WEIGHT" type="float"/>
|
||||
</accessor>
|
||||
</technique_common>
|
||||
</source>
|
||||
<joints>
|
||||
<input semantic="JOINT" source="#Armature_Cube-skin-joints"/>
|
||||
<input semantic="INV_BIND_MATRIX" source="#Armature_Cube-skin-bind_poses"/>
|
||||
</joints>
|
||||
<vertex_weights count="8">
|
||||
<input semantic="JOINT" source="#Armature_Cube-skin-joints" offset="0"/>
|
||||
<input semantic="WEIGHT" source="#Armature_Cube-skin-weights" offset="1"/>
|
||||
<vcount>1 1 1 1 1 1 1 1 </vcount>
|
||||
<v>0 0 0 1 0 2 0 3 0 4 0 5 0 6 0 7</v>
|
||||
</vertex_weights>
|
||||
</skin>
|
||||
</controller>
|
||||
</library_controllers>
|
||||
<library_animations>
|
||||
<animation id="action_container-Armature" name="Armature">
|
||||
<animation id="Armature_ArmatureAction_transform" name="Armature">
|
||||
<source id="Armature_ArmatureAction_transform-input">
|
||||
<float_array id="Armature_ArmatureAction_transform-input-array" count="40">0.04166662 0.08333331 0.125 0.1666666 0.2083333 0.25 0.2916666 0.3333333 0.375 0.4166666 0.4583333 0.5 0.5416667 0.5833333 0.625 0.6666667 0.7083333 0.75 0.7916667 0.8333333 0.875 0.9166667 0.9583333 1 1.041667 1.083333 1.125 1.166667 1.208333 1.25 1.291667 1.333333 1.375 1.416667 1.458333 1.5 1.541667 1.583333 1.625 1.666667</float_array>
|
||||
<technique_common>
|
||||
<accessor source="#Armature_ArmatureAction_transform-input-array" count="40" stride="1">
|
||||
<param name="TIME" type="float"/>
|
||||
</accessor>
|
||||
</technique_common>
|
||||
</source>
|
||||
<source id="Armature_ArmatureAction_transform-output">
|
||||
<float_array id="Armature_ArmatureAction_transform-output-array" count="640">1 0 0 1 0 1 0 -1 0 0 1 0 0 0 0 1 0.9999878 3.10816e-5 0.004935208 1 0 0.9999802 -0.006297799 -1 -0.004935306 0.006297722 0.999968 0 0 0 0 1 0.999819 4.61727e-4 0.01901668 1 0 0.9997054 -0.02427293 -1 -0.01902229 0.02426853 0.9995245 0 0 0 0 1 0.9991519 0.002163141 0.04111904 1 0 0.9986191 -0.05253414 -1 -0.04117589 0.05248959 0.9977722 0 0 0 0 1 0.9975264 0.006301912 0.07000974 1 0 0.9959731 -0.08965231 -1 -0.0702928 0.08943056 0.9935095 0 0 0 0 1 0.9944467 0.01411698 0.1042901 1 0 0.9909625 -0.1341392 -1 -0.1052413 0.1333943 0.9854594 0 0 0 0 1 0.9894527 0.02671701 0.1423712 1 0 0.9828442 -0.184438 -1 -0.1448563 0.1824927 0.9724778 0 0 0 0 1 0.9821799 0.04490547 0.1825 1 0 0.9710366 -0.2389307 -1 -0.1879434 0.234673 0.9537326 0 0 0 0 1 0.9724072 0.06904543 0.2228386 1 0 0.9551992 -0.2959637 -1 -0.2332902 0.2877972 0.9288425 0 0 0 0 1 0.9600915 0.09897761 0.261587 1 0 0.9352878 -0.3538882 -1 -0.2796861 0.339765 0.8979618 0 0 0 0 1 0.9453882 0.1340003 0.2971281 1 0 0.9115852 -0.4111113 -1 -0.3259466 0.3886598 0.8618018 0 0 0 0 1 0.9286572 0.1729132 0.328172 1 0 0.8847058 -0.4661497 -1 -0.3709391 0.4328933 0.8215885 0 0 0 0 1 0.9104556 0.2141147 0.3538722 1 0 0.8555763 -0.5176768 -1 -0.4136069 0.4713217 0.7789642 0 0 0 0 1 0.8915175 0.2557371 0.3738919 1 0 0.8253933 -0.5645581 -1 -0.4529863 0.5033134 0.7358525 0 0 0 0 1 0.8727233 0.2957927 0.388408 1 0 0.7955672 -0.6058654 -1 -0.4882152 0.5287529 0.6943099 0 0 0 0 1 0.8550603 0.332307 0.3980502 1 0 0.7676533 -0.6408653 -1 -0.5185286 0.5479785 0.6563899 0 0 0 0 1 0.8395769 0.3634188 0.4037789 1 0 0.7432778 -0.6689829 -1 -0.5432408 0.5616626 0.6240388 0 0 0 0 1 0.8273312 0.3874339 0.4067161 1 0 0.7240622 -0.6897347 -1 -0.5617144 0.5706391 0.5990393 0 0 0 0 1 0.8193359 0.4028329 0.4079393 1 0 0.7115462 -0.7026393 -1 -0.5733138 0.5756976 0.5829953 0 0 0 0 1 0.8164964 0.4082482 0.4082486 1 7.75722e-8 0.707107 -0.7071065 -1 -0.5773504 0.57735 0.5773503 0 0 0 0 1 0.8190646 0.4033515 0.4079717 1 7.78161e-8 0.7111219 -0.7030687 -1 -0.5737014 0.5758587 0.5824547 0 0 0 0 1 0.8263245 0.3893851 0.4068995 1 7.85059e-8 0.7224849 -0.6913868 -1 -0.5631944 0.5713098 0.5970069 0 0 0 0 1 0.8375081 0.3675125 0.4043696 1 7.95684e-8 0.7400277 -0.6725764 -1 -0.5464249 0.5632883 0.6197791 0 0 0 0 1 0.8517552 0.3390183 0.3994742 1 8.0922e-8 0.7624427 -0.6470557 -1 -0.5239399 0.5511332 0.6494145 0 0 0 0 1 0.8681612 0.3053284 0.3912425 1 8.24806e-8 0.7883466 -0.6152314 -1 -0.4962822 0.5341201 0.6844119 0 0 0 0 1 0.8858209 0.2680094 0.3788038 1 8.41584e-8 0.8163394 -0.5775725 -1 -0.4640273 0.5116258 0.7231305 0 0 0 0 1 0.9038687 0.2287352 0.3615268 1 8.58731e-8 0.8450637 -0.5346656 -1 -0.42781 0.4832675 0.7638266 0 0 0 0 1 0.9215156 0.1892192 0.339124 1 8.75496e-8 0.8732626 -0.4872499 -1 -0.3883413 0.4490085 0.8047251 0 0 0 0 1 0.9380813 0.1511175 0.3117163 1 8.91235e-8 0.899834 -0.4362323 -1 -0.3464153 0.4092214 0.8441175 0 0 0 0 1 0.9530206 0.1159168 0.2798482 1 9.05428e-8 0.9238796 -0.3826832 -1 -0.3029055 0.3647051 0.8804763 0 0 0 0 1 0.965943 0.08482374 0.2444564 1 9.17705e-8 0.9447417 -0.3278156 -1 -0.2587547 0.3166512 0.9125667 0 0 0 0 1 0.9766233 0.05867312 0.2067956 1 9.27852e-8 0.9620277 -0.2729518 -1 -0.2149581 0.2665711 0.9395387 0 0 0 0 1 0.9850019 0.03787052 0.1683363 1 9.35812e-8 0.975616 -0.2194843 -1 -0.1725436 0.2161924 0.9609836 0 0 0 0 1 0.991176 0.02237916 0.1306496 1 9.41678e-8 0.9856446 -0.1688333 -1 -0.1325524 0.1673435 0.9769473 0 0 0 0 1 0.9953793 0.01175384 0.09529842 1 9.45671e-8 0.9924796 -0.1224106 -1 -0.09602053 0.121845 0.9878936 0 0 0 0 1 0.997952 0.005218936 0.06375288 1 9.48115e-8 0.996666 -0.08159051 -1 -0.06396614 0.08142342 0.9946249 0 0 0 0 1 0.9993011 0.001782816 0.03733916 1 9.49397e-8 0.998862 -0.04769476 -1 -0.0373817 0.04766143 0.9981638 0 0 0 0 1 0.9998515 3.78837e-4 0.01722835 1 9.4992e-8 0.9997582 -0.02198936 -1 -0.01723252 0.0219861 0.9996098 0 0 0 0 1 0.99999 2.53135e-5 0.004462156 1 9.50052e-8 0.9999838 -0.00569412 -1 -0.004462227 0.005694063 0.9999738 0 0 0 0 1 1 0 0 2 0 1 0 -1 0 0 1 0 0 0 0 1</float_array>
|
||||
<technique_common>
|
||||
<accessor source="#Armature_ArmatureAction_transform-output-array" count="40" stride="16">
|
||||
<param name="TRANSFORM" type="float4x4"/>
|
||||
</accessor>
|
||||
</technique_common>
|
||||
</source>
|
||||
<source id="Armature_ArmatureAction_transform-interpolation">
|
||||
<Name_array id="Armature_ArmatureAction_transform-interpolation-array" count="40">LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR</Name_array>
|
||||
<technique_common>
|
||||
<accessor source="#Armature_ArmatureAction_transform-interpolation-array" count="40" stride="1">
|
||||
<param name="INTERPOLATION" type="name"/>
|
||||
</accessor>
|
||||
</technique_common>
|
||||
</source>
|
||||
<sampler id="Armature_ArmatureAction_transform-sampler">
|
||||
<input semantic="INPUT" source="#Armature_ArmatureAction_transform-input"/>
|
||||
<input semantic="OUTPUT" source="#Armature_ArmatureAction_transform-output"/>
|
||||
<input semantic="INTERPOLATION" source="#Armature_ArmatureAction_transform-interpolation"/>
|
||||
</sampler>
|
||||
<channel source="#Armature_ArmatureAction_transform-sampler" target="Armature_Bone/transform"/>
|
||||
</animation>
|
||||
</animation>
|
||||
</library_animations>
|
||||
<library_visual_scenes>
|
||||
<visual_scene id="Scene" name="Scene">
|
||||
<node id="Armature" name="Armature" type="NODE">
|
||||
<matrix sid="transform">1 0 0 1 0 1 0 -1 0 0 1 0 0 0 0 1</matrix>
|
||||
<node id="Armature_Bone" name="Bone" sid="Bone" type="JOINT">
|
||||
<matrix sid="transform">0.7886751 -0.5773503 -0.211325 0 0.2113248 0.5773503 -0.7886751 0 0.5773503 0.5773503 0.5773502 0 0 0 0 1</matrix>
|
||||
<extra>
|
||||
<technique profile="blender">
|
||||
<layer sid="layer" type="string">0</layer>
|
||||
<roll sid="roll" type="float">-0.5235989</roll>
|
||||
<tip_x sid="tip_x" type="float">-2</tip_x>
|
||||
<tip_y sid="tip_y" type="float">2</tip_y>
|
||||
<tip_z sid="tip_z" type="float">2</tip_z>
|
||||
</technique>
|
||||
</extra>
|
||||
</node>
|
||||
<node id="Cube" name="Cube" type="NODE">
|
||||
<translate sid="location">0 0 0</translate>
|
||||
<rotate sid="rotationZ">0 0 1 0</rotate>
|
||||
<rotate sid="rotationY">0 1 0 0</rotate>
|
||||
<rotate sid="rotationX">1 0 0 0</rotate>
|
||||
<scale sid="scale">1 1 1</scale>
|
||||
<instance_controller url="#Armature_Cube-skin">
|
||||
<skeleton>#Armature_Bone</skeleton>
|
||||
<bind_material>
|
||||
<technique_common>
|
||||
<instance_material symbol="Material-material" target="#Material-material">
|
||||
<bind_vertex_input semantic="UVMap" input_semantic="TEXCOORD" input_set="0"/>
|
||||
</instance_material>
|
||||
</technique_common>
|
||||
</bind_material>
|
||||
</instance_controller>
|
||||
</node>
|
||||
</node>
|
||||
</visual_scene>
|
||||
</library_visual_scenes>
|
||||
<scene>
|
||||
<instance_visual_scene url="#Scene"/>
|
||||
</scene>
|
||||
</COLLADA>
|
Binary file not shown.
|
@ -69,31 +69,44 @@ public:
|
|||
|
||||
virtual bool importerTest() final {
|
||||
Assimp::Importer importer;
|
||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.dae", aiProcess_ValidateDataStructure);
|
||||
if (scene == nullptr)
|
||||
return false;
|
||||
{
|
||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.dae", aiProcess_ValidateDataStructure);
|
||||
if (scene == nullptr)
|
||||
return false;
|
||||
|
||||
// Expected number of items
|
||||
EXPECT_EQ(scene->mNumMeshes, 1u);
|
||||
EXPECT_EQ(scene->mNumMaterials, 1u);
|
||||
EXPECT_EQ(scene->mNumAnimations, 0u);
|
||||
EXPECT_EQ(scene->mNumTextures, 0u);
|
||||
EXPECT_EQ(scene->mNumLights, 1u);
|
||||
EXPECT_EQ(scene->mNumCameras, 1u);
|
||||
// Expected number of items
|
||||
EXPECT_EQ(scene->mNumMeshes, 1u);
|
||||
EXPECT_EQ(scene->mNumMaterials, 1u);
|
||||
EXPECT_EQ(scene->mNumAnimations, 0u);
|
||||
EXPECT_EQ(scene->mNumTextures, 0u);
|
||||
EXPECT_EQ(scene->mNumLights, 1u);
|
||||
EXPECT_EQ(scene->mNumCameras, 1u);
|
||||
|
||||
// Expected common metadata
|
||||
aiString value;
|
||||
EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT, value)) << "No importer format metadata";
|
||||
EXPECT_STREQ("Collada Importer", value.C_Str());
|
||||
// Expected common metadata
|
||||
aiString value;
|
||||
EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT, value)) << "No importer format metadata";
|
||||
EXPECT_STREQ("Collada Importer", value.C_Str());
|
||||
|
||||
EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT_VERSION, value)) << "No format version metadata";
|
||||
EXPECT_STREQ("1.4.1", value.C_Str());
|
||||
EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT_VERSION, value)) << "No format version metadata";
|
||||
EXPECT_STREQ("1.4.1", value.C_Str());
|
||||
|
||||
EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_GENERATOR, value)) << "No generator metadata";
|
||||
EXPECT_EQ(strncmp(value.C_Str(), "Maya 8.0", 8), 0) << "AI_METADATA_SOURCE_GENERATOR was: " << value.C_Str();
|
||||
EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_GENERATOR, value)) << "No generator metadata";
|
||||
EXPECT_EQ(strncmp(value.C_Str(), "Maya 8.0", 8), 0) << "AI_METADATA_SOURCE_GENERATOR was: " << value.C_Str();
|
||||
|
||||
EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_COPYRIGHT, value)) << "No copyright metadata";
|
||||
EXPECT_EQ(strncmp(value.C_Str(), "Copyright 2006", 14), 0) << "AI_METADATA_SOURCE_COPYRIGHT was: " << value.C_Str();
|
||||
EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_COPYRIGHT, value)) << "No copyright metadata";
|
||||
EXPECT_EQ(strncmp(value.C_Str(), "Copyright 2006", 14), 0) << "AI_METADATA_SOURCE_COPYRIGHT was: " << value.C_Str();
|
||||
}
|
||||
|
||||
{
|
||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/box_nested_animation.dae", aiProcess_ValidateDataStructure);
|
||||
if (scene == nullptr)
|
||||
return false;
|
||||
|
||||
// Expect only one animation with the correct name
|
||||
EXPECT_EQ(scene->mNumAnimations, 1u);
|
||||
EXPECT_EQ(std::string(scene->mAnimations[0]->mName.C_Str()), std::string("Armature"));
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -423,3 +423,10 @@ TEST_F(utFBXImporterExporter, importMaxPbrMaterialsSpecularGloss) {
|
|||
ASSERT_EQ(mat->Get("$raw.3dsMax|main|emit_color", aiTextureType_NONE, 0, emitColor), aiReturn_SUCCESS);
|
||||
EXPECT_EQ(emitColor, aiColor4D(1, 0, 1, 1));
|
||||
}
|
||||
|
||||
TEST_F(utFBXImporterExporter, importSkeletonTest) {
|
||||
Assimp::Importer importer;
|
||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/animation_with_skeleton.fbx", aiProcess_ValidateDataStructure);
|
||||
ASSERT_NE(nullptr, scene);
|
||||
ASSERT_TRUE(scene->mRootNode);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
|
||||
#include "AbstractImportExportBase.h"
|
||||
|
||||
#include <assimp/scene.h>
|
||||
#include "UnitTestPCH.h"
|
||||
|
||||
#include <assimp/Importer.hpp>
|
||||
|
@ -51,11 +53,12 @@ public:
|
|||
bool importerTest() override {
|
||||
Assimp::Importer importer;
|
||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/OpenGEX/Example.ogex", 0);
|
||||
EXPECT_EQ(1u, scene->mNumMeshes);
|
||||
return nullptr != scene;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(utOpenGEXImportExport, importLWSFromFileTest) {
|
||||
TEST_F(utOpenGEXImportExport, importOpenGexFromFileTest) {
|
||||
EXPECT_TRUE(importerTest());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue