Add AnimationRootMotionFlags to configure root motion component extraction
Add `RootMotionMode` to support extracting root motion from animated skeleton pose center of mass #1429 #2152
This commit is contained in:
@@ -911,10 +911,10 @@ bool ModelData::Pack2AnimationHeader(WriteStream* stream, int32 animIndex) const
|
||||
}
|
||||
|
||||
// Info
|
||||
stream->WriteInt32(100); // Header version (for fast version upgrades without serialization format change)
|
||||
stream->WriteInt32(103); // Header version (for fast version upgrades without serialization format change)
|
||||
stream->WriteDouble(anim.Duration);
|
||||
stream->WriteDouble(anim.FramesPerSecond);
|
||||
stream->WriteBool(anim.EnableRootMotion);
|
||||
stream->WriteByte((byte)anim.RootMotionFlags);
|
||||
stream->WriteString(anim.RootNodeName, 13);
|
||||
|
||||
// Animation channels
|
||||
@@ -928,6 +928,12 @@ bool ModelData::Pack2AnimationHeader(WriteStream* stream, int32 animIndex) const
|
||||
Serialization::Serialize(*stream, channel.Scale);
|
||||
}
|
||||
|
||||
// Animation events
|
||||
stream->WriteInt32(0);
|
||||
|
||||
// Nested animations
|
||||
stream->WriteInt32(0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ public:
|
||||
FORCE_INLINE SkeletonNode& RootNode()
|
||||
{
|
||||
ASSERT(Nodes.HasItems());
|
||||
return Nodes[0];
|
||||
return Nodes.Get()[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -100,52 +100,24 @@ public:
|
||||
FORCE_INLINE const SkeletonNode& RootNode() const
|
||||
{
|
||||
ASSERT(Nodes.HasItems());
|
||||
return Nodes[0];
|
||||
return Nodes.Get()[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Swaps the contents of object with the other object without copy operation. Performs fast internal data exchange.
|
||||
/// </summary>
|
||||
void Swap(SkeletonData& other)
|
||||
{
|
||||
Nodes.Swap(other.Nodes);
|
||||
Bones.Swap(other.Bones);
|
||||
}
|
||||
void Swap(SkeletonData& other);
|
||||
|
||||
int32 FindNode(const StringView& name) const
|
||||
{
|
||||
for (int32 i = 0; i < Nodes.Count(); i++)
|
||||
{
|
||||
if (Nodes[i].Name == name)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
Transform GetNodeTransform(int32 nodeIndex) const;
|
||||
void SetNodeTransform(int32 nodeIndex, const Transform& value);
|
||||
|
||||
int32 FindBone(int32 nodeIndex) const
|
||||
{
|
||||
for (int32 i = 0; i < Bones.Count(); i++)
|
||||
{
|
||||
if (Bones[i].NodeIndex == nodeIndex)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int32 FindNode(const StringView& name) const;
|
||||
int32 FindBone(int32 nodeIndex) const;
|
||||
|
||||
uint64 GetMemoryUsage() const
|
||||
{
|
||||
uint64 result = Nodes.Capacity() * sizeof(SkeletonNode) + Bones.Capacity() * sizeof(SkeletonBone);
|
||||
for (const auto& e : Nodes)
|
||||
result += (e.Name.Length() + 1) * sizeof(Char);
|
||||
return result;
|
||||
}
|
||||
uint64 GetMemoryUsage() const;
|
||||
|
||||
/// <summary>
|
||||
/// Releases data.
|
||||
/// </summary>
|
||||
void Dispose()
|
||||
{
|
||||
Nodes.Resize(0);
|
||||
Bones.Resize(0);
|
||||
}
|
||||
void Dispose();
|
||||
};
|
||||
|
||||
@@ -18,6 +18,69 @@
|
||||
#include "Engine/Threading/Task.h"
|
||||
#include "Engine/Threading/Threading.h"
|
||||
|
||||
void SkeletonData::Swap(SkeletonData& other)
|
||||
{
|
||||
Nodes.Swap(other.Nodes);
|
||||
Bones.Swap(other.Bones);
|
||||
}
|
||||
|
||||
Transform SkeletonData::GetNodeTransform(int32 nodeIndex) const
|
||||
{
|
||||
const int32 parentIndex = Nodes[nodeIndex].ParentIndex;
|
||||
if (parentIndex == -1)
|
||||
{
|
||||
return Nodes[nodeIndex].LocalTransform;
|
||||
}
|
||||
const Transform parentTransform = GetNodeTransform(parentIndex);
|
||||
return parentTransform.LocalToWorld(Nodes[nodeIndex].LocalTransform);
|
||||
}
|
||||
|
||||
void SkeletonData::SetNodeTransform(int32 nodeIndex, const Transform& value)
|
||||
{
|
||||
const int32 parentIndex = Nodes[nodeIndex].ParentIndex;
|
||||
if (parentIndex == -1)
|
||||
{
|
||||
Nodes[nodeIndex].LocalTransform = value;
|
||||
return;
|
||||
}
|
||||
const Transform parentTransform = GetNodeTransform(parentIndex);
|
||||
parentTransform.WorldToLocal(value, Nodes[nodeIndex].LocalTransform);
|
||||
}
|
||||
|
||||
int32 SkeletonData::FindNode(const StringView& name) const
|
||||
{
|
||||
for (int32 i = 0; i < Nodes.Count(); i++)
|
||||
{
|
||||
if (Nodes[i].Name == name)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32 SkeletonData::FindBone(int32 nodeIndex) const
|
||||
{
|
||||
for (int32 i = 0; i < Bones.Count(); i++)
|
||||
{
|
||||
if (Bones[i].NodeIndex == nodeIndex)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint64 SkeletonData::GetMemoryUsage() const
|
||||
{
|
||||
uint64 result = Nodes.Capacity() * sizeof(SkeletonNode) + Bones.Capacity() * sizeof(SkeletonBone);
|
||||
for (const auto& e : Nodes)
|
||||
result += (e.Name.Length() + 1) * sizeof(Char);
|
||||
return result;
|
||||
}
|
||||
|
||||
void SkeletonData::Dispose()
|
||||
{
|
||||
Nodes.Resize(0);
|
||||
Bones.Resize(0);
|
||||
}
|
||||
|
||||
void SkinnedMesh::Init(SkinnedModel* model, int32 lodIndex, int32 index, int32 materialSlotIndex, const BoundingBox& box, const BoundingSphere& sphere)
|
||||
{
|
||||
_model = model;
|
||||
|
||||
Reference in New Issue
Block a user