Browse Source

Add serialization to SkeletalAnimation (#1372)

Small changes to add SkeletalAnimation::SaveBinaryState and SkeletalAnimation::sRestoreFromBinaryState features for serializing and deserializing the SkeletalAnimation instances.

Also added a public facing API to change the mIsLooping flag which was previously always true
Gustavo Silvera 8 months ago
parent
commit
4257d30ef6
2 changed files with 69 additions and 0 deletions
  1. 55 0
      Jolt/Skeleton/SkeletalAnimation.cpp
  2. 14 0
      Jolt/Skeleton/SkeletalAnimation.h

+ 55 - 0
Jolt/Skeleton/SkeletalAnimation.cpp

@@ -7,6 +7,8 @@
 #include <Jolt/Skeleton/SkeletalAnimation.h>
 #include <Jolt/Skeleton/SkeletonPose.h>
 #include <Jolt/ObjectStream/TypeDeclarations.h>
+#include <Jolt/Core/StreamIn.h>
+#include <Jolt/Core/StreamOut.h>
 
 JPH_NAMESPACE_BEGIN
 
@@ -107,4 +109,57 @@ void SkeletalAnimation::Sample(float inTime, SkeletonPose &ioPose) const
 	}
 }
 
+void SkeletalAnimation::SaveBinaryState(StreamOut &inStream) const
+{
+	inStream.Write((uint32)mAnimatedJoints.size());
+	for (const AnimatedJoint &j : mAnimatedJoints)
+	{
+		// Write Joint name and number of keyframes
+		inStream.Write(j.mJointName);
+		inStream.Write((uint32)j.mKeyframes.size());
+		for (const Keyframe &k : j.mKeyframes)
+		{
+			inStream.Write(k.mTime);
+			inStream.Write(k.mRotation);
+			inStream.Write(k.mTranslation);
+		}
+	}
+
+	// Save additional parameters
+	inStream.Write(mIsLooping);
+}
+
+SkeletalAnimation::AnimationResult SkeletalAnimation::sRestoreFromBinaryState(StreamIn &inStream)
+{
+	AnimationResult result;
+
+	Ref<SkeletalAnimation> animation = new SkeletalAnimation;
+
+	// Restore animated joints
+	uint32 len = 0;
+	inStream.Read(len);
+	animation->mAnimatedJoints.resize(len);
+	for (AnimatedJoint &j : animation->mAnimatedJoints)
+	{
+		// Read joint name
+		inStream.Read(j.mJointName);
+
+		// Read keyframes
+		len = 0;
+		inStream.Read(len);
+		j.mKeyframes.resize(len);
+		for (Keyframe &k : j.mKeyframes)
+		{
+			inStream.Read(k.mTime);
+			inStream.Read(k.mRotation);
+			inStream.Read(k.mTranslation);
+		}
+	}
+
+	// Read additional parameters
+	inStream.Read(animation->mIsLooping);
+	result.Set(animation);
+	return result;
+}
+
 JPH_NAMESPACE_END

+ 14 - 0
Jolt/Skeleton/SkeletalAnimation.h

@@ -5,6 +5,8 @@
 #pragma once
 
 #include <Jolt/Core/Reference.h>
+#include <Jolt/Core/Result.h>
+#include <Jolt/Core/StreamUtils.h>
 #include <Jolt/ObjectStream/SerializableObject.h>
 
 JPH_NAMESPACE_BEGIN
@@ -62,6 +64,10 @@ public:
 	/// Scale the size of all joints by inScale
 	void								ScaleJoints(float inScale);
 
+	/// If the animation is looping or not. If an animation is looping, the animation will continue playing after completion
+	void 								SetIsLooping(bool inIsLooping)						{ mIsLooping = inIsLooping; }
+	bool								IsLooping() const									{ return mIsLooping; }
+
 	/// Get the (interpolated) joint transforms at time inTime
 	void								Sample(float inTime, SkeletonPose &ioPose) const;
 
@@ -69,6 +75,14 @@ public:
 	const AnimatedJointVector &			GetAnimatedJoints() const							{ return mAnimatedJoints; }
 	AnimatedJointVector &				GetAnimatedJoints()									{ return mAnimatedJoints; }
 
+	/// Saves the state of this animation in binary form to inStream.
+	void								SaveBinaryState(StreamOut &inStream) const;
+
+	using AnimationResult = Result<Ref<SkeletalAnimation>>;
+
+	/// Restore a saved ragdoll from inStream
+	static AnimationResult				sRestoreFromBinaryState(StreamIn &inStream);
+
 private:
 	AnimatedJointVector					mAnimatedJoints;									///< List of joints and keyframes
 	bool								mIsLooping = true;									///< If this animation loops back to start