mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-12 15:14:35 +00:00
update assimp lib
This commit is contained in:
parent
03a348deb7
commit
d3f8fee74e
1725 changed files with 196314 additions and 62009 deletions
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "FBXUtil.h"
|
||||
#include <assimp/defs.h>
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
#include <assimp/Exceptional.h>
|
||||
#include <assimp/ByteSwapper.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
|
|
@ -139,6 +140,7 @@ size_t Offset(const char* begin, const char* cursor) {
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AI_WONT_RETURN void TokenizeError(const std::string& message, const char* begin, const char* cursor) AI_WONT_RETURN_SUFFIX;
|
||||
void TokenizeError(const std::string& message, const char* begin, const char* cursor) {
|
||||
TokenizeError(message, Offset(begin, cursor));
|
||||
}
|
||||
|
|
@ -341,8 +343,7 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input,
|
|||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end, bool const is64bits)
|
||||
{
|
||||
bool ReadScope(TokenList &output_tokens, StackAllocator &token_allocator, const char *input, const char *&cursor, const char *end, bool const is64bits) {
|
||||
// the first word contains the offset at which this block ends
|
||||
const uint64_t end_offset = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
|
||||
|
||||
|
|
@ -408,7 +409,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
|
|||
|
||||
// XXX this is vulnerable to stack overflowing ..
|
||||
while(Offset(input, cursor) < end_offset - sentinel_block_length) {
|
||||
ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, is64bits);
|
||||
ReadScope(output_tokens, token_allocator, input, cursor, input + end_offset - sentinel_block_length, is64bits);
|
||||
}
|
||||
output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
|
||||
|
||||
|
|
@ -431,8 +432,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent
|
||||
void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
|
||||
{
|
||||
void TokenizeBinary(TokenList &output_tokens, const char *input, size_t length, StackAllocator &token_allocator) {
|
||||
ai_assert(input);
|
||||
ASSIMP_LOG_DEBUG("Tokenizing binary FBX file");
|
||||
|
||||
|
|
@ -465,7 +465,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
|
|||
try
|
||||
{
|
||||
while (cursor < end ) {
|
||||
if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) {
|
||||
if (!ReadScope(output_tokens, token_allocator, input, cursor, input + length, is64bits)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -55,6 +55,7 @@ const char NULL_RECORD[NumNullRecords] = { // 25 null bytes in 64-bit and 13 nul
|
|||
'\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?)
|
||||
static std::string NULL_RECORD_STRING(NumNullRecords, '\0');
|
||||
const std::string SEPARATOR = { '\x00', '\x01' }; // for use inside strings
|
||||
const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import
|
||||
const int64_t SECOND = 46186158000; // FBX's kTime unit
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -55,9 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <assimp/MathFunctions.h>
|
||||
#include <assimp/StringComparison.h>
|
||||
|
||||
#include <assimp/scene.h>
|
||||
|
||||
#include <assimp/CreateAnimMesh.h>
|
||||
#include <assimp/StringUtils.h>
|
||||
#include <assimp/commonMetaData.h>
|
||||
|
|
@ -78,6 +76,53 @@ using namespace Util;
|
|||
|
||||
#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000LL
|
||||
|
||||
static void correctRootTransform(const aiScene *scene) {
|
||||
if (scene == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (scene->mMetaData == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t UpAxis = 1, UpAxisSign = 1, FrontAxis = 2, FrontAxisSign = 1, CoordAxis = 0, CoordAxisSign = 1;
|
||||
double UnitScaleFactor = 1.0;
|
||||
for (unsigned MetadataIndex = 0; MetadataIndex < scene->mMetaData->mNumProperties; ++MetadataIndex) {
|
||||
if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "UpAxis") == 0) {
|
||||
scene->mMetaData->Get<int32_t>(MetadataIndex, UpAxis);
|
||||
}
|
||||
if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "UpAxisSign") == 0) {
|
||||
scene->mMetaData->Get<int32_t>(MetadataIndex, UpAxisSign);
|
||||
}
|
||||
if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "FrontAxis") == 0) {
|
||||
scene->mMetaData->Get<int32_t>(MetadataIndex, FrontAxis);
|
||||
}
|
||||
if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "FrontAxisSign") == 0) {
|
||||
scene->mMetaData->Get<int32_t>(MetadataIndex, FrontAxisSign);
|
||||
}
|
||||
if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "CoordAxis") == 0) {
|
||||
scene->mMetaData->Get<int32_t>(MetadataIndex, CoordAxis);
|
||||
}
|
||||
if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "CoordAxisSign") == 0) {
|
||||
scene->mMetaData->Get<int32_t>(MetadataIndex, CoordAxisSign);
|
||||
}
|
||||
if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "UnitScaleFactor") == 0) {
|
||||
scene->mMetaData->Get<double>(MetadataIndex, UnitScaleFactor);
|
||||
}
|
||||
}
|
||||
|
||||
aiVector3D upVec, forwardVec, rightVec;
|
||||
upVec[UpAxis] = UpAxisSign * static_cast<float>(UnitScaleFactor);
|
||||
forwardVec[FrontAxis] = FrontAxisSign * static_cast<float>(UnitScaleFactor);
|
||||
rightVec[CoordAxis] = CoordAxisSign * (float)UnitScaleFactor;
|
||||
|
||||
aiMatrix4x4 mat(rightVec.x, rightVec.y, rightVec.z, 0.0f,
|
||||
upVec.x, upVec.y, upVec.z, 0.0f,
|
||||
forwardVec.x, forwardVec.y, forwardVec.z, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f);
|
||||
scene->mRootNode->mTransformation *= mat;
|
||||
}
|
||||
|
||||
FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBones) :
|
||||
defaultMaterialIndex(),
|
||||
mMeshes(),
|
||||
|
|
@ -93,6 +138,8 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo
|
|||
mSceneOut(out),
|
||||
doc(doc),
|
||||
mRemoveEmptyBones(removeEmptyBones) {
|
||||
|
||||
|
||||
// animations need to be converted first since this will
|
||||
// populate the node_anim_chain_bits map, which is needed
|
||||
// to determine which nodes need to be generated.
|
||||
|
|
@ -119,7 +166,7 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo
|
|||
if (mat) {
|
||||
|
||||
if (materials_converted.find(mat) == materials_converted.end()) {
|
||||
ConvertMaterial(*mat, 0);
|
||||
ConvertMaterial(*mat, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -133,6 +180,10 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo
|
|||
// need not contain geometry (i.e. camera animations, raw armatures).
|
||||
if (out->mNumMeshes == 0) {
|
||||
out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
|
||||
} else {
|
||||
// Apply the FBX axis metadata unless requested not to
|
||||
if (!doc.Settings().ignoreUpDirection)
|
||||
correctRootTransform(mSceneOut);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -196,7 +247,7 @@ struct FBXConverter::PotentialNode {
|
|||
/// todo: get bone from stack
|
||||
/// todo: make map of aiBone* to aiNode*
|
||||
/// then update convert clusters to the new format
|
||||
void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node) {
|
||||
void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node, const aiMatrix4x4& parent_transform) {
|
||||
const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(id, "Model");
|
||||
|
||||
std::vector<PotentialNode> nodes;
|
||||
|
|
@ -227,7 +278,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;
|
||||
aiMatrix4x4 new_abs_transform = parent_transform;
|
||||
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
|
||||
|
|
@ -261,6 +312,8 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
|
|||
|
||||
child->mParent = last_parent;
|
||||
last_parent = child.mNode;
|
||||
|
||||
new_abs_transform *= child->mTransformation;
|
||||
}
|
||||
|
||||
// attach geometry
|
||||
|
|
@ -283,6 +336,8 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
|
|||
|
||||
postnode->mParent = last_parent;
|
||||
last_parent = postnode.mNode;
|
||||
|
||||
new_abs_transform *= postnode->mTransformation;
|
||||
}
|
||||
} else {
|
||||
// free the nodes we allocated as we don't need them
|
||||
|
|
@ -290,7 +345,7 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
|
|||
}
|
||||
|
||||
// recursion call - child nodes
|
||||
ConvertNodes(model->ID(), last_parent, root_node);
|
||||
ConvertNodes(model->ID(), last_parent, root_node, new_abs_transform);
|
||||
|
||||
if (doc.Settings().readLights) {
|
||||
ConvertLights(*model, node_name);
|
||||
|
|
@ -305,18 +360,15 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
|
|||
}
|
||||
}
|
||||
|
||||
if (nodes.size()) {
|
||||
parent->mChildren = new aiNode *[nodes.size()]();
|
||||
parent->mNumChildren = static_cast<unsigned int>(nodes.size());
|
||||
|
||||
for (unsigned int i = 0; i < nodes.size(); ++i)
|
||||
{
|
||||
parent->mChildren[i] = nodes[i].mOwnership.release();
|
||||
}
|
||||
nodes.clear();
|
||||
} else {
|
||||
if (nodes.empty()) {
|
||||
parent->mNumChildren = 0;
|
||||
parent->mChildren = nullptr;
|
||||
} else {
|
||||
parent->mChildren = new aiNode *[nodes.size()]();
|
||||
parent->mNumChildren = static_cast<unsigned int>(nodes.size());
|
||||
for (unsigned int i = 0; i < nodes.size(); ++i) {
|
||||
parent->mChildren[i] = nodes[i].mOwnership.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -424,16 +476,32 @@ void FBXConverter::ConvertCamera(const Camera &cam, const std::string &orig_name
|
|||
|
||||
out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
|
||||
|
||||
// NOTE: Camera mPosition, mLookAt and mUp must be set to default here.
|
||||
// All transformations to the camera will be handled by its node in the scenegraph.
|
||||
out_camera->mPosition = aiVector3D(0.0f);
|
||||
out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f);
|
||||
out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
|
||||
|
||||
out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView());
|
||||
// NOTE: Some software (maya) does not put FieldOfView in FBX, so we compute
|
||||
// mHorizontalFOV from FocalLength and FilmWidth with unit conversion.
|
||||
|
||||
out_camera->mClipPlaneNear = cam.NearPlane();
|
||||
out_camera->mClipPlaneFar = cam.FarPlane();
|
||||
// TODO: This is not a complete solution for how FBX cameras can be stored.
|
||||
// TODO: Incorporate non-square pixel aspect ratio.
|
||||
// TODO: FBX aperture mode might be storing vertical FOV in need of conversion with aspect ratio.
|
||||
|
||||
float fov_deg = cam.FieldOfView();
|
||||
// If FOV not specified in file, compute using FilmWidth and FocalLength.
|
||||
if (fov_deg == kFovUnknown) {
|
||||
float film_width_inches = cam.FilmWidth();
|
||||
float focal_length_mm = cam.FocalLength();
|
||||
ASSIMP_LOG_VERBOSE_DEBUG("FBX FOV unspecified. Computing from FilmWidth (", film_width_inches, "inches) and FocalLength (", focal_length_mm, "mm).");
|
||||
double half_fov_rad = std::atan2(film_width_inches * 25.4 * 0.5, focal_length_mm);
|
||||
out_camera->mHorizontalFOV = static_cast<float>(half_fov_rad);
|
||||
} else {
|
||||
// FBX fov is full-view degrees. We want half-view radians.
|
||||
out_camera->mHorizontalFOV = AI_DEG_TO_RAD(fov_deg) * 0.5f;
|
||||
}
|
||||
|
||||
out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView());
|
||||
out_camera->mClipPlaneNear = cam.NearPlane();
|
||||
out_camera->mClipPlaneFar = cam.FarPlane();
|
||||
}
|
||||
|
|
@ -562,16 +630,17 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot
|
|||
bool is_id[3] = { true, true, true };
|
||||
|
||||
aiMatrix4x4 temp[3];
|
||||
if (std::fabs(rotation.z) > angle_epsilon) {
|
||||
aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z), temp[2]);
|
||||
const auto rot = AI_DEG_TO_RAD(rotation);
|
||||
if (std::fabs(rot.z) > angle_epsilon) {
|
||||
aiMatrix4x4::RotationZ(rot.z, temp[2]);
|
||||
is_id[2] = false;
|
||||
}
|
||||
if (std::fabs(rotation.y) > angle_epsilon) {
|
||||
aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y), temp[1]);
|
||||
if (std::fabs(rot.y) > angle_epsilon) {
|
||||
aiMatrix4x4::RotationY(rot.y, temp[1]);
|
||||
is_id[1] = false;
|
||||
}
|
||||
if (std::fabs(rotation.x) > angle_epsilon) {
|
||||
aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x), temp[0]);
|
||||
if (std::fabs(rot.x) > angle_epsilon) {
|
||||
aiMatrix4x4::RotationX(rot.x, temp[0]);
|
||||
is_id[0] = false;
|
||||
}
|
||||
|
||||
|
|
@ -643,13 +712,12 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot
|
|||
bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
|
||||
const PropertyTable &props = model.Props();
|
||||
|
||||
const auto zero_epsilon = ai_epsilon;
|
||||
const auto zero_epsilon = Math::getEpsilon<ai_real>();
|
||||
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);
|
||||
|
||||
if (comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation ||
|
||||
comp == TransformationComp_PreRotation || comp == TransformationComp_PostRotation) {
|
||||
if (comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -876,8 +944,12 @@ void FBXConverter::SetupNodeMetadata(const Model &model, aiNode &nd) {
|
|||
data->Set(index++, prop.first, interpretedBool->Value());
|
||||
} else if (const TypedProperty<int> *interpretedInt = prop.second->As<TypedProperty<int>>()) {
|
||||
data->Set(index++, prop.first, interpretedInt->Value());
|
||||
} else if (const TypedProperty<uint32_t> *interpretedUInt = prop.second->As<TypedProperty<uint32_t>>()) {
|
||||
data->Set(index++, prop.first, interpretedUInt->Value());
|
||||
} else if (const TypedProperty<uint64_t> *interpretedUint64 = prop.second->As<TypedProperty<uint64_t>>()) {
|
||||
data->Set(index++, prop.first, interpretedUint64->Value());
|
||||
} else if (const TypedProperty<int64_t> *interpretedint64 = prop.second->As<TypedProperty<int64_t>>()) {
|
||||
data->Set(index++, prop.first, interpretedint64->Value());
|
||||
} else if (const TypedProperty<float> *interpretedFloat = prop.second->As<TypedProperty<float>>()) {
|
||||
data->Set(index++, prop.first, interpretedFloat->Value());
|
||||
} else if (const TypedProperty<std::string> *interpretedString = prop.second->As<TypedProperty<std::string>>()) {
|
||||
|
|
@ -1179,19 +1251,27 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
|
|||
std::vector<aiAnimMesh *> animMeshes;
|
||||
for (const BlendShape *blendShape : mesh.GetBlendShapes()) {
|
||||
for (const BlendShapeChannel *blendShapeChannel : blendShape->BlendShapeChannels()) {
|
||||
const std::vector<const ShapeGeometry *> &shapeGeometries = blendShapeChannel->GetShapeGeometries();
|
||||
for (size_t i = 0; i < shapeGeometries.size(); i++) {
|
||||
aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh);
|
||||
const ShapeGeometry *shapeGeometry = shapeGeometries.at(i);
|
||||
const std::vector<aiVector3D> &curVertices = shapeGeometry->GetVertices();
|
||||
const std::vector<aiVector3D> &curNormals = shapeGeometry->GetNormals();
|
||||
const std::vector<unsigned int> &curIndices = shapeGeometry->GetIndices();
|
||||
const auto& shapeGeometries = blendShapeChannel->GetShapeGeometries();
|
||||
for (const ShapeGeometry *shapeGeometry : shapeGeometries) {
|
||||
const auto &curNormals = shapeGeometry->GetNormals();
|
||||
aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh, true, !curNormals.empty());
|
||||
const auto &curVertices = shapeGeometry->GetVertices();
|
||||
const auto &curIndices = shapeGeometry->GetIndices();
|
||||
//losing channel name if using shapeGeometry->Name()
|
||||
animMesh->mName.Set(FixAnimMeshName(blendShapeChannel->Name()));
|
||||
// if blendShapeChannel Name is empty or doesn't have a ".", add geoMetryName;
|
||||
auto aniName = FixAnimMeshName(blendShapeChannel->Name());
|
||||
auto geoMetryName = FixAnimMeshName(shapeGeometry->Name());
|
||||
if (aniName.empty()) {
|
||||
aniName = geoMetryName;
|
||||
}
|
||||
else if (aniName.find('.') == aniName.npos) {
|
||||
aniName += "." + geoMetryName;
|
||||
}
|
||||
animMesh->mName.Set(aniName);
|
||||
for (size_t j = 0; j < curIndices.size(); j++) {
|
||||
const unsigned int curIndex = curIndices.at(j);
|
||||
aiVector3D vertex = curVertices.at(j);
|
||||
aiVector3D normal = curNormals.at(j);
|
||||
aiVector3D normal = curNormals.empty() ? aiVector3D() : curNormals.at(j);
|
||||
unsigned int count = 0;
|
||||
const unsigned int *outIndices = mesh.ToOutputVertexIndex(curIndex, count);
|
||||
for (unsigned int k = 0; k < count; k++) {
|
||||
|
|
@ -1409,18 +1489,17 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
|
|||
std::vector<aiAnimMesh *> animMeshes;
|
||||
for (const BlendShape *blendShape : mesh.GetBlendShapes()) {
|
||||
for (const BlendShapeChannel *blendShapeChannel : blendShape->BlendShapeChannels()) {
|
||||
const std::vector<const ShapeGeometry *> &shapeGeometries = blendShapeChannel->GetShapeGeometries();
|
||||
for (size_t i = 0; i < shapeGeometries.size(); i++) {
|
||||
aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh);
|
||||
const ShapeGeometry *shapeGeometry = shapeGeometries.at(i);
|
||||
const std::vector<aiVector3D> &curVertices = shapeGeometry->GetVertices();
|
||||
const std::vector<aiVector3D> &curNormals = shapeGeometry->GetNormals();
|
||||
const std::vector<unsigned int> &curIndices = shapeGeometry->GetIndices();
|
||||
const auto& shapeGeometries = blendShapeChannel->GetShapeGeometries();
|
||||
for (const ShapeGeometry *shapeGeometry : shapeGeometries) {
|
||||
const auto& curNormals = shapeGeometry->GetNormals();
|
||||
aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh, true, !curNormals.empty());
|
||||
const auto& curVertices = shapeGeometry->GetVertices();
|
||||
const auto& curIndices = shapeGeometry->GetIndices();
|
||||
animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name()));
|
||||
for (size_t j = 0; j < curIndices.size(); j++) {
|
||||
unsigned int curIndex = curIndices.at(j);
|
||||
aiVector3D vertex = curVertices.at(j);
|
||||
aiVector3D normal = curNormals.at(j);
|
||||
aiVector3D normal = curNormals.empty() ? aiVector3D() : curNormals.at(j);
|
||||
unsigned int count = 0;
|
||||
const unsigned int *outIndices = mesh.ToOutputVertexIndex(curIndex, count);
|
||||
for (unsigned int k = 0; k < count; k++) {
|
||||
|
|
@ -1458,7 +1537,9 @@ static void copyBoneToSkeletonBone(aiMesh *mesh, aiBone *bone, aiSkeletonBone *s
|
|||
skeletonBone->mWeights = bone->mWeights;
|
||||
skeletonBone->mOffsetMatrix = bone->mOffsetMatrix;
|
||||
skeletonBone->mMeshId = mesh;
|
||||
#ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
|
||||
skeletonBone->mNode = bone->mNode;
|
||||
#endif
|
||||
skeletonBone->mParent = -1;
|
||||
}
|
||||
|
||||
|
|
@ -1566,7 +1647,7 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const ai
|
|||
out->mBones = nullptr;
|
||||
out->mNumBones = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
out->mBones = new aiBone *[bones.size()]();
|
||||
out->mNumBones = static_cast<unsigned int>(bones.size());
|
||||
|
|
@ -1575,7 +1656,7 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const ai
|
|||
|
||||
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, const aiMatrix4x4 & /* absolute_transform*/,
|
||||
std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform,
|
||||
aiNode *) {
|
||||
ai_assert(cluster != nullptr); // make sure cluster valid
|
||||
|
||||
|
|
@ -1592,16 +1673,16 @@ void FBXConverter::ConvertCluster(std::vector<aiBone*> &local_mesh_bones, const
|
|||
bone = new aiBone();
|
||||
bone->mName = bone_name;
|
||||
|
||||
bone->mOffsetMatrix = cluster->Transform();
|
||||
//bone->mOffsetMatrix = cluster->Transform();
|
||||
// store local transform link for post processing
|
||||
/*
|
||||
|
||||
bone->mOffsetMatrix = cluster->TransformLink();
|
||||
bone->mOffsetMatrix.Inverse();
|
||||
|
||||
aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform;
|
||||
const aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform;
|
||||
|
||||
bone->mOffsetMatrix = bone->mOffsetMatrix * matrix; // * mesh_offset
|
||||
*/
|
||||
|
||||
//
|
||||
// Now calculate the aiVertexWeights
|
||||
//
|
||||
|
|
@ -1784,7 +1865,7 @@ aiString FBXConverter::GetTexturePath(const Texture *tex) {
|
|||
// We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
|
||||
// This may occur on this case too, it has to be studied
|
||||
path.data[0] = '*';
|
||||
path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
|
||||
path.length = 1 + ASSIMP_itoa10(path.data + 1, AI_MAXLEN - 1, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2052,6 +2133,10 @@ void FBXConverter::SetTextureProperties(aiMaterial *out_mat, const TextureMap &_
|
|||
TrySetTextureProperties(out_mat, _textures, "Maya|emissionColor", aiTextureType_EMISSION_COLOR, mesh);
|
||||
TrySetTextureProperties(out_mat, _textures, "Maya|metalness", aiTextureType_METALNESS, mesh);
|
||||
TrySetTextureProperties(out_mat, _textures, "Maya|diffuseRoughness", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
|
||||
TrySetTextureProperties(out_mat, _textures, "Maya|base", aiTextureType_MAYA_BASE, mesh);
|
||||
TrySetTextureProperties(out_mat, _textures, "Maya|specular", aiTextureType_MAYA_SPECULAR, mesh);
|
||||
TrySetTextureProperties(out_mat, _textures, "Maya|specularColor", aiTextureType_MAYA_SPECULAR_COLOR, mesh);
|
||||
TrySetTextureProperties(out_mat, _textures, "Maya|specularRoughness", aiTextureType_MAYA_SPECULAR_ROUGHNESS, mesh);
|
||||
|
||||
// Maya stingray
|
||||
TrySetTextureProperties(out_mat, _textures, "Maya|TEX_color_map", aiTextureType_BASE_COLOR, mesh);
|
||||
|
|
@ -2364,7 +2449,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
|
|||
|
||||
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
|
||||
path.data[0] = '*';
|
||||
path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
|
||||
path.length = 1 + ASSIMP_itoa10(path.data + 1, AI_MAXLEN - 1, index);
|
||||
}
|
||||
|
||||
out_mat->AddProperty(&path, (name + "|file").c_str(), aiTextureType_UNKNOWN, 0);
|
||||
|
|
@ -2730,7 +2815,7 @@ void FBXConverter::ProcessMorphAnimDatas(std::map<std::string, morphAnimData *>
|
|||
auto geoIt = std::find(model->GetGeometry().begin(), model->GetGeometry().end(), geo);
|
||||
auto geoIndex = static_cast<unsigned int>(std::distance(model->GetGeometry().begin(), geoIt));
|
||||
auto name = aiString(FixNodeName(model->Name() + "*"));
|
||||
name.length = 1 + ASSIMP_itoa10(name.data + name.length, MAXLEN - 1, geoIndex);
|
||||
name.length = 1 + ASSIMP_itoa10(name.data + name.length, AI_MAXLEN - 1, geoIndex);
|
||||
morphAnimData *animData;
|
||||
auto animIt = morphAnimDatas->find(name.C_Str());
|
||||
if (animIt == morphAnimDatas->end()) {
|
||||
|
|
@ -3197,7 +3282,6 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
|
|||
aiVector3D defTranslate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f));
|
||||
aiVector3D defRotation = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f));
|
||||
aiVector3D defScale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f));
|
||||
aiQuaternion defQuat = EulerToQuaternion(defRotation, rotOrder);
|
||||
|
||||
aiVectorKey* outTranslations = new aiVectorKey[keyCount];
|
||||
aiQuatKey* outRotations = new aiQuatKey[keyCount];
|
||||
|
|
@ -3215,6 +3299,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
|
|||
if (keyframeLists[TransformationComp_Rotation].size() > 0) {
|
||||
InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], defRotation, maxTime, minTime, rotOrder);
|
||||
} else {
|
||||
aiQuaternion defQuat = EulerToQuaternion(defRotation, rotOrder);
|
||||
for (size_t i = 0; i < keyCount; ++i) {
|
||||
outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps;
|
||||
outRotations[i].mValue = defQuat;
|
||||
|
|
@ -3231,7 +3316,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
|
|||
}
|
||||
|
||||
bool ok = false;
|
||||
|
||||
|
||||
const auto zero_epsilon = ai_epsilon;
|
||||
|
||||
const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
@ -134,7 +134,7 @@ private:
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// collect and assign child nodes
|
||||
void ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node);
|
||||
void ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node, const aiMatrix4x4& parent_transform = aiMatrix4x4());
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConvertLights(const Model& model, const std::string &orig_name );
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ Cluster::Cluster(uint64_t id, const Element& element, const Document& doc, const
|
|||
transform = ReadMatrix(Transform);
|
||||
transformLink = ReadMatrix(TransformLink);
|
||||
|
||||
// it is actually possible that there be Deformer's with no weights
|
||||
// it is actually possible that there are Deformer's with no weights
|
||||
if (!!Indexes != !!Weights) {
|
||||
DOMError("either Indexes or Weights are missing from Cluster",&element);
|
||||
}
|
||||
|
|
@ -154,8 +154,10 @@ BlendShape::BlendShape(uint64_t id, const Element& element, const Document& doc,
|
|||
for (const Connection* con : conns) {
|
||||
const BlendShapeChannel* const bspc = ProcessSimpleConnection<BlendShapeChannel>(*con, false, "BlendShapeChannel -> BlendShape", element);
|
||||
if (bspc) {
|
||||
blendShapeChannels.push_back(bspc);
|
||||
continue;
|
||||
auto pr = blendShapeChannels.insert(bspc);
|
||||
if (!pr.second) {
|
||||
FBXImporter::LogWarn("there is the same blendShapeChannel id ", bspc->ID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -179,8 +181,10 @@ BlendShapeChannel::BlendShapeChannel(uint64_t id, const Element& element, const
|
|||
for (const Connection* con : conns) {
|
||||
const ShapeGeometry* const sg = ProcessSimpleConnection<ShapeGeometry>(*con, false, "Shape -> BlendShapeChannel", element);
|
||||
if (sg) {
|
||||
shapeGeometries.push_back(sg);
|
||||
continue;
|
||||
auto pr = shapeGeometries.insert(sg);
|
||||
if (!pr.second) {
|
||||
FBXImporter::LogWarn("there is the same shapeGeometrie id ", sg->ID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ const Object* LazyObject::Get(bool dieOnError) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (object.get()) {
|
||||
if (object) {
|
||||
return object.get();
|
||||
}
|
||||
|
||||
|
|
@ -199,6 +199,14 @@ const Object* LazyObject::Get(bool dieOnError) {
|
|||
object.reset(new AnimationCurveNode(id,element,name,doc));
|
||||
}
|
||||
}
|
||||
catch (std::bad_alloc&) {
|
||||
// out-of-memory is unrecoverable and should always lead to a failure
|
||||
|
||||
flags &= ~BEING_CONSTRUCTED;
|
||||
flags |= FAILED_TO_CONSTRUCT;
|
||||
|
||||
throw;
|
||||
}
|
||||
catch(std::exception& ex) {
|
||||
flags &= ~BEING_CONSTRUCTED;
|
||||
flags |= FAILED_TO_CONSTRUCT;
|
||||
|
|
@ -214,7 +222,7 @@ const Object* LazyObject::Get(bool dieOnError) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (!object.get()) {
|
||||
if (!object) {
|
||||
//DOMError("failed to convert element to DOM object, class: " + classtag + ", name: " + name,&element);
|
||||
}
|
||||
|
||||
|
|
@ -235,7 +243,7 @@ FileGlobalSettings::FileGlobalSettings(const Document &doc, std::shared_ptr<cons
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Document::Document(const Parser& parser, const ImportSettings& settings) :
|
||||
Document::Document(Parser& parser, const ImportSettings& settings) :
|
||||
settings(settings), parser(parser) {
|
||||
ASSIMP_LOG_DEBUG("Creating FBX Document");
|
||||
|
||||
|
|
@ -257,13 +265,17 @@ Document::Document(const Parser& parser, const ImportSettings& settings) :
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Document::~Document() {
|
||||
for(ObjectMap::value_type& v : objects) {
|
||||
delete v.second;
|
||||
Document::~Document()
|
||||
{
|
||||
// The document does not own the memory for the following objects, but we need to call their d'tor
|
||||
// so they can properly free memory like string members:
|
||||
|
||||
for (ObjectMap::value_type &v : objects) {
|
||||
delete_LazyObject(v.second);
|
||||
}
|
||||
|
||||
for(ConnectionMap::value_type& v : src_connections) {
|
||||
delete v.second;
|
||||
for (ConnectionMap::value_type &v : src_connections) {
|
||||
delete_Connection(v.second);
|
||||
}
|
||||
// |dest_connections| contain the same Connection objects as the |src_connections|
|
||||
}
|
||||
|
|
@ -336,7 +348,7 @@ void Document::ReadGlobalSettings() {
|
|||
DOMError("GlobalSettings dictionary contains no property table");
|
||||
}
|
||||
|
||||
globals.reset(new FileGlobalSettings(*this, props));
|
||||
globals.reset(new FileGlobalSettings(*this, std::move(props)));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
@ -348,9 +360,11 @@ void Document::ReadObjects() {
|
|||
DOMError("no Objects dictionary found");
|
||||
}
|
||||
|
||||
StackAllocator &allocator = parser.GetAllocator();
|
||||
|
||||
// add a dummy entry to represent the Model::RootNode object (id 0),
|
||||
// which is only indirectly defined in the input file
|
||||
objects[0] = new LazyObject(0L, *eobjects, *this);
|
||||
objects[0] = new_LazyObject(0L, *eobjects, *this);
|
||||
|
||||
const Scope& sobjects = *eobjects->Compound();
|
||||
for(const ElementMap::value_type& el : sobjects.Elements()) {
|
||||
|
|
@ -373,11 +387,13 @@ void Document::ReadObjects() {
|
|||
DOMError("encountered object with implicitly defined id 0",el.second);
|
||||
}
|
||||
|
||||
if(objects.find(id) != objects.end()) {
|
||||
const auto foundObject = objects.find(id);
|
||||
if(foundObject != objects.end()) {
|
||||
DOMWarning("encountered duplicate object id, ignoring first occurrence",el.second);
|
||||
delete_LazyObject(foundObject->second);
|
||||
}
|
||||
|
||||
objects[id] = new LazyObject(id, *el.second, *this);
|
||||
objects[id] = new_LazyObject(id, *el.second, *this);
|
||||
|
||||
// grab all animation stacks upfront since there is no listing of them
|
||||
if(!strcmp(el.first.c_str(),"AnimationStack")) {
|
||||
|
|
@ -444,8 +460,10 @@ void Document::ReadPropertyTemplates() {
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Document::ReadConnections() {
|
||||
const Scope& sc = parser.GetRootScope();
|
||||
void Document::ReadConnections()
|
||||
{
|
||||
StackAllocator &allocator = parser.GetAllocator();
|
||||
const Scope &sc = parser.GetRootScope();
|
||||
// read property templates from "Definitions" section
|
||||
const Element* const econns = sc["Connections"];
|
||||
if(!econns || !econns->Compound()) {
|
||||
|
|
@ -484,7 +502,7 @@ void Document::ReadConnections() {
|
|||
}
|
||||
|
||||
// add new connection
|
||||
const Connection* const c = new Connection(insertionOrder++,src,dest,prop,*this);
|
||||
const Connection* const c = new_Connection(insertionOrder++,src,dest,prop,*this);
|
||||
src_connections.insert(ConnectionMap::value_type(src,c));
|
||||
dest_connections.insert(ConnectionMap::value_type(dest,c));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define INCLUDED_AI_FBX_DOCUMENT_H
|
||||
|
||||
#include <numeric>
|
||||
#include <unordered_set>
|
||||
#include <stdint.h>
|
||||
#include <assimp/mesh.h>
|
||||
#include "FBXProperties.h"
|
||||
|
|
@ -54,9 +55,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define _AI_CONCAT(a,b) a ## b
|
||||
#define AI_CONCAT(a,b) _AI_CONCAT(a,b)
|
||||
|
||||
|
||||
namespace Assimp {
|
||||
namespace FBX {
|
||||
|
||||
// Use an 'illegal' default FOV value to detect if the FBX camera has set the FOV.
|
||||
static const float kFovUnknown = -1.0f;
|
||||
|
||||
|
||||
class Parser;
|
||||
class Object;
|
||||
struct ImportSettings;
|
||||
|
|
@ -80,6 +86,10 @@ class BlendShape;
|
|||
class Skin;
|
||||
class Cluster;
|
||||
|
||||
#define new_LazyObject new (allocator.Allocate(sizeof(LazyObject))) LazyObject
|
||||
#define new_Connection new (allocator.Allocate(sizeof(Connection))) Connection
|
||||
#define delete_LazyObject(_p) (_p)->~LazyObject()
|
||||
#define delete_Connection(_p) (_p)->~Connection()
|
||||
|
||||
/** Represents a delay-parsed FBX objects. Many objects in the scene
|
||||
* are not needed by assimp, so it makes no sense to parse them
|
||||
|
|
@ -168,7 +178,7 @@ public:
|
|||
|
||||
const PropertyTable& Props() const {
|
||||
ai_assert(props.get());
|
||||
return *props.get();
|
||||
return *props;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -242,7 +252,7 @@ public:
|
|||
fbx_simple_property(FilmAspectRatio, float, 1.0f)
|
||||
fbx_simple_property(ApertureMode, int, 0)
|
||||
|
||||
fbx_simple_property(FieldOfView, float, 1.0f)
|
||||
fbx_simple_property(FieldOfView, float, kFovUnknown)
|
||||
fbx_simple_property(FocalLength, float, 1.0f)
|
||||
};
|
||||
|
||||
|
|
@ -432,7 +442,7 @@ public:
|
|||
|
||||
const PropertyTable& Props() const {
|
||||
ai_assert(props.get());
|
||||
return *props.get();
|
||||
return *props;
|
||||
}
|
||||
|
||||
/** Get material links */
|
||||
|
|
@ -503,7 +513,7 @@ public:
|
|||
|
||||
const PropertyTable& Props() const {
|
||||
ai_assert(props.get());
|
||||
return *props.get();
|
||||
return *props;
|
||||
}
|
||||
|
||||
// return a 4-tuple
|
||||
|
|
@ -618,7 +628,7 @@ public:
|
|||
|
||||
const PropertyTable& Props() const {
|
||||
ai_assert(props.get());
|
||||
return *props.get();
|
||||
return *props;
|
||||
}
|
||||
|
||||
const uint8_t* Content() const {
|
||||
|
|
@ -632,7 +642,7 @@ public:
|
|||
|
||||
uint8_t* RelinquishContent() {
|
||||
uint8_t* ptr = content;
|
||||
content = 0;
|
||||
content = nullptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
|
@ -663,7 +673,7 @@ public:
|
|||
|
||||
const PropertyTable& Props() const {
|
||||
ai_assert(props.get());
|
||||
return *props.get();
|
||||
return *props;
|
||||
}
|
||||
|
||||
const TextureMap& Textures() const {
|
||||
|
|
@ -735,7 +745,7 @@ public:
|
|||
|
||||
const PropertyTable& Props() const {
|
||||
ai_assert(props.get());
|
||||
return *props.get();
|
||||
return *props;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -780,7 +790,7 @@ public:
|
|||
|
||||
const PropertyTable& Props() const {
|
||||
ai_assert(props.get());
|
||||
return *props.get();
|
||||
return *props;
|
||||
}
|
||||
|
||||
/* the optional white list specifies a list of property names for which the caller
|
||||
|
|
@ -808,7 +818,7 @@ public:
|
|||
|
||||
const PropertyTable& Props() const {
|
||||
ai_assert(props.get());
|
||||
return *props.get();
|
||||
return *props;
|
||||
}
|
||||
|
||||
const AnimationLayerList& Layers() const {
|
||||
|
|
@ -829,7 +839,7 @@ public:
|
|||
|
||||
const PropertyTable& Props() const {
|
||||
ai_assert(props.get());
|
||||
return *props.get();
|
||||
return *props;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -855,14 +865,14 @@ public:
|
|||
return fullWeights;
|
||||
}
|
||||
|
||||
const std::vector<const ShapeGeometry*>& GetShapeGeometries() const {
|
||||
const std::unordered_set<const ShapeGeometry*>& GetShapeGeometries() const {
|
||||
return shapeGeometries;
|
||||
}
|
||||
|
||||
private:
|
||||
float percent;
|
||||
WeightArray fullWeights;
|
||||
std::vector<const ShapeGeometry*> shapeGeometries;
|
||||
std::unordered_set<const ShapeGeometry*> shapeGeometries;
|
||||
};
|
||||
|
||||
/** DOM class for BlendShape deformers */
|
||||
|
|
@ -872,12 +882,12 @@ public:
|
|||
|
||||
virtual ~BlendShape();
|
||||
|
||||
const std::vector<const BlendShapeChannel*>& BlendShapeChannels() const {
|
||||
const std::unordered_set<const BlendShapeChannel*>& BlendShapeChannels() const {
|
||||
return blendShapeChannels;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<const BlendShapeChannel*> blendShapeChannels;
|
||||
std::unordered_set<const BlendShapeChannel*> blendShapeChannels;
|
||||
};
|
||||
|
||||
/** DOM class for skin deformer clusters (aka sub-deformers) */
|
||||
|
|
@ -1018,7 +1028,7 @@ public:
|
|||
|
||||
const PropertyTable& Props() const {
|
||||
ai_assert(props.get());
|
||||
return *props.get();
|
||||
return *props;
|
||||
}
|
||||
|
||||
const Document& GetDocument() const {
|
||||
|
|
@ -1072,7 +1082,7 @@ private:
|
|||
/** DOM root for a FBX file */
|
||||
class Document {
|
||||
public:
|
||||
Document(const Parser& parser, const ImportSettings& settings);
|
||||
Document(Parser& parser, const ImportSettings& settings);
|
||||
|
||||
~Document();
|
||||
|
||||
|
|
@ -1097,7 +1107,7 @@ public:
|
|||
|
||||
const FileGlobalSettings& GlobalSettings() const {
|
||||
ai_assert(globals.get());
|
||||
return *globals.get();
|
||||
return *globals;
|
||||
}
|
||||
|
||||
const PropertyTemplateMap& Templates() const {
|
||||
|
|
@ -1156,7 +1166,7 @@ private:
|
|||
const ImportSettings& settings;
|
||||
|
||||
ObjectMap objects;
|
||||
const Parser& parser;
|
||||
Parser& parser;
|
||||
|
||||
PropertyTemplateMap templates;
|
||||
ConnectionMap src_connections;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -58,12 +58,11 @@ namespace Util {
|
|||
|
||||
/* DOM/Parse error reporting - does not return */
|
||||
AI_WONT_RETURN void DOMError(const std::string& message, const Token& token) AI_WONT_RETURN_SUFFIX;
|
||||
AI_WONT_RETURN void DOMError(const std::string& message, const Element* element = NULL) AI_WONT_RETURN_SUFFIX;
|
||||
AI_WONT_RETURN void DOMError(const std::string &message, const Element *element = nullptr) AI_WONT_RETURN_SUFFIX;
|
||||
|
||||
// does return
|
||||
void DOMWarning(const std::string& message, const Token& token);
|
||||
void DOMWarning(const std::string& message, const Element* element = NULL);
|
||||
|
||||
void DOMWarning(const std::string &message, const Element *element = nullptr);
|
||||
|
||||
// fetch a property table and the corresponding property template
|
||||
std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -360,7 +360,7 @@ void FBX::Node::EndBinary(
|
|||
bool has_children
|
||||
) {
|
||||
// if there were children, add a null record
|
||||
if (has_children) { s.PutString(Assimp::FBX::NULL_RECORD); }
|
||||
if (has_children) { s.PutString(Assimp::FBX::NULL_RECORD_STRING); }
|
||||
|
||||
// now go back and write initial pos
|
||||
this->end_pos = s.Tell();
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/StreamWriter.h> // StreamWriterLE
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace Assimp {
|
||||
|
|
@ -76,34 +77,30 @@ public: // constructors
|
|||
/// The class constructor with the name.
|
||||
Node(const std::string& n)
|
||||
: name(n)
|
||||
, properties()
|
||||
, children()
|
||||
, force_has_children( false ) {
|
||||
// empty
|
||||
}
|
||||
|
||||
// convenience template to construct with properties directly
|
||||
template <typename... More>
|
||||
Node(const std::string& n, const More... more)
|
||||
Node(const std::string& n, More&&... more)
|
||||
: name(n)
|
||||
, properties()
|
||||
, children()
|
||||
, force_has_children(false) {
|
||||
AddProperties(more...);
|
||||
AddProperties(std::forward<More>(more)...);
|
||||
}
|
||||
|
||||
public: // functions to add properties or children
|
||||
// add a single property to the node
|
||||
template <typename T>
|
||||
void AddProperty(T value) {
|
||||
properties.emplace_back(value);
|
||||
void AddProperty(T&& value) {
|
||||
properties.emplace_back(std::forward<T>(value));
|
||||
}
|
||||
|
||||
// convenience function to add multiple properties at once
|
||||
template <typename T, typename... More>
|
||||
void AddProperties(T value, More... more) {
|
||||
properties.emplace_back(value);
|
||||
AddProperties(more...);
|
||||
void AddProperties(T&& value, More&&... more) {
|
||||
properties.emplace_back(std::forward<T>(value));
|
||||
AddProperties(std::forward<More>(more)...);
|
||||
}
|
||||
void AddProperties() {}
|
||||
|
||||
|
|
@ -114,11 +111,11 @@ public: // functions to add properties or children
|
|||
template <typename... More>
|
||||
void AddChild(
|
||||
const std::string& name,
|
||||
More... more
|
||||
More&&... more
|
||||
) {
|
||||
FBX::Node c(name);
|
||||
c.AddProperties(more...);
|
||||
children.push_back(c);
|
||||
c.AddProperties(std::forward<More>(more)...);
|
||||
children.push_back(std::move(c));
|
||||
}
|
||||
|
||||
public: // support specifically for dealing with Properties70 nodes
|
||||
|
|
@ -146,10 +143,10 @@ public: // support specifically for dealing with Properties70 nodes
|
|||
const std::string& type,
|
||||
const std::string& type2,
|
||||
const std::string& flags,
|
||||
More... more
|
||||
More&&... more
|
||||
) {
|
||||
Node n("P");
|
||||
n.AddProperties(name, type, type2, flags, more...);
|
||||
n.AddProperties(name, type, type2, flags, std::forward<More>(more)...);
|
||||
AddChild(n);
|
||||
}
|
||||
|
||||
|
|
@ -214,7 +211,7 @@ public: // static member functions
|
|||
bool binary, int indent
|
||||
) {
|
||||
FBX::FBXExportProperty p(value);
|
||||
FBX::Node node(name, p);
|
||||
FBX::Node node(name, std::move(p));
|
||||
node.Dump(s, binary, indent);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -58,23 +58,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/mesh.h>
|
||||
|
||||
// Header files, standard library.
|
||||
#include <memory> // shared_ptr
|
||||
#include <string>
|
||||
#include <sstream> // stringstream
|
||||
#include <array>
|
||||
#include <ctime> // localtime, tm_*
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <unordered_set>
|
||||
#include <memory> // shared_ptr
|
||||
#include <numeric>
|
||||
#include <set>
|
||||
#include <sstream> // stringstream
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
// RESOURCES:
|
||||
// https://code.blender.org/2013/08/fbx-binary-file-format-specification/
|
||||
// https://wiki.blender.org/index.php/User:Mont29/Foundation/FBX_File_Structure
|
||||
|
||||
const ai_real DEG = ai_real( 57.29577951308232087679815481 ); // degrees per radian
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::FBX;
|
||||
|
||||
|
|
@ -390,7 +390,7 @@ void FBXExporter::WriteHeaderExtension ()
|
|||
raw[i] = uint8_t(GENERIC_FILEID[i]);
|
||||
}
|
||||
FBX::Node::WritePropertyNode(
|
||||
"FileId", raw, outstream, binary, indent
|
||||
"FileId", std::move(raw), outstream, binary, indent
|
||||
);
|
||||
FBX::Node::WritePropertyNode(
|
||||
"CreationTime", GENERIC_CTIME, outstream, binary, indent
|
||||
|
|
@ -680,9 +680,9 @@ void FBXExporter::WriteDefinitions ()
|
|||
pt = FBX::Node("PropertyTemplate", "FBXAnimLayer");
|
||||
p = FBX::Node("Properties70");
|
||||
p.AddP70("Weight", "Number", "", "A", double(100));
|
||||
p.AddP70bool("Mute", 0);
|
||||
p.AddP70bool("Solo", 0);
|
||||
p.AddP70bool("Lock", 0);
|
||||
p.AddP70bool("Mute", false);
|
||||
p.AddP70bool("Solo", false);
|
||||
p.AddP70bool("Lock", false);
|
||||
p.AddP70color("Color", 0.8, 0.8, 0.8);
|
||||
p.AddP70("BlendMode", "enum", "", "", int32_t(0));
|
||||
p.AddP70("RotationAccumulationMode", "enum", "", "", int32_t(0));
|
||||
|
|
@ -732,42 +732,42 @@ void FBXExporter::WriteDefinitions ()
|
|||
p.AddP70vector("RotationPivot", 0.0, 0.0, 0.0);
|
||||
p.AddP70vector("ScalingOffset", 0.0, 0.0, 0.0);
|
||||
p.AddP70vector("ScalingPivot", 0.0, 0.0, 0.0);
|
||||
p.AddP70bool("TranslationActive", 0);
|
||||
p.AddP70bool("TranslationActive", false);
|
||||
p.AddP70vector("TranslationMin", 0.0, 0.0, 0.0);
|
||||
p.AddP70vector("TranslationMax", 0.0, 0.0, 0.0);
|
||||
p.AddP70bool("TranslationMinX", 0);
|
||||
p.AddP70bool("TranslationMinY", 0);
|
||||
p.AddP70bool("TranslationMinZ", 0);
|
||||
p.AddP70bool("TranslationMaxX", 0);
|
||||
p.AddP70bool("TranslationMaxY", 0);
|
||||
p.AddP70bool("TranslationMaxZ", 0);
|
||||
p.AddP70bool("TranslationMinX", false);
|
||||
p.AddP70bool("TranslationMinY", false);
|
||||
p.AddP70bool("TranslationMinZ", false);
|
||||
p.AddP70bool("TranslationMaxX", false);
|
||||
p.AddP70bool("TranslationMaxY", false);
|
||||
p.AddP70bool("TranslationMaxZ", false);
|
||||
p.AddP70enum("RotationOrder", 0);
|
||||
p.AddP70bool("RotationSpaceForLimitOnly", 0);
|
||||
p.AddP70bool("RotationSpaceForLimitOnly", false);
|
||||
p.AddP70double("RotationStiffnessX", 0.0);
|
||||
p.AddP70double("RotationStiffnessY", 0.0);
|
||||
p.AddP70double("RotationStiffnessZ", 0.0);
|
||||
p.AddP70double("AxisLen", 10.0);
|
||||
p.AddP70vector("PreRotation", 0.0, 0.0, 0.0);
|
||||
p.AddP70vector("PostRotation", 0.0, 0.0, 0.0);
|
||||
p.AddP70bool("RotationActive", 0);
|
||||
p.AddP70bool("RotationActive", false);
|
||||
p.AddP70vector("RotationMin", 0.0, 0.0, 0.0);
|
||||
p.AddP70vector("RotationMax", 0.0, 0.0, 0.0);
|
||||
p.AddP70bool("RotationMinX", 0);
|
||||
p.AddP70bool("RotationMinY", 0);
|
||||
p.AddP70bool("RotationMinZ", 0);
|
||||
p.AddP70bool("RotationMaxX", 0);
|
||||
p.AddP70bool("RotationMaxY", 0);
|
||||
p.AddP70bool("RotationMaxZ", 0);
|
||||
p.AddP70bool("RotationMinX", false);
|
||||
p.AddP70bool("RotationMinY", false);
|
||||
p.AddP70bool("RotationMinZ", false);
|
||||
p.AddP70bool("RotationMaxX", false);
|
||||
p.AddP70bool("RotationMaxY", false);
|
||||
p.AddP70bool("RotationMaxZ", false);
|
||||
p.AddP70enum("InheritType", 0);
|
||||
p.AddP70bool("ScalingActive", 0);
|
||||
p.AddP70bool("ScalingActive", false);
|
||||
p.AddP70vector("ScalingMin", 0.0, 0.0, 0.0);
|
||||
p.AddP70vector("ScalingMax", 1.0, 1.0, 1.0);
|
||||
p.AddP70bool("ScalingMinX", 0);
|
||||
p.AddP70bool("ScalingMinY", 0);
|
||||
p.AddP70bool("ScalingMinZ", 0);
|
||||
p.AddP70bool("ScalingMaxX", 0);
|
||||
p.AddP70bool("ScalingMaxY", 0);
|
||||
p.AddP70bool("ScalingMaxZ", 0);
|
||||
p.AddP70bool("ScalingMinX", false);
|
||||
p.AddP70bool("ScalingMinY", false);
|
||||
p.AddP70bool("ScalingMinZ", false);
|
||||
p.AddP70bool("ScalingMaxX", false);
|
||||
p.AddP70bool("ScalingMaxY", false);
|
||||
p.AddP70bool("ScalingMaxZ", false);
|
||||
p.AddP70vector("GeometricTranslation", 0.0, 0.0, 0.0);
|
||||
p.AddP70vector("GeometricRotation", 0.0, 0.0, 0.0);
|
||||
p.AddP70vector("GeometricScaling", 1.0, 1.0, 1.0);
|
||||
|
|
@ -788,11 +788,11 @@ void FBXExporter::WriteDefinitions ()
|
|||
p.AddP70double("PreferedAngleZ", 0.0);
|
||||
p.AddP70("LookAtProperty", "object", "", "");
|
||||
p.AddP70("UpVectorProperty", "object", "", "");
|
||||
p.AddP70bool("Show", 1);
|
||||
p.AddP70bool("NegativePercentShapeSupport", 1);
|
||||
p.AddP70bool("Show", true);
|
||||
p.AddP70bool("NegativePercentShapeSupport", true);
|
||||
p.AddP70int("DefaultAttributeIndex", -1);
|
||||
p.AddP70bool("Freeze", 0);
|
||||
p.AddP70bool("LODBox", 0);
|
||||
p.AddP70bool("Freeze", false);
|
||||
p.AddP70bool("LODBox", false);
|
||||
p.AddP70(
|
||||
"Lcl Translation", "Lcl Translation", "", "A",
|
||||
double(0), double(0), double(0)
|
||||
|
|
@ -839,9 +839,9 @@ void FBXExporter::WriteDefinitions ()
|
|||
p.AddP70color("Color", 0, 0, 0);
|
||||
p.AddP70vector("BBoxMin", 0, 0, 0);
|
||||
p.AddP70vector("BBoxMax", 0, 0, 0);
|
||||
p.AddP70bool("Primary Visibility", 1);
|
||||
p.AddP70bool("Casts Shadows", 1);
|
||||
p.AddP70bool("Receive Shadows", 1);
|
||||
p.AddP70bool("Primary Visibility", true);
|
||||
p.AddP70bool("Casts Shadows", true);
|
||||
p.AddP70bool("Receive Shadows", true);
|
||||
pt.AddChild(p);
|
||||
n.AddChild(pt);
|
||||
object_nodes.push_back(n);
|
||||
|
|
@ -872,7 +872,7 @@ void FBXExporter::WriteDefinitions ()
|
|||
} else {
|
||||
p.AddP70string("ShadingModel", "Lambert");
|
||||
}
|
||||
p.AddP70bool("MultiLayer", 0);
|
||||
p.AddP70bool("MultiLayer", false);
|
||||
p.AddP70colorA("EmissiveColor", 0.0, 0.0, 0.0);
|
||||
p.AddP70numberA("EmissiveFactor", 1.0);
|
||||
p.AddP70colorA("AmbientColor", 0.2, 0.2, 0.2);
|
||||
|
|
@ -909,7 +909,7 @@ void FBXExporter::WriteDefinitions ()
|
|||
n.AddChild("Count", count);
|
||||
pt = FBX::Node("PropertyTemplate", "FbxVideo");
|
||||
p = FBX::Node("Properties70");
|
||||
p.AddP70bool("ImageSequence", 0);
|
||||
p.AddP70bool("ImageSequence", false);
|
||||
p.AddP70int("ImageSequenceOffset", 0);
|
||||
p.AddP70double("FrameRate", 0.0);
|
||||
p.AddP70int("LastFrame", 0);
|
||||
|
|
@ -921,8 +921,8 @@ void FBXExporter::WriteDefinitions ()
|
|||
p.AddP70double("PlaySpeed", 0.0);
|
||||
p.AddP70time("Offset", 0);
|
||||
p.AddP70enum("InterlaceMode", 0);
|
||||
p.AddP70bool("FreeRunning", 0);
|
||||
p.AddP70bool("Loop", 0);
|
||||
p.AddP70bool("FreeRunning", false);
|
||||
p.AddP70bool("Loop", false);
|
||||
p.AddP70enum("AccessMode", 0);
|
||||
pt.AddChild(p);
|
||||
n.AddChild(pt);
|
||||
|
|
@ -943,8 +943,8 @@ void FBXExporter::WriteDefinitions ()
|
|||
p.AddP70enum("CurrentMappingType", 0);
|
||||
p.AddP70enum("WrapModeU", 0);
|
||||
p.AddP70enum("WrapModeV", 0);
|
||||
p.AddP70bool("UVSwap", 0);
|
||||
p.AddP70bool("PremultiplyAlpha", 1);
|
||||
p.AddP70bool("UVSwap", false);
|
||||
p.AddP70bool("PremultiplyAlpha", true);
|
||||
p.AddP70vectorA("Translation", 0.0, 0.0, 0.0);
|
||||
p.AddP70vectorA("Rotation", 0.0, 0.0, 0.0);
|
||||
p.AddP70vectorA("Scaling", 1.0, 1.0, 1.0);
|
||||
|
|
@ -952,8 +952,8 @@ void FBXExporter::WriteDefinitions ()
|
|||
p.AddP70vector("TextureScalingPivot", 0.0, 0.0, 0.0);
|
||||
p.AddP70enum("CurrentTextureBlendMode", 1);
|
||||
p.AddP70string("UVSet", "default");
|
||||
p.AddP70bool("UseMaterial", 0);
|
||||
p.AddP70bool("UseMipMap", 0);
|
||||
p.AddP70bool("UseMaterial", false);
|
||||
p.AddP70bool("UseMipMap", false);
|
||||
pt.AddChild(p);
|
||||
n.AddChild(pt);
|
||||
object_nodes.push_back(n);
|
||||
|
|
@ -1051,7 +1051,7 @@ aiNode* get_node_for_mesh(unsigned int meshIndex, aiNode* node)
|
|||
aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene)
|
||||
{
|
||||
std::vector<const aiNode*> node_chain;
|
||||
while (node != scene->mRootNode) {
|
||||
while (node != scene->mRootNode && node != nullptr) {
|
||||
node_chain.push_back(node);
|
||||
node = node->mParent;
|
||||
}
|
||||
|
|
@ -1062,14 +1062,14 @@ aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene)
|
|||
return transform;
|
||||
}
|
||||
|
||||
int64_t to_ktime(double ticks, const aiAnimation* anim) {
|
||||
if (anim->mTicksPerSecond <= 0) {
|
||||
inline int64_t to_ktime(double ticks, const aiAnimation* anim) {
|
||||
if (FP_ZERO == std::fpclassify(anim->mTicksPerSecond)) {
|
||||
return static_cast<int64_t>(ticks) * FBX::SECOND;
|
||||
}
|
||||
return (static_cast<int64_t>(ticks) / static_cast<int64_t>(anim->mTicksPerSecond)) * FBX::SECOND;
|
||||
return (static_cast<int64_t>(ticks / anim->mTicksPerSecond)) * FBX::SECOND;
|
||||
}
|
||||
|
||||
int64_t to_ktime(double time) {
|
||||
inline int64_t to_ktime(double time) {
|
||||
return (static_cast<int64_t>(time * FBX::SECOND));
|
||||
}
|
||||
|
||||
|
|
@ -1089,6 +1089,8 @@ void FBXExporter::WriteObjects ()
|
|||
bool bJoinIdenticalVertices = mProperties->GetPropertyBool("bJoinIdenticalVertices", true);
|
||||
std::vector<std::vector<int32_t>> vVertexIndice;//save vertex_indices as it is needed later
|
||||
|
||||
const auto bTransparencyFactorReferencedToOpacity = mProperties->GetPropertyBool(AI_CONFIG_EXPORT_FBX_TRANSPARENCY_FACTOR_REFER_TO_OPACITY, false);
|
||||
|
||||
// geometry (aiMesh)
|
||||
mesh_uids.clear();
|
||||
indent = 1;
|
||||
|
|
@ -1215,10 +1217,8 @@ void FBXExporter::WriteObjects ()
|
|||
}
|
||||
|
||||
// colors, if any
|
||||
// TODO only one color channel currently
|
||||
const int32_t colorChannelIndex = 0;
|
||||
if (m->HasVertexColors(colorChannelIndex)) {
|
||||
FBX::Node vertexcolors("LayerElementColor", int32_t(colorChannelIndex));
|
||||
for (size_t ci = 0; ci < m->GetNumColorChannels(); ++ci) {
|
||||
FBX::Node vertexcolors("LayerElementColor", int32_t(ci));
|
||||
vertexcolors.Begin(outstream, binary, indent);
|
||||
vertexcolors.DumpProperties(outstream, binary, indent);
|
||||
vertexcolors.EndProperties(outstream, binary, indent);
|
||||
|
|
@ -1228,7 +1228,7 @@ void FBXExporter::WriteObjects ()
|
|||
"Version", int32_t(101), outstream, binary, indent
|
||||
);
|
||||
char layerName[8];
|
||||
sprintf(layerName, "COLOR_%d", colorChannelIndex);
|
||||
snprintf(layerName, sizeof(layerName), "COLOR_%d", int32_t(ci));
|
||||
FBX::Node::WritePropertyNode(
|
||||
"Name", (const char*)layerName, outstream, binary, indent
|
||||
);
|
||||
|
|
@ -1245,7 +1245,7 @@ void FBXExporter::WriteObjects ()
|
|||
for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
|
||||
const aiFace &f = m->mFaces[fi];
|
||||
for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
|
||||
const aiColor4D &c = m->mColors[colorChannelIndex][f.mIndices[pvi]];
|
||||
const aiColor4D &c = m->mColors[ci][f.mIndices[pvi]];
|
||||
color_data.push_back(c.r);
|
||||
color_data.push_back(c.g);
|
||||
color_data.push_back(c.b);
|
||||
|
|
@ -1352,11 +1352,14 @@ void FBXExporter::WriteObjects ()
|
|||
le.AddChild("Type", "LayerElementNormal");
|
||||
le.AddChild("TypedIndex", int32_t(0));
|
||||
layer.AddChild(le);
|
||||
// TODO only 1 color channel currently
|
||||
le = FBX::Node("LayerElement");
|
||||
le.AddChild("Type", "LayerElementColor");
|
||||
le.AddChild("TypedIndex", int32_t(0));
|
||||
layer.AddChild(le);
|
||||
|
||||
for (size_t ci = 0; ci < m->GetNumColorChannels(); ++ci) {
|
||||
le = FBX::Node("LayerElement");
|
||||
le.AddChild("Type", "LayerElementColor");
|
||||
le.AddChild("TypedIndex", int32_t(ci));
|
||||
layer.AddChild(le);
|
||||
}
|
||||
|
||||
le = FBX::Node("LayerElement");
|
||||
le.AddChild("Type", "LayerElementMaterial");
|
||||
le.AddChild("TypedIndex", int32_t(0));
|
||||
|
|
@ -1390,7 +1393,7 @@ void FBXExporter::WriteObjects ()
|
|||
aiMaterial* m = mScene->mMaterials[i];
|
||||
|
||||
// these are used to receive material data
|
||||
float f; aiColor3D c;
|
||||
ai_real f; aiColor3D c;
|
||||
|
||||
// start the node record
|
||||
FBX::Node n("Material");
|
||||
|
|
@ -1445,13 +1448,21 @@ void FBXExporter::WriteObjects ()
|
|||
// "TransparentColor" / "TransparencyFactor"...
|
||||
// thanks FBX, for your insightful interpretation of consistency
|
||||
p.AddP70colorA("TransparentColor", c.r, c.g, c.b);
|
||||
// TransparencyFactor defaults to 0.0, so set it to 1.0.
|
||||
// note: Maya always sets this to 1.0,
|
||||
// so we can't use it sensibly as "Opacity".
|
||||
// In stead we rely on the legacy "Opacity" value, below.
|
||||
// Blender also relies on "Opacity" not "TransparencyFactor",
|
||||
// probably for a similar reason.
|
||||
p.AddP70numberA("TransparencyFactor", 1.0);
|
||||
|
||||
if (!bTransparencyFactorReferencedToOpacity) {
|
||||
// TransparencyFactor defaults to 0.0, so set it to 1.0.
|
||||
// note: Maya always sets this to 1.0,
|
||||
// so we can't use it sensibly as "Opacity".
|
||||
// In stead we rely on the legacy "Opacity" value, below.
|
||||
// Blender also relies on "Opacity" not "TransparencyFactor",
|
||||
// probably for a similar reason.
|
||||
p.AddP70numberA("TransparencyFactor", 1.0);
|
||||
}
|
||||
}
|
||||
if (bTransparencyFactorReferencedToOpacity) {
|
||||
if (m->Get(AI_MATKEY_OPACITY, f) == aiReturn_SUCCESS) {
|
||||
p.AddP70numberA("TransparencyFactor", 1.0 - f);
|
||||
}
|
||||
}
|
||||
if (m->Get(AI_MATKEY_COLOR_REFLECTIVE, c) == aiReturn_SUCCESS) {
|
||||
p.AddP70colorA("ReflectionColor", c.r, c.g, c.b);
|
||||
|
|
@ -1707,7 +1718,7 @@ void FBXExporter::WriteObjects ()
|
|||
p.AddP70vectorA("Scaling", trafo.mScaling[0], trafo.mScaling[1], 0.0);
|
||||
p.AddP70enum("CurrentTextureBlendMode", 0); // TODO: verify
|
||||
//p.AddP70string("UVSet", ""); // TODO: how should this work?
|
||||
p.AddP70bool("UseMaterial", 1);
|
||||
p.AddP70bool("UseMaterial", true);
|
||||
tnode.AddChild(p);
|
||||
// can't easily determine which texture path will be correct,
|
||||
// so just store what we have in every field.
|
||||
|
|
@ -1749,7 +1760,7 @@ void FBXExporter::WriteObjects ()
|
|||
int64_t blendshape_uid = generate_uid();
|
||||
mesh_uids.push_back(blendshape_uid);
|
||||
bsnode.AddProperty(blendshape_uid);
|
||||
bsnode.AddProperty(blendshape_name + FBX::SEPARATOR + "Blendshape");
|
||||
bsnode.AddProperty(blendshape_name + FBX::SEPARATOR + "Geometry");
|
||||
bsnode.AddProperty("Shape");
|
||||
bsnode.AddChild("Version", int32_t(100));
|
||||
bsnode.Begin(outstream, binary, indent);
|
||||
|
|
@ -1759,23 +1770,25 @@ void FBXExporter::WriteObjects ()
|
|||
indent++;
|
||||
if (pAnimMesh->HasPositions()) {
|
||||
std::vector<int32_t>shape_indices;
|
||||
std::vector<double>pPositionDiff;
|
||||
std::vector<double>pNormalDiff;
|
||||
std::vector<float>pPositionDiff;
|
||||
std::vector<float>pNormalDiff;
|
||||
|
||||
for (unsigned int vt = 0; vt < vertex_indices.size(); ++vt) {
|
||||
aiVector3D pDiff = (pAnimMesh->mVertices[vertex_indices[vt]] - m->mVertices[vertex_indices[vt]]);
|
||||
if(pDiff.Length()>1e-8){
|
||||
shape_indices.push_back(vertex_indices[vt]);
|
||||
pPositionDiff.push_back(pDiff[0]);
|
||||
pPositionDiff.push_back(pDiff[1]);
|
||||
pPositionDiff.push_back(pDiff[2]);
|
||||
shape_indices.push_back(vertex_indices[vt]);
|
||||
pPositionDiff.push_back(pDiff[0]);
|
||||
pPositionDiff.push_back(pDiff[1]);
|
||||
pPositionDiff.push_back(pDiff[2]);
|
||||
|
||||
if (pAnimMesh->HasNormals()) {
|
||||
aiVector3D nDiff = (pAnimMesh->mNormals[vertex_indices[vt]] - m->mNormals[vertex_indices[vt]]);
|
||||
pNormalDiff.push_back(nDiff[0]);
|
||||
pNormalDiff.push_back(nDiff[1]);
|
||||
pNormalDiff.push_back(nDiff[2]);
|
||||
}
|
||||
if (pAnimMesh->HasNormals()) {
|
||||
aiVector3D nDiff = (pAnimMesh->mNormals[vertex_indices[vt]] - m->mNormals[vertex_indices[vt]]);
|
||||
pNormalDiff.push_back(nDiff[0]);
|
||||
pNormalDiff.push_back(nDiff[1]);
|
||||
pNormalDiff.push_back(nDiff[2]);
|
||||
} else {
|
||||
pNormalDiff.push_back(0.0);
|
||||
pNormalDiff.push_back(0.0);
|
||||
pNormalDiff.push_back(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1808,7 +1821,7 @@ void FBXExporter::WriteObjects ()
|
|||
p.AddP70numberA("DeformPercent", 0.0);
|
||||
sdnode.AddChild(p);
|
||||
// TODO: Normally just one weight per channel, adding stub for later development
|
||||
std::vector<float>fFullWeights;
|
||||
std::vector<double>fFullWeights;
|
||||
fFullWeights.push_back(100.);
|
||||
sdnode.AddChild("FullWeights", fFullWeights);
|
||||
sdnode.Dump(outstream, binary, indent);
|
||||
|
|
@ -1858,33 +1871,26 @@ void FBXExporter::WriteObjects ()
|
|||
// one sticky point is that the number of vertices may not match,
|
||||
// because assimp splits vertices by normal, uv, etc.
|
||||
|
||||
// functor for aiNode sorting
|
||||
struct SortNodeByName
|
||||
{
|
||||
bool operator()(const aiNode *lhs, const aiNode *rhs) const
|
||||
{
|
||||
return strcmp(lhs->mName.C_Str(), rhs->mName.C_Str()) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
// first we should mark the skeleton for each mesh.
|
||||
// the skeleton must include not only the aiBones,
|
||||
// but also all their parent nodes.
|
||||
// anything that affects the position of any bone node must be included.
|
||||
// Use SorNodeByName to make sure the exported result will be the same across all systems
|
||||
// Otherwise the aiNodes of the skeleton would be sorted based on the pointer address, which isn't consistent
|
||||
std::vector<std::set<const aiNode*, SortNodeByName>> skeleton_by_mesh(mScene->mNumMeshes);
|
||||
|
||||
// note that we want to preserve input order as much as possible here.
|
||||
// previously, sorting by name lead to consistent output across systems, but was not
|
||||
// suitable for downstream consumption by some applications.
|
||||
std::vector<std::vector<const aiNode*>> skeleton_by_mesh(mScene->mNumMeshes);
|
||||
// at the same time we can build a list of all the skeleton nodes,
|
||||
// which will be used later to mark them as type "limbNode".
|
||||
std::unordered_set<const aiNode*> limbnodes;
|
||||
|
||||
//actual bone nodes in fbx, without parenting-up
|
||||
std::unordered_set<std::string> setAllBoneNamesInScene;
|
||||
for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m)
|
||||
{
|
||||
std::vector<std::string> allBoneNames;
|
||||
for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m) {
|
||||
aiMesh* pMesh = mScene->mMeshes[m];
|
||||
for(unsigned int b = 0; b < pMesh->mNumBones; ++ b)
|
||||
setAllBoneNamesInScene.insert(pMesh->mBones[b]->mName.data);
|
||||
allBoneNames.push_back(pMesh->mBones[b]->mName.data);
|
||||
}
|
||||
aiMatrix4x4 mxTransIdentity;
|
||||
|
||||
|
|
@ -1892,7 +1898,7 @@ void FBXExporter::WriteObjects ()
|
|||
std::map<std::string,aiNode*> node_by_bone;
|
||||
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
|
||||
const aiMesh* m = mScene->mMeshes[mi];
|
||||
std::set<const aiNode*, SortNodeByName> skeleton;
|
||||
std::vector<const aiNode*> skeleton;
|
||||
for (size_t bi =0; bi < m->mNumBones; ++bi) {
|
||||
const aiBone* b = m->mBones[bi];
|
||||
const std::string name(b->mName.C_Str());
|
||||
|
|
@ -1911,7 +1917,7 @@ void FBXExporter::WriteObjects ()
|
|||
node_by_bone[name] = n;
|
||||
limbnodes.insert(n);
|
||||
}
|
||||
skeleton.insert(n);
|
||||
skeleton.push_back(n);
|
||||
// mark all parent nodes as skeleton as well,
|
||||
// up until we find the root node,
|
||||
// or else the node containing the mesh,
|
||||
|
|
@ -1922,7 +1928,7 @@ void FBXExporter::WriteObjects ()
|
|||
parent = parent->mParent
|
||||
) {
|
||||
// if we've already done this node we can skip it all
|
||||
if (skeleton.count(parent)) {
|
||||
if (std::find(skeleton.begin(), skeleton.end(), parent) != skeleton.end()) {
|
||||
break;
|
||||
}
|
||||
// ignore fbx transform nodes as these will be collapsed later
|
||||
|
|
@ -1932,7 +1938,7 @@ void FBXExporter::WriteObjects ()
|
|||
continue;
|
||||
}
|
||||
//not a bone in scene && no effect in transform
|
||||
if(setAllBoneNamesInScene.find(node_name)==setAllBoneNamesInScene.end()
|
||||
if (std::find(allBoneNames.begin(), allBoneNames.end(), node_name) == allBoneNames.end()
|
||||
&& parent->mTransformation == mxTransIdentity) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -2017,7 +2023,7 @@ void FBXExporter::WriteObjects ()
|
|||
aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene);
|
||||
|
||||
// now make a subdeformer for each bone in the skeleton
|
||||
const std::set<const aiNode*, SortNodeByName> skeleton= skeleton_by_mesh[mi];
|
||||
const auto & skeleton= skeleton_by_mesh[mi];
|
||||
for (const aiNode* bone_node : skeleton) {
|
||||
// if there's a bone for this node, find it
|
||||
const aiBone* b = nullptr;
|
||||
|
|
@ -2414,7 +2420,7 @@ void FBXExporter::WriteObjects ()
|
|||
// position/translation
|
||||
for (size_t ki = 0; ki < na->mNumPositionKeys; ++ki) {
|
||||
const aiVectorKey& k = na->mPositionKeys[ki];
|
||||
times.push_back(to_ktime(k.mTime));
|
||||
times.push_back(to_ktime(k.mTime, anim));
|
||||
xval.push_back(k.mValue.x);
|
||||
yval.push_back(k.mValue.y);
|
||||
zval.push_back(k.mValue.z);
|
||||
|
|
@ -2428,12 +2434,12 @@ void FBXExporter::WriteObjects ()
|
|||
times.clear(); xval.clear(); yval.clear(); zval.clear();
|
||||
for (size_t ki = 0; ki < na->mNumRotationKeys; ++ki) {
|
||||
const aiQuatKey& k = na->mRotationKeys[ki];
|
||||
times.push_back(to_ktime(k.mTime));
|
||||
times.push_back(to_ktime(k.mTime, anim));
|
||||
// TODO: aiQuaternion method to convert to Euler...
|
||||
aiMatrix4x4 m(k.mValue.GetMatrix());
|
||||
aiVector3D qs, qr, qt;
|
||||
m.Decompose(qs, qr, qt);
|
||||
qr *= DEG;
|
||||
qr = AI_RAD_TO_DEG(qr);
|
||||
xval.push_back(qr.x);
|
||||
yval.push_back(qr.y);
|
||||
zval.push_back(qr.z);
|
||||
|
|
@ -2446,7 +2452,7 @@ void FBXExporter::WriteObjects ()
|
|||
times.clear(); xval.clear(); yval.clear(); zval.clear();
|
||||
for (size_t ki = 0; ki < na->mNumScalingKeys; ++ki) {
|
||||
const aiVectorKey& k = na->mScalingKeys[ki];
|
||||
times.push_back(to_ktime(k.mTime));
|
||||
times.push_back(to_ktime(k.mTime, anim));
|
||||
xval.push_back(k.mValue.x);
|
||||
yval.push_back(k.mValue.y);
|
||||
zval.push_back(k.mValue.z);
|
||||
|
|
@ -2483,6 +2489,57 @@ const std::map<std::string,std::pair<std::string,char>> transform_types = {
|
|||
{"GeometricScalingInverse", {"GeometricScalingInverse", 'i'}}
|
||||
};
|
||||
|
||||
//add metadata to fbx property
|
||||
void add_meta(FBX::Node& fbx_node, const aiNode* node){
|
||||
if(node->mMetaData == nullptr) return;
|
||||
aiMetadata* meta = node->mMetaData;
|
||||
for (unsigned int i = 0; i < meta->mNumProperties; ++i) {
|
||||
aiString key = meta->mKeys[i];
|
||||
aiMetadataEntry* entry = &meta->mValues[i];
|
||||
switch (entry->mType) {
|
||||
case AI_BOOL:{
|
||||
bool val = *static_cast<bool *>(entry->mData);
|
||||
fbx_node.AddP70bool(key.C_Str(), val);
|
||||
break;
|
||||
}
|
||||
case AI_INT32:{
|
||||
int32_t val = *static_cast<int32_t *>(entry->mData);
|
||||
fbx_node.AddP70int(key.C_Str(), val);
|
||||
break;
|
||||
}
|
||||
case AI_UINT64:{
|
||||
//use string to add uint64
|
||||
uint64_t val = *static_cast<uint64_t *>(entry->mData);
|
||||
fbx_node.AddP70string(key.C_Str(), std::to_string(val).c_str());
|
||||
break;
|
||||
}
|
||||
case AI_FLOAT:{
|
||||
float val = *static_cast<float *>(entry->mData);
|
||||
fbx_node.AddP70double(key.C_Str(), val);
|
||||
break;
|
||||
}
|
||||
case AI_DOUBLE:{
|
||||
double val = *static_cast<double *>(entry->mData);
|
||||
fbx_node.AddP70double(key.C_Str(), val);
|
||||
break;
|
||||
}
|
||||
case AI_AISTRING:{
|
||||
aiString val = *static_cast<aiString *>(entry->mData);
|
||||
fbx_node.AddP70string(key.C_Str(), val.C_Str());
|
||||
break;
|
||||
}
|
||||
case AI_AIMETADATA: {
|
||||
//ignore
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// write a single model node to the stream
|
||||
void FBXExporter::WriteModelNode(
|
||||
StreamWriterLE& outstream,
|
||||
|
|
@ -2497,10 +2554,10 @@ void FBXExporter::WriteModelNode(
|
|||
const aiVector3D one = {1, 1, 1};
|
||||
FBX::Node m("Model");
|
||||
std::string name = node->mName.C_Str() + FBX::SEPARATOR + "Model";
|
||||
m.AddProperties(node_uid, name, type);
|
||||
m.AddProperties(node_uid, std::move(name), type);
|
||||
m.AddChild("Version", int32_t(232));
|
||||
FBX::Node p("Properties70");
|
||||
p.AddP70bool("RotationActive", 1);
|
||||
p.AddP70bool("RotationActive", true);
|
||||
p.AddP70int("DefaultAttributeIndex", 0);
|
||||
p.AddP70enum("InheritType", inherit_type);
|
||||
if (transform_chain.empty()) {
|
||||
|
|
@ -2514,9 +2571,10 @@ void FBXExporter::WriteModelNode(
|
|||
);
|
||||
}
|
||||
if (r != zero) {
|
||||
r = AI_RAD_TO_DEG(r);
|
||||
p.AddP70(
|
||||
"Lcl Rotation", "Lcl Rotation", "", "A",
|
||||
double(DEG*r.x), double(DEG*r.y), double(DEG*r.z)
|
||||
double(r.x), double(r.y), double(r.z)
|
||||
);
|
||||
}
|
||||
if (s != one) {
|
||||
|
|
@ -2549,6 +2607,7 @@ void FBXExporter::WriteModelNode(
|
|||
}
|
||||
}
|
||||
}
|
||||
add_meta(p, node);
|
||||
m.AddChild(p);
|
||||
|
||||
// not sure what these are for,
|
||||
|
|
@ -2600,8 +2659,7 @@ void FBXExporter::WriteModelNodes(
|
|||
transform_chain.emplace_back(elem->first, t);
|
||||
break;
|
||||
case 'r': // rotation
|
||||
r *= float(DEG);
|
||||
transform_chain.emplace_back(elem->first, r);
|
||||
transform_chain.emplace_back(elem->first, AI_RAD_TO_DEG(r));
|
||||
break;
|
||||
case 's': // scale
|
||||
transform_chain.emplace_back(elem->first, s);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -156,6 +156,9 @@ struct ImportSettings {
|
|||
/** Set to true to perform a conversion from cm to meter after the import
|
||||
*/
|
||||
bool convertToMeters;
|
||||
|
||||
// Set to true to ignore the axis configuration in the file
|
||||
bool ignoreUpDirection = false;
|
||||
};
|
||||
|
||||
} // namespace FBX
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -62,8 +62,7 @@ namespace Assimp {
|
|||
|
||||
template <>
|
||||
const char *LogFunctions<FBXImporter>::Prefix() {
|
||||
static auto prefix = "FBX: ";
|
||||
return prefix;
|
||||
return "FBX: ";
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
|
@ -73,33 +72,25 @@ using namespace Assimp::Formatter;
|
|||
using namespace Assimp::FBX;
|
||||
|
||||
namespace {
|
||||
|
||||
static const aiImporterDesc desc = {
|
||||
"Autodesk FBX Importer",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
aiImporterFlags_SupportTextFlavour,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"fbx"
|
||||
};
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by #Importer
|
||||
FBXImporter::FBXImporter() :
|
||||
mSettings() {
|
||||
// empty
|
||||
static constexpr aiImporterDesc desc = {
|
||||
"Autodesk FBX Importer",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
aiImporterFlags_SupportTextFlavour,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"fbx"
|
||||
};
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the class can handle the format of the given file.
|
||||
bool FBXImporter::CanRead(const std::string & pFile, IOSystem * pIOHandler, bool /*checkSig*/) const {
|
||||
// at least ASCII-FBX files usually have a 'FBX' somewhere in their head
|
||||
static const char *tokens[] = { "fbx" };
|
||||
static const char *tokens[] = { " \n\r\n " };
|
||||
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
|
||||
}
|
||||
|
||||
|
|
@ -126,6 +117,7 @@ void FBXImporter::SetupProperties(const Importer *pImp) {
|
|||
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.ignoreUpDirection = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_IGNORE_UP_DIRECTION, false);
|
||||
mSettings.useSkeleton = pImp->GetPropertyBool(AI_CONFIG_FBX_USE_SKELETON_BONE_CONTAINER, false);
|
||||
}
|
||||
|
||||
|
|
@ -156,19 +148,19 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
|||
// broad-phase tokenized pass in which we identify the core
|
||||
// syntax elements of FBX (brackets, commas, key:value mappings)
|
||||
TokenList tokens;
|
||||
try {
|
||||
|
||||
Assimp::StackAllocator tempAllocator;
|
||||
try {
|
||||
bool is_binary = false;
|
||||
if (!strncmp(begin, "Kaydara FBX Binary", 18)) {
|
||||
is_binary = true;
|
||||
TokenizeBinary(tokens, begin, contents.size());
|
||||
TokenizeBinary(tokens, begin, contents.size(), tempAllocator);
|
||||
} else {
|
||||
Tokenize(tokens, begin);
|
||||
Tokenize(tokens, begin, tempAllocator);
|
||||
}
|
||||
|
||||
// use this information to construct a very rudimentary
|
||||
// parse-tree representing the FBX scope structure
|
||||
Parser parser(tokens, is_binary);
|
||||
Parser parser(tokens, tempAllocator, is_binary);
|
||||
|
||||
// take the raw parse-tree and convert it to a FBX DOM
|
||||
Document doc(parser, mSettings);
|
||||
|
|
@ -187,10 +179,12 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
|||
// assimp universal format (M)
|
||||
SetFileScale(size_relative_to_cm * 0.01f);
|
||||
|
||||
std::for_each(tokens.begin(), tokens.end(), Util::delete_fun<Token>());
|
||||
} catch (std::exception &) {
|
||||
std::for_each(tokens.begin(), tokens.end(), Util::delete_fun<Token>());
|
||||
throw;
|
||||
// This collection does not own the memory for the tokens, but we need to call their d'tor
|
||||
std::for_each(tokens.begin(), tokens.end(), Util::destructor_fun<Token>());
|
||||
|
||||
} catch (std::exception &) {
|
||||
std::for_each(tokens.begin(), tokens.end(), Util::destructor_fun<Token>());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ 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() = default;
|
||||
|
||||
/// @brief The class destructor, default implementation.
|
||||
~FBXImporter() override = default;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -138,20 +138,6 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
Material::~Material() = default;
|
||||
|
||||
aiVector2D uvTrans;
|
||||
aiVector2D uvScaling;
|
||||
ai_real uvRotation;
|
||||
|
||||
std::string type;
|
||||
std::string relativeFileName;
|
||||
std::string fileName;
|
||||
std::string alphaSource;
|
||||
std::shared_ptr<const PropertyTable> props;
|
||||
|
||||
unsigned int crop[4]{};
|
||||
|
||||
const Video* media;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
|
||||
Object(id,element,name),
|
||||
|
|
@ -292,10 +278,10 @@ void LayeredTexture::fillTexture(const Document& doc) {
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Video::Video(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
|
||||
Object(id,element,name),
|
||||
Video::Video(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
|
||||
Object(id, element, name),
|
||||
contentLength(0),
|
||||
content(0) {
|
||||
content(nullptr) {
|
||||
const Scope& sc = GetRequiredScope(element);
|
||||
|
||||
const Element* const Type = sc["Type"];
|
||||
|
|
@ -380,9 +366,10 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
|
|||
props = GetPropertyTable(doc,"Video.FbxVideo",element,sc);
|
||||
}
|
||||
|
||||
|
||||
Video::~Video() {
|
||||
delete[] content;
|
||||
if (contentLength > 0) {
|
||||
delete[] content;
|
||||
}
|
||||
}
|
||||
|
||||
} //!FBX
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -69,13 +69,16 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name,
|
|||
}
|
||||
const BlendShape* const bsp = ProcessSimpleConnection<BlendShape>(*con, false, "BlendShape -> Geometry", element);
|
||||
if (bsp) {
|
||||
blendShapes.push_back(bsp);
|
||||
auto pr = blendShapes.insert(bsp);
|
||||
if (!pr.second) {
|
||||
FBXImporter::LogWarn("there is the same blendShape id ", bsp->ID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const std::vector<const BlendShape*>& Geometry::GetBlendShapes() const {
|
||||
const std::unordered_set<const BlendShape*>& Geometry::GetBlendShapes() const {
|
||||
return blendShapes;
|
||||
}
|
||||
|
||||
|
|
@ -415,9 +418,11 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
|||
{
|
||||
bool isDirect = ReferenceInformationType == "Direct";
|
||||
bool isIndexToDirect = ReferenceInformationType == "IndexToDirect";
|
||||
const bool hasDataElement = HasElement(source, dataElementName);
|
||||
const bool hasIndexDataElement = HasElement(source, indexDataElementName);
|
||||
|
||||
// fall-back to direct data if there is no index data element
|
||||
if ( isIndexToDirect && !HasElement( source, indexDataElementName ) ) {
|
||||
if (isIndexToDirect && !hasIndexDataElement) {
|
||||
isDirect = true;
|
||||
isIndexToDirect = false;
|
||||
}
|
||||
|
|
@ -426,7 +431,8 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
|||
// deal with this more elegantly and with less redundancy, but right
|
||||
// now it seems unavoidable.
|
||||
if (MappingInformationType == "ByVertice" && isDirect) {
|
||||
if (!HasElement(source, dataElementName)) {
|
||||
if (!hasDataElement) {
|
||||
FBXImporter::LogWarn("missing data element: ", dataElementName);
|
||||
return;
|
||||
}
|
||||
std::vector<T> tempData;
|
||||
|
|
@ -448,14 +454,22 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
|||
}
|
||||
else if (MappingInformationType == "ByVertice" && isIndexToDirect) {
|
||||
std::vector<T> tempData;
|
||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||
if (!hasDataElement || !hasIndexDataElement) {
|
||||
if (!hasDataElement)
|
||||
FBXImporter::LogWarn("missing data element: ", dataElementName);
|
||||
if (!hasIndexDataElement)
|
||||
FBXImporter::LogWarn("missing index data element: ", indexDataElementName);
|
||||
return;
|
||||
}
|
||||
|
||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||
|
||||
std::vector<int> uvIndices;
|
||||
ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
|
||||
|
||||
if (uvIndices.size() != vertex_count) {
|
||||
if (uvIndices.size() != mapping_offsets.size()) {
|
||||
FBXImporter::LogError("length of input data unexpected for ByVertice mapping: ",
|
||||
uvIndices.size(), ", expected ", vertex_count);
|
||||
uvIndices.size(), ", expected ", mapping_offsets.size());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -473,6 +487,11 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
|||
}
|
||||
}
|
||||
else if (MappingInformationType == "ByPolygonVertex" && isDirect) {
|
||||
if (!hasDataElement) {
|
||||
FBXImporter::LogWarn("missing data element: ", dataElementName);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<T> tempData;
|
||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||
|
||||
|
|
@ -487,7 +506,14 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
|||
}
|
||||
else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) {
|
||||
std::vector<T> tempData;
|
||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||
if (!hasDataElement || !hasIndexDataElement) {
|
||||
if (!hasDataElement)
|
||||
FBXImporter::LogWarn("missing data element: ", dataElementName);
|
||||
if (!hasIndexDataElement)
|
||||
FBXImporter::LogWarn("missing index data element: ", indexDataElementName);
|
||||
return;
|
||||
}
|
||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||
|
||||
std::vector<int> uvIndices;
|
||||
ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
|
||||
|
|
@ -618,10 +644,12 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
|
|||
return;
|
||||
}
|
||||
|
||||
// materials are handled separately. First of all, they are assigned per-face
|
||||
// and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect
|
||||
// has a slightly different meaning for materials.
|
||||
ParseVectorDataArray(materials_out,GetRequiredElement(source,"Materials"));
|
||||
if (source["Materials"]) {
|
||||
// materials are handled separately. First of all, they are assigned per-face
|
||||
// and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect
|
||||
// has a slightly different meaning for materials.
|
||||
ParseVectorDataArray(materials_out, GetRequiredElement(source, "Materials"));
|
||||
}
|
||||
|
||||
if (MappingInformationType == "AllSame") {
|
||||
// easy - same material for all faces
|
||||
|
|
@ -657,11 +685,14 @@ ShapeGeometry::ShapeGeometry(uint64_t id, const Element& element, const std::str
|
|||
DOMError("failed to read Geometry object (class: Shape), no data scope found");
|
||||
}
|
||||
const Element& Indexes = GetRequiredElement(*sc, "Indexes", &element);
|
||||
const Element& Normals = GetRequiredElement(*sc, "Normals", &element);
|
||||
const Element& Vertices = GetRequiredElement(*sc, "Vertices", &element);
|
||||
ParseVectorDataArray(m_indices, Indexes);
|
||||
ParseVectorDataArray(m_vertices, Vertices);
|
||||
ParseVectorDataArray(m_normals, Normals);
|
||||
|
||||
if ((*sc)["Normals"]) {
|
||||
const Element& Normals = GetRequiredElement(*sc, "Normals", &element);
|
||||
ParseVectorDataArray(m_normals, Normals);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -53,84 +52,101 @@ namespace Assimp {
|
|||
namespace FBX {
|
||||
|
||||
/**
|
||||
* DOM base class for all kinds of FBX geometry
|
||||
* @brief DOM base class for all kinds of FBX geometry
|
||||
*/
|
||||
class Geometry : public Object {
|
||||
public:
|
||||
/// @brief The class constructor with all parameters.
|
||||
/// @param id The id.
|
||||
/// @param element
|
||||
/// @param name
|
||||
/// @param doc
|
||||
/// @param element The element instance
|
||||
/// @param name The name instance
|
||||
/// @param doc The document instance
|
||||
Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
|
||||
|
||||
/// @brief The class destructor, default.
|
||||
virtual ~Geometry() = default;
|
||||
|
||||
/// Get the Skin attached to this geometry or nullptr
|
||||
/// @brief Get the Skin attached to this geometry or nullptr.
|
||||
/// @return The deformer skip instance as a pointer, nullptr if none.
|
||||
const Skin* DeformerSkin() const;
|
||||
|
||||
/// Get the BlendShape attached to this geometry or nullptr
|
||||
const std::vector<const BlendShape*>& GetBlendShapes() const;
|
||||
/// @brief Get the BlendShape attached to this geometry or nullptr
|
||||
/// @return The blendshape arrays.
|
||||
const std::unordered_set<const BlendShape*>& GetBlendShapes() const;
|
||||
|
||||
private:
|
||||
const Skin* skin;
|
||||
std::vector<const BlendShape*> blendShapes;
|
||||
std::unordered_set<const BlendShape*> blendShapes;
|
||||
|
||||
};
|
||||
|
||||
typedef std::vector<int> MatIndexArray;
|
||||
|
||||
|
||||
/**
|
||||
* DOM class for FBX geometry of type "Mesh"
|
||||
* @brief DOM class for FBX geometry of type "Mesh"
|
||||
*/
|
||||
class MeshGeometry : public Geometry {
|
||||
public:
|
||||
/** The class constructor */
|
||||
/// @brief The class constructor
|
||||
/// @param id The id.
|
||||
/// @param element The element instance
|
||||
/// @param name The name instance
|
||||
/// @param doc The document instance
|
||||
MeshGeometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
|
||||
|
||||
/** The class destructor */
|
||||
/// @brief The class destructor, default.
|
||||
virtual ~MeshGeometry() = default;
|
||||
|
||||
/** Get a list of all vertex points, non-unique*/
|
||||
/// brief Get a vector of all vertex points, non-unique.
|
||||
/// @return The vertices vector.
|
||||
const std::vector<aiVector3D>& GetVertices() const;
|
||||
|
||||
/** Get a list of all vertex normals or an empty array if
|
||||
* no normals are specified. */
|
||||
/// @brief Get a vector of all vertex normals or an empty array if no normals are specified.
|
||||
/// @return The normal vector.
|
||||
const std::vector<aiVector3D>& GetNormals() const;
|
||||
|
||||
/** Get a list of all vertex tangents or an empty array
|
||||
* if no tangents are specified */
|
||||
/// @brief Get a vector of all vertex tangents or an empty array if no tangents are specified.
|
||||
/// @return The vertex tangents vector.
|
||||
const std::vector<aiVector3D>& GetTangents() const;
|
||||
|
||||
/** Get a list of all vertex bi-normals or an empty array
|
||||
* if no bi-normals are specified */
|
||||
/// @brief Get a vector of all vertex bi-normals or an empty array if no bi-normals are specified.
|
||||
/// @return The binomal vector.
|
||||
const std::vector<aiVector3D>& GetBinormals() const;
|
||||
|
||||
/** Return list of faces - each entry denotes a face and specifies
|
||||
* how many vertices it has. Vertices are taken from the
|
||||
* vertex data arrays in sequential order. */
|
||||
/// @brief Return list of faces - each entry denotes a face and specifies how many vertices it has.
|
||||
/// Vertices are taken from the vertex data arrays in sequential order.
|
||||
/// @return The face indices vector.
|
||||
const std::vector<unsigned int>& GetFaceIndexCounts() const;
|
||||
|
||||
/** Get a UV coordinate slot, returns an empty array if
|
||||
* the requested slot does not exist. */
|
||||
/// @brief Get a UV coordinate slot, returns an empty array if the requested slot does not exist.
|
||||
/// @param index The requested texture coordinate slot.
|
||||
/// @return The texture coordinates.
|
||||
const std::vector<aiVector2D>& GetTextureCoords( unsigned int index ) const;
|
||||
|
||||
/** Get a UV coordinate slot, returns an empty array if
|
||||
* the requested slot does not exist. */
|
||||
/// @brief Get a UV coordinate slot, returns an empty array if the requested slot does not exist.
|
||||
/// @param index The requested texture coordinate slot.
|
||||
/// @return The texture coordinate channel name.
|
||||
std::string GetTextureCoordChannelName( unsigned int index ) const;
|
||||
|
||||
/** Get a vertex color coordinate slot, returns an empty array if
|
||||
* the requested slot does not exist. */
|
||||
/// @brief Get a vertex color coordinate slot, returns an empty array if the requested slot does not exist.
|
||||
/// @param index The requested texture coordinate slot.
|
||||
/// @return The vertex color vector.
|
||||
const std::vector<aiColor4D>& GetVertexColors( unsigned int index ) const;
|
||||
|
||||
/** Get per-face-vertex material assignments */
|
||||
/// @brief Get per-face-vertex material assignments.
|
||||
/// @return The Material indices Array.
|
||||
const MatIndexArray& GetMaterialIndices() const;
|
||||
|
||||
/** Convert from a fbx file vertex index (for example from a #Cluster weight) or nullptr
|
||||
* if the vertex index is not valid. */
|
||||
/// @brief Convert from a fbx file vertex index (for example from a #Cluster weight) or nullptr if the vertex index is not valid.
|
||||
/// @param in_index The requested input index.
|
||||
/// @param count The number of indices.
|
||||
/// @return The indices.
|
||||
const unsigned int* ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const;
|
||||
|
||||
/** Determine the face to which a particular output vertex index belongs.
|
||||
* This mapping is always unique. */
|
||||
/// @brief Determine the face to which a particular output vertex index belongs.
|
||||
/// This mapping is always unique.
|
||||
/// @param in_index The requested input index.
|
||||
/// @return The face-to-vertex index.
|
||||
unsigned int FaceForVertexIndex( unsigned int in_index ) const;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -45,12 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
|
||||
|
||||
//#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
|
||||
#include "Common/Compression.h"
|
||||
//# include <zlib.h>
|
||||
//#else
|
||||
//# include "../contrib/zlib/zlib.h"
|
||||
//#endif
|
||||
|
||||
#include "FBXTokenizer.h"
|
||||
#include "FBXParser.h"
|
||||
|
|
@ -88,6 +83,7 @@ namespace {
|
|||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AI_WONT_RETURN void ParseError(const std::string& message, TokenPtr token) AI_WONT_RETURN_SUFFIX;
|
||||
void ParseError(const std::string& message, TokenPtr token)
|
||||
{
|
||||
if(token) {
|
||||
|
|
@ -115,8 +111,11 @@ namespace Assimp {
|
|||
namespace FBX {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Element::Element(const Token& key_token, Parser& parser) : key_token(key_token) {
|
||||
Element::Element(const Token& key_token, Parser& parser) :
|
||||
key_token(key_token), compound(nullptr)
|
||||
{
|
||||
TokenPtr n = nullptr;
|
||||
StackAllocator &allocator = parser.GetAllocator();
|
||||
do {
|
||||
n = parser.AdvanceToNextToken();
|
||||
if(!n) {
|
||||
|
|
@ -145,7 +144,7 @@ Element::Element(const Token& key_token, Parser& parser) : key_token(key_token)
|
|||
}
|
||||
|
||||
if (n->Type() == TokenType_OPEN_BRACKET) {
|
||||
compound.reset(new Scope(parser));
|
||||
compound = new_Scope(parser);
|
||||
|
||||
// current token should be a TOK_CLOSE_BRACKET
|
||||
n = parser.CurrentToken();
|
||||
|
|
@ -163,6 +162,15 @@ Element::Element(const Token& key_token, Parser& parser) : key_token(key_token)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Element::~Element()
|
||||
{
|
||||
if (compound) {
|
||||
delete_Scope(compound);
|
||||
}
|
||||
|
||||
// no need to delete tokens, they are owned by the parser
|
||||
}
|
||||
|
||||
Scope::Scope(Parser& parser,bool topLevel)
|
||||
{
|
||||
if(!topLevel) {
|
||||
|
|
@ -172,6 +180,7 @@ Scope::Scope(Parser& parser,bool topLevel)
|
|||
}
|
||||
}
|
||||
|
||||
StackAllocator &allocator = parser.GetAllocator();
|
||||
TokenPtr n = parser.AdvanceToNextToken();
|
||||
if (n == nullptr) {
|
||||
ParseError("unexpected end of file");
|
||||
|
|
@ -187,37 +196,46 @@ Scope::Scope(Parser& parser,bool topLevel)
|
|||
if (str.empty()) {
|
||||
ParseError("unexpected content: empty string.");
|
||||
}
|
||||
|
||||
elements.insert(ElementMap::value_type(str,new_Element(*n,parser)));
|
||||
|
||||
auto *element = new_Element(*n, parser);
|
||||
|
||||
// Element() should stop at the next Key token (or right after a Close token)
|
||||
n = parser.CurrentToken();
|
||||
if (n == nullptr) {
|
||||
if (topLevel) {
|
||||
elements.insert(ElementMap::value_type(str, element));
|
||||
return;
|
||||
}
|
||||
delete_Element(element);
|
||||
ParseError("unexpected end of file",parser.LastToken());
|
||||
} else {
|
||||
elements.insert(ElementMap::value_type(str, element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Scope::~Scope() {
|
||||
for(ElementMap::value_type& v : elements) {
|
||||
delete v.second;
|
||||
Scope::~Scope()
|
||||
{
|
||||
// This collection does not own the memory for the elements, but we need to call their d'tor:
|
||||
|
||||
for (ElementMap::value_type &v : elements) {
|
||||
delete_Element(v.second);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Parser::Parser (const TokenList& tokens, bool is_binary)
|
||||
: tokens(tokens)
|
||||
, last()
|
||||
, current()
|
||||
, cursor(tokens.begin())
|
||||
, is_binary(is_binary)
|
||||
Parser::Parser(const TokenList &tokens, StackAllocator &allocator, bool is_binary) :
|
||||
tokens(tokens), allocator(allocator), last(), current(), cursor(tokens.begin()), is_binary(is_binary)
|
||||
{
|
||||
ASSIMP_LOG_DEBUG("Parsing FBX tokens");
|
||||
root.reset(new Scope(*this,true));
|
||||
root = new_Scope(*this, true);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Parser::~Parser()
|
||||
{
|
||||
delete_Scope(root);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/LogAux.h>
|
||||
#include <assimp/fast_atof.h>
|
||||
|
||||
#include "Common/StackAllocator.h"
|
||||
#include "FBXCompileConfig.h"
|
||||
#include "FBXTokenizer.h"
|
||||
|
||||
|
|
@ -62,15 +63,14 @@ class Scope;
|
|||
class Parser;
|
||||
class Element;
|
||||
|
||||
// XXX should use C++11's unique_ptr - but assimp's need to keep working with 03
|
||||
typedef std::vector< Scope* > ScopeList;
|
||||
typedef std::fbx_unordered_multimap< std::string, Element* > ElementMap;
|
||||
|
||||
typedef std::pair<ElementMap::const_iterator,ElementMap::const_iterator> ElementCollection;
|
||||
|
||||
# define new_Scope new Scope
|
||||
# define new_Element new Element
|
||||
using ScopeList = std::vector<Scope*>;
|
||||
using ElementMap = std::fbx_unordered_multimap< std::string, Element*>;
|
||||
using ElementCollection = std::pair<ElementMap::const_iterator,ElementMap::const_iterator>;
|
||||
|
||||
#define new_Scope new (allocator.Allocate(sizeof(Scope))) Scope
|
||||
#define new_Element new (allocator.Allocate(sizeof(Element))) Element
|
||||
#define delete_Scope(_p) (_p)->~Scope()
|
||||
#define delete_Element(_p) (_p)->~Element()
|
||||
|
||||
/** FBX data entity that consists of a key:value tuple.
|
||||
*
|
||||
|
|
@ -82,15 +82,16 @@ typedef std::pair<ElementMap::const_iterator,ElementMap::const_iterator> Element
|
|||
* @endverbatim
|
||||
*
|
||||
* As can be seen in this sample, elements can contain nested #Scope
|
||||
* as their trailing member. **/
|
||||
* as their trailing member.
|
||||
**/
|
||||
class Element
|
||||
{
|
||||
public:
|
||||
Element(const Token& key_token, Parser& parser);
|
||||
~Element() = default;
|
||||
~Element();
|
||||
|
||||
const Scope* Compound() const {
|
||||
return compound.get();
|
||||
return compound;
|
||||
}
|
||||
|
||||
const Token& KeyToken() const {
|
||||
|
|
@ -104,7 +105,7 @@ public:
|
|||
private:
|
||||
const Token& key_token;
|
||||
TokenList tokens;
|
||||
std::unique_ptr<Scope> compound;
|
||||
Scope* compound;
|
||||
};
|
||||
|
||||
/** FBX data entity that consists of a 'scope', a collection
|
||||
|
|
@ -133,7 +134,7 @@ public:
|
|||
const char* elementNameCStr = elementName.c_str();
|
||||
for (auto element = elements.begin(); element != elements.end(); ++element)
|
||||
{
|
||||
if (!ASSIMP_strincmp(element->first.c_str(), elementNameCStr, MAXLEN)) {
|
||||
if (!ASSIMP_strincmp(element->first.c_str(), elementNameCStr, AI_MAXLEN)) {
|
||||
return element->second;
|
||||
}
|
||||
}
|
||||
|
|
@ -159,17 +160,21 @@ class Parser
|
|||
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() = default;
|
||||
Parser(const TokenList &tokens, StackAllocator &allocator, bool is_binary);
|
||||
~Parser();
|
||||
|
||||
const Scope& GetRootScope() const {
|
||||
return *root.get();
|
||||
return *root;
|
||||
}
|
||||
|
||||
bool IsBinary() const {
|
||||
return is_binary;
|
||||
}
|
||||
|
||||
StackAllocator &GetAllocator() {
|
||||
return allocator;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Scope;
|
||||
friend class Element;
|
||||
|
|
@ -180,10 +185,10 @@ private:
|
|||
|
||||
private:
|
||||
const TokenList& tokens;
|
||||
|
||||
StackAllocator &allocator;
|
||||
TokenPtr last, current;
|
||||
TokenList::const_iterator cursor;
|
||||
std::unique_ptr<Scope> root;
|
||||
Scope *root;
|
||||
|
||||
const bool is_binary;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
@ -243,7 +243,6 @@ DirectPropertyMap PropertyTable::GetUnparsedProperties() const
|
|||
|
||||
// Read the element's value.
|
||||
// Wrap the naked pointer (since the call site is required to acquire ownership)
|
||||
// std::unique_ptr from C++11 would be preferred both as a wrapper and a return value.
|
||||
std::shared_ptr<Property> prop = std::shared_ptr<Property>(ReadTypedProperty(*currentElement.second));
|
||||
|
||||
// Element could not be read. Skip it.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
@ -94,7 +94,8 @@ AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line,
|
|||
|
||||
// process a potential data token up to 'cur', adding it to 'output_tokens'.
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ProcessDataToken( TokenList& output_tokens, const char*& start, const char*& end,
|
||||
void ProcessDataToken(TokenList &output_tokens, StackAllocator &token_allocator,
|
||||
const char*& start, const char*& end,
|
||||
unsigned int line,
|
||||
unsigned int column,
|
||||
TokenType type = TokenType_DATA,
|
||||
|
|
@ -131,8 +132,7 @@ void ProcessDataToken( TokenList& output_tokens, const char*& start, const char*
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Tokenize(TokenList& output_tokens, const char* input)
|
||||
{
|
||||
void Tokenize(TokenList &output_tokens, const char *input, StackAllocator &token_allocator) {
|
||||
ai_assert(input);
|
||||
ASSIMP_LOG_DEBUG("Tokenizing ASCII FBX file");
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ void Tokenize(TokenList& output_tokens, const char* input)
|
|||
in_double_quotes = false;
|
||||
token_end = cur;
|
||||
|
||||
ProcessDataToken(output_tokens,token_begin,token_end,line,column);
|
||||
ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column);
|
||||
pending_data_token = false;
|
||||
}
|
||||
continue;
|
||||
|
|
@ -181,30 +181,30 @@ void Tokenize(TokenList& output_tokens, const char* input)
|
|||
continue;
|
||||
|
||||
case ';':
|
||||
ProcessDataToken(output_tokens,token_begin,token_end,line,column);
|
||||
ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column);
|
||||
comment = true;
|
||||
continue;
|
||||
|
||||
case '{':
|
||||
ProcessDataToken(output_tokens,token_begin,token_end, line, column);
|
||||
ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column);
|
||||
output_tokens.push_back(new_Token(cur,cur+1,TokenType_OPEN_BRACKET,line,column));
|
||||
continue;
|
||||
|
||||
case '}':
|
||||
ProcessDataToken(output_tokens,token_begin,token_end,line,column);
|
||||
ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column);
|
||||
output_tokens.push_back(new_Token(cur,cur+1,TokenType_CLOSE_BRACKET,line,column));
|
||||
continue;
|
||||
|
||||
case ',':
|
||||
if (pending_data_token) {
|
||||
ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_DATA,true);
|
||||
ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column, TokenType_DATA, true);
|
||||
}
|
||||
output_tokens.push_back(new_Token(cur,cur+1,TokenType_COMMA,line,column));
|
||||
continue;
|
||||
|
||||
case ':':
|
||||
if (pending_data_token) {
|
||||
ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_KEY,true);
|
||||
ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column, TokenType_KEY, true);
|
||||
}
|
||||
else {
|
||||
TokenizeError("unexpected colon", line, column);
|
||||
|
|
@ -226,7 +226,7 @@ void Tokenize(TokenList& output_tokens, const char* input)
|
|||
}
|
||||
}
|
||||
|
||||
ProcessDataToken(output_tokens,token_begin,token_end,line,column,type);
|
||||
ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column, type);
|
||||
}
|
||||
|
||||
pending_data_token = false;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define INCLUDED_AI_FBX_TOKENIZER_H
|
||||
|
||||
#include "FBXCompileConfig.h"
|
||||
#include "Common/StackAllocator.h"
|
||||
#include <assimp/ai_assert.h>
|
||||
#include <assimp/defs.h>
|
||||
#include <vector>
|
||||
|
|
@ -154,11 +155,11 @@ private:
|
|||
const unsigned int column;
|
||||
};
|
||||
|
||||
// XXX should use C++11's unique_ptr - but assimp's need to keep working with 03
|
||||
typedef const Token* TokenPtr;
|
||||
typedef std::vector< TokenPtr > TokenList;
|
||||
|
||||
#define new_Token new Token
|
||||
#define new_Token new (token_allocator.Allocate(sizeof(Token))) Token
|
||||
#define delete_Token(_p) (_p)->~Token()
|
||||
|
||||
|
||||
/** Main FBX tokenizer function. Transform input buffer into a list of preprocessed tokens.
|
||||
|
|
@ -168,7 +169,7 @@ typedef std::vector< TokenPtr > TokenList;
|
|||
* @param output_tokens Receives a list of all tokens in the input data.
|
||||
* @param input_buffer Textual input buffer to be processed, 0-terminated.
|
||||
* @throw DeadlyImportError if something goes wrong */
|
||||
void Tokenize(TokenList& output_tokens, const char* input);
|
||||
void Tokenize(TokenList &output_tokens, const char *input, StackAllocator &tokenAllocator);
|
||||
|
||||
|
||||
/** Tokenizer function for binary FBX files.
|
||||
|
|
@ -179,7 +180,7 @@ void Tokenize(TokenList& output_tokens, const char* input);
|
|||
* @param input_buffer Binary input buffer to be processed.
|
||||
* @param length Length of input buffer, in bytes. There is no 0-terminal.
|
||||
* @throw DeadlyImportError if something goes wrong */
|
||||
void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length);
|
||||
void TokenizeBinary(TokenList &output_tokens, const char *input, size_t length, StackAllocator &tokenAllocator);
|
||||
|
||||
|
||||
} // ! FBX
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
@ -155,7 +155,7 @@ size_t DecodeBase64(const char* in, size_t inLength, uint8_t* out, size_t maxOut
|
|||
const size_t realLength = inLength - size_t(in[inLength - 1] == '=') - size_t(in[inLength - 2] == '=');
|
||||
size_t dst_offset = 0;
|
||||
int val = 0, valb = -8;
|
||||
for (size_t src_offset = 0; src_offset < realLength; ++src_offset)
|
||||
for (size_t src_offset = 0; src_offset < realLength && dst_offset < maxOutLength; ++src_offset)
|
||||
{
|
||||
const uint8_t table_value = Util::DecodeBase64(in[src_offset]);
|
||||
if (table_value == 255)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
Copyright (c) 2006-2024, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
|
@ -66,6 +66,17 @@ struct delete_fun
|
|||
}
|
||||
};
|
||||
|
||||
/** helper for std::for_each to call the destructor on all items in a container without freeing their heap*/
|
||||
template <typename T>
|
||||
struct destructor_fun {
|
||||
void operator()(const volatile T* del) {
|
||||
if (del) {
|
||||
del->~T();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Get a string representation for a #TokenType. */
|
||||
const char* TokenTypeString(TokenType t);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue