Fix model importer to use precomputed Offset Matrix for skeletal model bones
#1525
This commit is contained in:
@@ -366,9 +366,7 @@ void ProcessNodes(OpenFbxImporterData& data, const ofbx::Object* aNode, int32 pa
|
|||||||
{
|
{
|
||||||
node.LodIndex = data.Nodes[parentIndex].LodIndex;
|
node.LodIndex = data.Nodes[parentIndex].LodIndex;
|
||||||
if (node.LodIndex == 0)
|
if (node.LodIndex == 0)
|
||||||
{
|
|
||||||
node.LodIndex = ModelTool::DetectLodIndex(node.Name);
|
node.LodIndex = ModelTool::DetectLodIndex(node.Name);
|
||||||
}
|
|
||||||
ASSERT(Math::IsInRange(node.LodIndex, 0, MODEL_MAX_LODS - 1));
|
ASSERT(Math::IsInRange(node.LodIndex, 0, MODEL_MAX_LODS - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,8 +414,9 @@ Matrix GetOffsetMatrix(OpenFbxImporterData& data, const ofbx::Mesh* mesh, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//return Matrix::Identity;
|
||||||
return ToMatrix(node->getGlobalTransform());
|
return ToMatrix(node->getGlobalTransform());
|
||||||
#elif 1
|
#else
|
||||||
Matrix t = Matrix::Identity;
|
Matrix t = Matrix::Identity;
|
||||||
const int32 boneIdx = data.FindBone(node);
|
const int32 boneIdx = data.FindBone(node);
|
||||||
int32 idx = data.Bones[boneIdx].NodeIndex;
|
int32 idx = data.Bones[boneIdx].NodeIndex;
|
||||||
@@ -427,17 +426,6 @@ Matrix GetOffsetMatrix(OpenFbxImporterData& data, const ofbx::Mesh* mesh, const
|
|||||||
idx = data.Nodes[idx].ParentIndex;
|
idx = data.Nodes[idx].ParentIndex;
|
||||||
} while (idx != -1);
|
} while (idx != -1);
|
||||||
return t;
|
return t;
|
||||||
#else
|
|
||||||
auto* skin = mesh->getGeometry()->getSkin();
|
|
||||||
for (int i = 0, c = skin->getClusterCount(); i < c; i++)
|
|
||||||
{
|
|
||||||
const ofbx::Cluster* cluster = skin->getCluster(i);
|
|
||||||
if (cluster->getLink() == node)
|
|
||||||
{
|
|
||||||
return ToMatrix(cluster->getTransformLinkMatrix());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Matrix::Identity;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,17 +443,14 @@ bool ImportBones(OpenFbxImporterData& data, String& errorMsg)
|
|||||||
const auto aMesh = data.Scene->getMesh(i);
|
const auto aMesh = data.Scene->getMesh(i);
|
||||||
const auto aGeometry = aMesh->getGeometry();
|
const auto aGeometry = aMesh->getGeometry();
|
||||||
const ofbx::Skin* skin = aGeometry->getSkin();
|
const ofbx::Skin* skin = aGeometry->getSkin();
|
||||||
|
|
||||||
if (skin == nullptr || IsMeshInvalid(aMesh))
|
if (skin == nullptr || IsMeshInvalid(aMesh))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (int clusterIndex = 0, c = skin->getClusterCount(); clusterIndex < c; clusterIndex++)
|
for (int clusterIndex = 0, clusterCount = skin->getClusterCount(); clusterIndex < clusterCount; clusterIndex++)
|
||||||
{
|
{
|
||||||
const ofbx::Cluster* cluster = skin->getCluster(clusterIndex);
|
const ofbx::Cluster* cluster = skin->getCluster(clusterIndex);
|
||||||
|
|
||||||
if (cluster->getIndicesCount() == 0)
|
if (cluster->getIndicesCount() == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto link = cluster->getLink();
|
const auto link = cluster->getLink();
|
||||||
ASSERT(link != nullptr);
|
ASSERT(link != nullptr);
|
||||||
|
|
||||||
@@ -487,7 +472,7 @@ bool ImportBones(OpenFbxImporterData& data, String& errorMsg)
|
|||||||
|
|
||||||
// Add bone
|
// Add bone
|
||||||
boneIndex = data.Bones.Count();
|
boneIndex = data.Bones.Count();
|
||||||
data.Bones.EnsureCapacity(Math::Max(128, boneIndex + 16));
|
data.Bones.EnsureCapacity(256);
|
||||||
data.Bones.Resize(boneIndex + 1);
|
data.Bones.Resize(boneIndex + 1);
|
||||||
auto& bone = data.Bones[boneIndex];
|
auto& bone = data.Bones[boneIndex];
|
||||||
|
|
||||||
@@ -495,7 +480,7 @@ bool ImportBones(OpenFbxImporterData& data, String& errorMsg)
|
|||||||
bone.NodeIndex = nodeIndex;
|
bone.NodeIndex = nodeIndex;
|
||||||
bone.ParentBoneIndex = -1;
|
bone.ParentBoneIndex = -1;
|
||||||
bone.FbxObj = link;
|
bone.FbxObj = link;
|
||||||
bone.OffsetMatrix = GetOffsetMatrix(data, aMesh, link);
|
bone.OffsetMatrix = GetOffsetMatrix(data, aMesh, link) * Matrix::Scaling(data.GlobalSettings.UnitScaleFactor);
|
||||||
bone.OffsetMatrix.Invert();
|
bone.OffsetMatrix.Invert();
|
||||||
|
|
||||||
// Mirror offset matrices (RH to LH)
|
// Mirror offset matrices (RH to LH)
|
||||||
@@ -547,9 +532,7 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
|
|||||||
// Vertex positions
|
// Vertex positions
|
||||||
mesh.Positions.Resize(vertexCount, false);
|
mesh.Positions.Resize(vertexCount, false);
|
||||||
for (int i = 0; i < vertexCount; i++)
|
for (int i = 0; i < vertexCount; i++)
|
||||||
{
|
|
||||||
mesh.Positions.Get()[i] = ToFloat3(vertices[i + firstVertexOffset]);
|
mesh.Positions.Get()[i] = ToFloat3(vertices[i + firstVertexOffset]);
|
||||||
}
|
|
||||||
|
|
||||||
// Indices (dummy index buffer)
|
// Indices (dummy index buffer)
|
||||||
if (vertexCount % 3 != 0)
|
if (vertexCount % 3 != 0)
|
||||||
@@ -559,24 +542,18 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
|
|||||||
}
|
}
|
||||||
mesh.Indices.Resize(vertexCount, false);
|
mesh.Indices.Resize(vertexCount, false);
|
||||||
for (int i = 0; i < vertexCount; i++)
|
for (int i = 0; i < vertexCount; i++)
|
||||||
{
|
|
||||||
mesh.Indices.Get()[i] = i;
|
mesh.Indices.Get()[i] = i;
|
||||||
}
|
|
||||||
|
|
||||||
// Texture coordinates
|
// Texture coordinates
|
||||||
if (uvs)
|
if (uvs)
|
||||||
{
|
{
|
||||||
mesh.UVs.Resize(vertexCount, false);
|
mesh.UVs.Resize(vertexCount, false);
|
||||||
for (int i = 0; i < vertexCount; i++)
|
for (int i = 0; i < vertexCount; i++)
|
||||||
{
|
|
||||||
mesh.UVs.Get()[i] = ToFloat2(uvs[i + firstVertexOffset]);
|
mesh.UVs.Get()[i] = ToFloat2(uvs[i + firstVertexOffset]);
|
||||||
}
|
|
||||||
if (data.ConvertRH)
|
if (data.ConvertRH)
|
||||||
{
|
{
|
||||||
for (int32 v = 0; v < vertexCount; v++)
|
for (int32 v = 0; v < vertexCount; v++)
|
||||||
{
|
|
||||||
mesh.UVs[v].Y = 1.0f - mesh.UVs[v].Y;
|
mesh.UVs[v].Y = 1.0f - mesh.UVs[v].Y;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -593,16 +570,12 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
|
|||||||
{
|
{
|
||||||
mesh.Normals.Resize(vertexCount, false);
|
mesh.Normals.Resize(vertexCount, false);
|
||||||
for (int i = 0; i < vertexCount; i++)
|
for (int i = 0; i < vertexCount; i++)
|
||||||
{
|
|
||||||
mesh.Normals.Get()[i] = ToFloat3(normals[i + firstVertexOffset]);
|
mesh.Normals.Get()[i] = ToFloat3(normals[i + firstVertexOffset]);
|
||||||
}
|
|
||||||
if (data.ConvertRH)
|
if (data.ConvertRH)
|
||||||
{
|
{
|
||||||
// Mirror normals along the Z axis
|
// Mirror normals along the Z axis
|
||||||
for (int32 i = 0; i < vertexCount; i++)
|
for (int32 i = 0; i < vertexCount; i++)
|
||||||
{
|
|
||||||
mesh.Normals.Get()[i].Z *= -1.0f;
|
mesh.Normals.Get()[i].Z *= -1.0f;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,16 +588,12 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
|
|||||||
{
|
{
|
||||||
mesh.Tangents.Resize(vertexCount, false);
|
mesh.Tangents.Resize(vertexCount, false);
|
||||||
for (int i = 0; i < vertexCount; i++)
|
for (int i = 0; i < vertexCount; i++)
|
||||||
{
|
|
||||||
mesh.Tangents.Get()[i] = ToFloat3(tangents[i + firstVertexOffset]);
|
mesh.Tangents.Get()[i] = ToFloat3(tangents[i + firstVertexOffset]);
|
||||||
}
|
|
||||||
if (data.ConvertRH)
|
if (data.ConvertRH)
|
||||||
{
|
{
|
||||||
// Mirror tangents along the Z axis
|
// Mirror tangents along the Z axis
|
||||||
for (int32 i = 0; i < vertexCount; i++)
|
for (int32 i = 0; i < vertexCount; i++)
|
||||||
{
|
|
||||||
mesh.Tangents.Get()[i].Z *= -1.0f;
|
mesh.Tangents.Get()[i].Z *= -1.0f;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -670,15 +639,11 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
|
|||||||
{
|
{
|
||||||
mesh.LightmapUVs.Resize(vertexCount, false);
|
mesh.LightmapUVs.Resize(vertexCount, false);
|
||||||
for (int i = 0; i < vertexCount; i++)
|
for (int i = 0; i < vertexCount; i++)
|
||||||
{
|
|
||||||
mesh.LightmapUVs.Get()[i] = ToFloat2(lightmapUVs[i + firstVertexOffset]);
|
mesh.LightmapUVs.Get()[i] = ToFloat2(lightmapUVs[i + firstVertexOffset]);
|
||||||
}
|
|
||||||
if (data.ConvertRH)
|
if (data.ConvertRH)
|
||||||
{
|
{
|
||||||
for (int32 v = 0; v < vertexCount; v++)
|
for (int32 v = 0; v < vertexCount; v++)
|
||||||
{
|
|
||||||
mesh.LightmapUVs[v].Y = 1.0f - mesh.LightmapUVs[v].Y;
|
mesh.LightmapUVs[v].Y = 1.0f - mesh.LightmapUVs[v].Y;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -692,9 +657,7 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
|
|||||||
{
|
{
|
||||||
mesh.Colors.Resize(vertexCount, false);
|
mesh.Colors.Resize(vertexCount, false);
|
||||||
for (int i = 0; i < vertexCount; i++)
|
for (int i = 0; i < vertexCount; i++)
|
||||||
{
|
|
||||||
mesh.Colors.Get()[i] = ToColor(colors[i + firstVertexOffset]);
|
mesh.Colors.Get()[i] = ToColor(colors[i + firstVertexOffset]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blend Indices and Blend Weights
|
// Blend Indices and Blend Weights
|
||||||
@@ -705,13 +668,11 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
|
|||||||
mesh.BlendIndices.SetAll(Int4::Zero);
|
mesh.BlendIndices.SetAll(Int4::Zero);
|
||||||
mesh.BlendWeights.SetAll(Float4::Zero);
|
mesh.BlendWeights.SetAll(Float4::Zero);
|
||||||
|
|
||||||
for (int clusterIndex = 0, c = skin->getClusterCount(); clusterIndex < c; clusterIndex++)
|
for (int clusterIndex = 0, clusterCount = skin->getClusterCount(); clusterIndex < clusterCount; clusterIndex++)
|
||||||
{
|
{
|
||||||
const ofbx::Cluster* cluster = skin->getCluster(clusterIndex);
|
const ofbx::Cluster* cluster = skin->getCluster(clusterIndex);
|
||||||
|
|
||||||
if (cluster->getIndicesCount() == 0)
|
if (cluster->getIndicesCount() == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto link = cluster->getLink();
|
const auto link = cluster->getLink();
|
||||||
ASSERT(link != nullptr);
|
ASSERT(link != nullptr);
|
||||||
|
|
||||||
@@ -815,15 +776,11 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
|
|||||||
{
|
{
|
||||||
// Mirror positions along the Z axis
|
// Mirror positions along the Z axis
|
||||||
for (int32 i = 0; i < vertexCount; i++)
|
for (int32 i = 0; i < vertexCount; i++)
|
||||||
{
|
|
||||||
mesh.Positions[i].Z *= -1.0f;
|
mesh.Positions[i].Z *= -1.0f;
|
||||||
}
|
|
||||||
for (auto& blendShapeData : mesh.BlendShapes)
|
for (auto& blendShapeData : mesh.BlendShapes)
|
||||||
{
|
{
|
||||||
for (auto& v : blendShapeData.Vertices)
|
for (auto& v : blendShapeData.Vertices)
|
||||||
{
|
|
||||||
v.PositionDelta.Z *= -1.0f;
|
v.PositionDelta.Z *= -1.0f;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -834,9 +791,7 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
|
|||||||
{
|
{
|
||||||
// Invert the order
|
// Invert the order
|
||||||
for (int32 i = 0; i < mesh.Indices.Count(); i += 3)
|
for (int32 i = 0; i < mesh.Indices.Count(); i += 3)
|
||||||
{
|
|
||||||
Swap(mesh.Indices[i], mesh.Indices[i + 2]);
|
Swap(mesh.Indices[i], mesh.Indices[i + 2]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((data.Options.CalculateTangents || !tangents) && mesh.UVs.HasItems())
|
if ((data.Options.CalculateTangents || !tangents) && mesh.UVs.HasItems())
|
||||||
@@ -888,9 +843,7 @@ bool ImportMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofbx
|
|||||||
{
|
{
|
||||||
node.LodIndex = data.Nodes[0].LodIndex;
|
node.LodIndex = data.Nodes[0].LodIndex;
|
||||||
if (node.LodIndex == 0)
|
if (node.LodIndex == 0)
|
||||||
{
|
|
||||||
node.LodIndex = ModelTool::DetectLodIndex(node.Name);
|
node.LodIndex = ModelTool::DetectLodIndex(node.Name);
|
||||||
}
|
|
||||||
ASSERT(Math::IsInRange(node.LodIndex, 0, MODEL_MAX_LODS - 1));
|
ASSERT(Math::IsInRange(node.LodIndex, 0, MODEL_MAX_LODS - 1));
|
||||||
}
|
}
|
||||||
node.LocalTransform = Transform::Identity;
|
node.LocalTransform = Transform::Identity;
|
||||||
@@ -999,7 +952,6 @@ void ImportCurve(const ofbx::AnimationCurveNode* curveNode, LinearCurve<T>& curv
|
|||||||
{
|
{
|
||||||
if (curveNode == nullptr)
|
if (curveNode == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto keyframes = curve.Resize(info.FramesCount);
|
const auto keyframes = curve.Resize(info.FramesCount);
|
||||||
const auto bone = curveNode->getBone();
|
const auto bone = curveNode->getBone();
|
||||||
Frame localFrame;
|
Frame localFrame;
|
||||||
|
|||||||
@@ -1320,14 +1320,17 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply import transform on root bones
|
// Apply import transform on bones
|
||||||
for (int32 i = 0; i < data.Skeleton.Bones.Count(); i++)
|
Matrix importMatrixInv;
|
||||||
|
importTransform.GetWorld(importMatrixInv);
|
||||||
|
importMatrixInv.Invert();
|
||||||
|
for (SkeletonBone& bone : data.Skeleton.Bones)
|
||||||
{
|
{
|
||||||
auto& bone = data.Skeleton.Bones.Get()[i];
|
|
||||||
if (bone.ParentIndex == -1)
|
if (bone.ParentIndex == -1)
|
||||||
{
|
{
|
||||||
bone.LocalTransform = importTransform.LocalToWorld(bone.LocalTransform);
|
bone.LocalTransform = importTransform.LocalToWorld(bone.LocalTransform);
|
||||||
}
|
}
|
||||||
|
bone.OffsetMatrix = importMatrixInv * bone.OffsetMatrix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1363,20 +1366,21 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
|
|||||||
// use SkeletonMapping<SkeletonBone> to map bones?
|
// use SkeletonMapping<SkeletonBone> to map bones?
|
||||||
|
|
||||||
// Calculate offset matrix (inverse bind pose transform) for every bone manually
|
// Calculate offset matrix (inverse bind pose transform) for every bone manually
|
||||||
{
|
/*{
|
||||||
for (int32 i = 0; i < data.Skeleton.Bones.Count(); i++)
|
for (SkeletonBone& bone : data.Skeleton.Bones)
|
||||||
{
|
{
|
||||||
Matrix t = Matrix::Identity;
|
Matrix t = Matrix::Identity;
|
||||||
int32 idx = data.Skeleton.Bones[i].NodeIndex;
|
int32 idx = bone.NodeIndex;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
t *= data.Skeleton.Nodes[idx].LocalTransform.GetWorld();
|
const SkeletonNode& node = data.Skeleton.Nodes[idx];
|
||||||
idx = data.Skeleton.Nodes[idx].ParentIndex;
|
t *= node.LocalTransform.GetWorld();
|
||||||
|
idx = node.ParentIndex;
|
||||||
} while (idx != -1);
|
} while (idx != -1);
|
||||||
t.Invert();
|
t.Invert();
|
||||||
data.Skeleton.Bones[i].OffsetMatrix = t;
|
bone.OffsetMatrix = t;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
#if USE_SKELETON_NODES_SORTING
|
#if USE_SKELETON_NODES_SORTING
|
||||||
// Sort skeleton nodes and bones hierarchy (parents first)
|
// Sort skeleton nodes and bones hierarchy (parents first)
|
||||||
|
|||||||
2
Source/ThirdParty/OpenFBX/ofbx.cpp
vendored
2
Source/ThirdParty/OpenFBX/ofbx.cpp
vendored
@@ -3538,7 +3538,7 @@ Object* Object::resolveObjectLink(int idx) const
|
|||||||
if (connection.to == id && connection.from != 0)
|
if (connection.to == id && connection.from != 0)
|
||||||
{
|
{
|
||||||
Object* obj = scene.m_object_map.find(connection.from)->second.object;
|
Object* obj = scene.m_object_map.find(connection.from)->second.object;
|
||||||
if (obj)
|
if (obj && obj->is_node && obj != this && connection.type == Scene::Connection::OBJECT_OBJECT)
|
||||||
{
|
{
|
||||||
if (idx == 0) return obj;
|
if (idx == 0) return obj;
|
||||||
--idx;
|
--idx;
|
||||||
|
|||||||
Reference in New Issue
Block a user