Initial commit

This commit is contained in:
Martin Felis
2021-11-11 21:22:24 +01:00
commit b78045ffe7
812 changed files with 421882 additions and 0 deletions
+325
View File
@@ -0,0 +1,325 @@
//----------------------------------------------------------------------------//
// //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
// and distributed under the MIT License (MIT). //
// //
// Copyright (c) Guillaume Blanc //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
// DEALINGS IN THE SOFTWARE. //
// //
//----------------------------------------------------------------------------//
#include "ozz/animation/offline/fbx/fbx.h"
#include "ozz/base/log.h"
#include "ozz/base/maths/transform.h"
#include "ozz/base/memory/allocator.h"
namespace ozz {
namespace animation {
namespace offline {
namespace fbx {
FbxManagerInstance::FbxManagerInstance() : fbx_manager_(nullptr) {
// Instantiate Fbx manager, mostly a memory manager.
fbx_manager_ = FbxManager::Create();
// Logs SDK version.
ozz::log::Log() << "FBX importer version " << fbx_manager_->GetVersion()
<< "." << std::endl;
}
FbxManagerInstance::~FbxManagerInstance() {
// Destroy the manager and all associated objects.
fbx_manager_->Destroy();
fbx_manager_ = nullptr;
}
FbxDefaultIOSettings::FbxDefaultIOSettings(const FbxManagerInstance& _manager)
: io_settings_(nullptr) {
io_settings_ = FbxIOSettings::Create(_manager, IOSROOT);
io_settings_->SetBoolProp(IMP_FBX_MATERIAL, false);
io_settings_->SetBoolProp(IMP_FBX_TEXTURE, false);
io_settings_->SetBoolProp(IMP_FBX_MODEL, false);
io_settings_->SetBoolProp(IMP_FBX_SHAPE, false);
io_settings_->SetBoolProp(IMP_FBX_LINK, false);
io_settings_->SetBoolProp(IMP_FBX_GOBO, false);
}
FbxDefaultIOSettings::~FbxDefaultIOSettings() {
io_settings_->Destroy();
io_settings_ = nullptr;
}
FbxAnimationIOSettings::FbxAnimationIOSettings(
const FbxManagerInstance& _manager)
: FbxDefaultIOSettings(_manager) {}
FbxSkeletonIOSettings::FbxSkeletonIOSettings(const FbxManagerInstance& _manager)
: FbxDefaultIOSettings(_manager) {
settings()->SetBoolProp(IMP_FBX_ANIMATION, false);
}
FbxSceneLoader::FbxSceneLoader(const char* _filename, const char* _password,
const FbxManagerInstance& _manager,
const FbxDefaultIOSettings& _io_settings)
: scene_(nullptr), converter_(nullptr) {
// Create an importer.
FbxImporter* importer = FbxImporter::Create(_manager, "ozz file importer");
const bool initialized = importer->Initialize(_filename, -1, _io_settings);
ImportScene(importer, initialized, _password, _manager, _io_settings);
// Destroy the importer
importer->Destroy();
}
FbxSceneLoader::FbxSceneLoader(FbxStream* _stream, const char* _password,
const FbxManagerInstance& _manager,
const FbxDefaultIOSettings& _io_settings)
: scene_(nullptr), converter_(nullptr) {
// Create an importer.
FbxImporter* importer = FbxImporter::Create(_manager, "ozz stream importer");
const bool initialized =
importer->Initialize(_stream, nullptr, -1, _io_settings);
ImportScene(importer, initialized, _password, _manager, _io_settings);
// Destroy the importer
importer->Destroy();
}
void FbxSceneLoader::ImportScene(FbxImporter* _importer,
const bool _initialized, const char* _password,
const FbxManagerInstance& _manager,
const FbxDefaultIOSettings& _io_settings) {
// Get the version of the FBX file format.
int major, minor, revision;
_importer->GetFileVersion(major, minor, revision);
if (!_initialized) // Problem with the file to be imported.
{
const FbxString error = _importer->GetStatus().GetErrorString();
ozz::log::Err() << "FbxImporter initialization failed with error: "
<< error.Buffer() << std::endl;
if (_importer->GetStatus().GetCode() == FbxStatus::eInvalidFileVersion) {
ozz::log::Err() << "FBX file version is " << major << "." << minor << "."
<< revision << "." << std::endl;
}
} else {
if (_importer->IsFBX()) {
ozz::log::Log() << "FBX file version is " << major << "." << minor << "."
<< revision << "." << std::endl;
}
// Load the scene.
scene_ = FbxScene::Create(_manager, "ozz scene");
bool imported = _importer->Import(scene_);
if (!imported && // The import file may have a password
_importer->GetStatus().GetCode() == FbxStatus::ePasswordError) {
_io_settings.settings()->SetStringProp(IMP_FBX_PASSWORD, _password);
_io_settings.settings()->SetBoolProp(IMP_FBX_PASSWORD_ENABLE, true);
// Retries to import the scene.
imported = _importer->Import(scene_);
if (!imported &&
_importer->GetStatus().GetCode() == FbxStatus::ePasswordError) {
ozz::log::Err() << "Incorrect password." << std::endl;
// scene_ will be destroyed because imported is false.
}
}
// Setup axis and system converter.
if (imported) {
FbxGlobalSettings& settings = scene_->GetGlobalSettings();
converter_ = New<FbxSystemConverter>(settings.GetAxisSystem(),
settings.GetSystemUnit());
}
// Clear the scene if import failed.
if (!imported) {
scene_->Destroy();
scene_ = nullptr;
}
}
}
FbxSceneLoader::~FbxSceneLoader() {
if (scene_) {
scene_->Destroy();
scene_ = nullptr;
}
if (converter_) {
ozz::Delete(converter_);
converter_ = nullptr;
}
}
namespace {
ozz::math::Float4x4 BuildAxisSystemMatrix(const FbxAxisSystem& _system) {
int sign;
ozz::math::SimdFloat4 up = ozz::math::simd_float4::y_axis();
ozz::math::SimdFloat4 at = ozz::math::simd_float4::z_axis();
// The EUpVector specifies which axis has the up and down direction in the
// system (typically this is the Y or Z axis). The sign of the EUpVector is
// applied to represent the direction (1 is up and -1 is down relative to the
// observer).
const FbxAxisSystem::EUpVector eup = _system.GetUpVector(sign);
switch (eup) {
case FbxAxisSystem::eXAxis: {
up = math::simd_float4::Load(1.f * sign, 0.f, 0.f, 0.f);
// If the up axis is X, the remain two axes will be Y And Z, so the
// ParityEven is Y, and the ParityOdd is Z
if (_system.GetFrontVector(sign) == FbxAxisSystem::eParityEven) {
at = math::simd_float4::Load(0.f, 1.f * sign, 0.f, 0.f);
} else {
at = math::simd_float4::Load(0.f, 0.f, 1.f * sign, 0.f);
}
break;
}
case FbxAxisSystem::eYAxis: {
up = math::simd_float4::Load(0.f, 1.f * sign, 0.f, 0.f);
// If the up axis is Y, the remain two axes will X And Z, so the
// ParityEven is X, and the ParityOdd is Z
if (_system.GetFrontVector(sign) == FbxAxisSystem::eParityEven) {
at = math::simd_float4::Load(1.f * sign, 0.f, 0.f, 0.f);
} else {
at = math::simd_float4::Load(0.f, 0.f, 1.f * sign, 0.f);
}
break;
}
case FbxAxisSystem::eZAxis: {
up = math::simd_float4::Load(0.f, 0.f, 1.f * sign, 0.f);
// If the up axis is Z, the remain two axes will X And Y, so the
// ParityEven is X, and the ParityOdd is Y
if (_system.GetFrontVector(sign) == FbxAxisSystem::eParityEven) {
at = math::simd_float4::Load(1.f * sign, 0.f, 0.f, 0.f);
} else {
at = math::simd_float4::Load(0.f, 1.f * sign, 0.f, 0.f);
}
break;
}
default: {
assert(false && "Invalid FbxAxisSystem");
break;
}
}
// If the front axis and the up axis are determined, the third axis will be
// automatically determined as the left one. The ECoordSystem enum is a
// parameter to determine the direction of the third axis just as the
// EUpVector sign. It determines if the axis system is right-handed or
// left-handed just as the enum values.
ozz::math::SimdFloat4 right;
if (_system.GetCoorSystem() == FbxAxisSystem::eRightHanded) {
right = math::Cross3(up, at);
} else {
right = math::Cross3(at, up);
}
const ozz::math::Float4x4 matrix = {
{right, up, at, ozz::math::simd_float4::w_axis()}};
return matrix;
}
} // namespace
FbxSystemConverter::FbxSystemConverter(const FbxAxisSystem& _from_axis,
const FbxSystemUnit& _from_unit) {
// Build axis system conversion matrix.
const math::Float4x4 from_matrix = BuildAxisSystemMatrix(_from_axis);
// Finds unit conversion ratio to meters, where GetScaleFactor() is in cm.
const float to_meters =
static_cast<float>(_from_unit.GetScaleFactor()) * .01f;
// Builds conversion matrices.
convert_ = Invert(from_matrix) *
math::Float4x4::Scaling(math::simd_float4::Load1(to_meters));
inverse_convert_ = Invert(convert_);
inverse_transpose_convert_ = Transpose(inverse_convert_);
}
math::Float4x4 FbxSystemConverter::ConvertMatrix(const FbxAMatrix& _m) const {
const ozz::math::Float4x4 m = {{
ozz::math::simd_float4::Load(
static_cast<float>(_m[0][0]), static_cast<float>(_m[0][1]),
static_cast<float>(_m[0][2]), static_cast<float>(_m[0][3])),
ozz::math::simd_float4::Load(
static_cast<float>(_m[1][0]), static_cast<float>(_m[1][1]),
static_cast<float>(_m[1][2]), static_cast<float>(_m[1][3])),
ozz::math::simd_float4::Load(
static_cast<float>(_m[2][0]), static_cast<float>(_m[2][1]),
static_cast<float>(_m[2][2]), static_cast<float>(_m[2][3])),
ozz::math::simd_float4::Load(
static_cast<float>(_m[3][0]), static_cast<float>(_m[3][1]),
static_cast<float>(_m[3][2]), static_cast<float>(_m[3][3])),
}};
return convert_ * m * inverse_convert_;
}
math::Float3 FbxSystemConverter::ConvertPoint(const FbxVector4& _p) const {
const math::SimdFloat4 p_in = math::simd_float4::Load(
static_cast<float>(_p[0]), static_cast<float>(_p[1]),
static_cast<float>(_p[2]), 1.f);
const math::SimdFloat4 p_out = convert_ * p_in;
math::Float3 ret;
math::Store3PtrU(p_out, &ret.x);
return ret;
}
math::Float3 FbxSystemConverter::ConvertVector(const FbxVector4& _p) const {
const math::SimdFloat4 p_in = math::simd_float4::Load(
static_cast<float>(_p[0]), static_cast<float>(_p[1]),
static_cast<float>(_p[2]), 0.f);
const math::SimdFloat4 p_out = inverse_transpose_convert_ * p_in;
math::Float3 ret;
math::Store3PtrU(p_out, &ret.x);
return ret;
}
bool FbxSystemConverter::ConvertTransform(const FbxAMatrix& _m,
math::Transform* _transform) const {
assert(_transform);
const math::Float4x4 matrix = ConvertMatrix(_m);
math::SimdFloat4 translation, rotation, scale;
if (ToAffine(matrix, &translation, &rotation, &scale)) {
ozz::math::Transform transform;
math::Store3PtrU(translation, &_transform->translation.x);
math::StorePtrU(math::Normalize4(rotation), &_transform->rotation.x);
math::Store3PtrU(scale, &_transform->scale.x);
return true;
}
// Failed to decompose matrix, reset transform to identity.
*_transform = ozz::math::Transform::identity();
return false;
}
} // namespace fbx
} // namespace offline
} // namespace animation
} // namespace ozz