Browse Source

Fix some bugs in the animation code

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
c980beee4e

+ 32 - 39
src/anki/resource/AnimationResource.cpp

@@ -28,10 +28,10 @@ Error AnimationResource::load(const ResourceFilename& filename, Bool async)
 {
 	XmlElement el;
 	I64 tmp;
-	F64 ftmp;
+	Second ftmp;
 
-	m_startTime = MAX_F64;
-	F64 maxTime = MIN_F64;
+	m_startTime = MAX_SECOND;
+	Second maxTime = MIN_SECOND;
 
 	// Document
 	XmlDocument doc;
@@ -44,19 +44,6 @@ Error AnimationResource::load(const ResourceFilename& filename, Bool async)
 	U identRotCount = 0;
 	U identScaleCount = 0;
 
-	// <repeat>
-	XmlElement repel;
-	ANKI_CHECK(rootel.getChildElementOptional("repeat", repel));
-	if(repel)
-	{
-		ANKI_CHECK(repel.getNumber(tmp));
-		m_repeat = tmp;
-	}
-	else
-	{
-		m_repeat = false;
-	}
-
 	// <channels>
 	XmlElement channelsEl;
 	ANKI_CHECK(rootel.getChildElement("channels", channelsEl));
@@ -65,6 +52,7 @@ Error AnimationResource::load(const ResourceFilename& filename, Bool async)
 
 	U32 channelCount = 0;
 	ANKI_CHECK(chEl.getSiblingElementsCount(channelCount));
+	++channelCount;
 	if(channelCount == 0)
 	{
 		ANKI_RESOURCE_LOGE("Didn't found any channels");
@@ -94,6 +82,7 @@ Error AnimationResource::load(const ResourceFilename& filename, Bool async)
 
 			U32 count = 0;
 			ANKI_CHECK(keyEl.getSiblingElementsCount(count));
+			++count;
 			ch.m_positions.create(getAllocator(), count);
 
 			count = 0;
@@ -130,7 +119,8 @@ Error AnimationResource::load(const ResourceFilename& filename, Bool async)
 			ANKI_CHECK(keysEl.getChildElement("key", keyEl));
 
 			U32 count = 0;
-			ANKI_CHECK(keysEl.getSiblingElementsCount(count));
+			ANKI_CHECK(keyEl.getSiblingElementsCount(count));
+			++count;
 			ch.m_rotations.create(getAllocator(), count);
 
 			count = 0;
@@ -151,6 +141,8 @@ Error AnimationResource::load(const ResourceFilename& filename, Bool async)
 				ANKI_CHECK(el.getVec4(tmp2));
 				key.m_value = Quat(tmp2);
 
+				printf("%f\n", key.m_value.getLength());
+
 				// Check ident
 				if(key.m_value == Quat::getIdentity())
 				{
@@ -170,6 +162,7 @@ Error AnimationResource::load(const ResourceFilename& filename, Bool async)
 
 			U32 count = 0;
 			ANKI_CHECK(keyEl.getSiblingElementsCount(count));
+			++count;
 			ch.m_scales.create(getAllocator(), count);
 
 			count = 0;
@@ -226,10 +219,10 @@ Error AnimationResource::load(const ResourceFilename& filename, Bool async)
 	return Error::NONE;
 }
 
-void AnimationResource::interpolate(U channelIndex, F64 time, Vec3& pos, Quat& rot, F32& scale) const
+void AnimationResource::interpolate(U channelIndex, Second time, Vec3& pos, Quat& rot, F32& scale) const
 {
 	// Audjust time
-	if(m_repeat && time > m_startTime + m_duration)
+	if(time > m_startTime + m_duration)
 	{
 		time = mod(time - m_startTime, m_duration) + m_startTime;
 	}
@@ -242,33 +235,33 @@ void AnimationResource::interpolate(U channelIndex, F64 time, Vec3& pos, Quat& r
 	// Position
 	if(channel.m_positions.getSize() > 1)
 	{
-		auto next = channel.m_positions.begin();
-
-		do
+		for(U i = 0; i < channel.m_positions.getSize() - 1; ++i)
 		{
-		} while((next->m_time < time) && (++next != channel.m_positions.end()));
-
-		ANKI_ASSERT(next != channel.m_positions.end());
-		auto prev = next - 1;
-
-		F64 u = (time - prev->m_time) / (next->m_time - prev->m_time);
-		pos = linearInterpolate(prev->m_value, next->m_value, u);
+			const AnimationKeyframe<Vec3>& left = channel.m_positions[i];
+			const AnimationKeyframe<Vec3>& right = channel.m_positions[i + 1];
+			if(time >= left.m_time && time <= right.m_time)
+			{
+				const Second u = (time - left.m_time) / (right.m_time - left.m_time);
+				pos = linearInterpolate(left.m_value, right.m_value, u);
+				break;
+			}
+		}
 	}
 
 	// Rotation
 	if(channel.m_rotations.getSize() > 1)
 	{
-		auto next = channel.m_rotations.begin();
-
-		do
+		for(U i = 0; i < channel.m_rotations.getSize() - 1; ++i)
 		{
-		} while((next->m_time < time) && (++next != channel.m_rotations.end()));
-
-		ANKI_ASSERT(next != channel.m_rotations.end());
-		auto prev = next - 1;
-
-		F64 u = (time - prev->m_time) / (next->m_time - prev->m_time);
-		rot = prev->m_value.slerp(next->m_value, u);
+			const AnimationKeyframe<Quat>& left = channel.m_rotations[i];
+			const AnimationKeyframe<Quat>& right = channel.m_rotations[i + 1];
+			if(time >= left.m_time && time <= right.m_time)
+			{
+				const Second u = (time - left.m_time) / (right.m_time - left.m_time);
+				rot = left.m_value.slerp(right.m_value, u);
+				break;
+			}
+		}
 	}
 }
 

+ 7 - 14
src/anki/resource/AnimationResource.h

@@ -25,7 +25,7 @@ class AnimationKeyframe
 	friend class AnimationResource;
 
 public:
-	F64 getTime() const
+	Second getTime() const
 	{
 		return m_time;
 	}
@@ -36,7 +36,7 @@ public:
 	}
 
 private:
-	F64 m_time;
+	Second m_time;
 	T m_value;
 };
 
@@ -80,31 +80,24 @@ public:
 	}
 
 	/// Get the duration of the animation in seconds
-	F64 getDuration() const
+	Second getDuration() const
 	{
 		return m_duration;
 	}
 
 	/// Get the time (in seconds) the animation should start
-	F64 getStartingTime() const
+	Second getStartingTime() const
 	{
 		return m_startTime;
 	}
 
-	/// The animation repeats
-	Bool getRepeat() const
-	{
-		return m_repeat;
-	}
-
 	/// Get the interpolated data
-	void interpolate(U channelIndex, F64 time, Vec3& position, Quat& rotation, F32& scale) const;
+	void interpolate(U channelIndex, Second time, Vec3& position, Quat& rotation, F32& scale) const;
 
 private:
 	DynamicArray<AnimationChannel> m_channels;
-	F64 m_duration;
-	F64 m_startTime;
-	Bool8 m_repeat;
+	Second m_duration;
+	Second m_startTime;
 };
 /// @}
 

+ 3 - 3
src/anki/scene/components/SkinComponent.cpp

@@ -27,7 +27,7 @@ SkinComponent::~SkinComponent()
 	m_boneTrfs.destroy(getAllocator());
 }
 
-void SkinComponent::playAnimation(U track, AnimationResourcePtr anim, F64 startTime, Bool repeat)
+void SkinComponent::playAnimation(U track, AnimationResourcePtr anim, Second startTime, Bool repeat)
 {
 	m_tracks[track].m_anim = anim;
 	m_tracks[track].m_time = startTime;
@@ -37,7 +37,7 @@ void SkinComponent::playAnimation(U track, AnimationResourcePtr anim, F64 startT
 Error SkinComponent::update(Second prevTime, Second crntTime, Bool& updated)
 {
 	updated = false;
-	const F64 timeDiff = crntTime - prevTime;
+	const Second timeDiff = crntTime - prevTime;
 
 	for(Track& track : m_tracks)
 	{
@@ -48,7 +48,7 @@ Error SkinComponent::update(Second prevTime, Second crntTime, Bool& updated)
 
 		updated = true;
 
-		const F64 animTime = track.m_time;
+		const Second animTime = track.m_time;
 		track.m_time += timeDiff;
 
 		// Iterate the animation channels and interpolate

+ 1 - 1
src/anki/scene/components/SkinComponent.h

@@ -29,7 +29,7 @@ public:
 
 	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override;
 
-	void playAnimation(U track, AnimationResourcePtr anim, F64 startTime, Bool repeat);
+	void playAnimation(U track, AnimationResourcePtr anim, Second startTime, Bool repeat);
 
 	const DynamicArray<Mat4>& getBoneTransforms() const
 	{

+ 1 - 1
src/anki/scene/events/AnimationEvent.cpp

@@ -22,7 +22,7 @@ Error AnimationEvent::init(const AnimationResourcePtr& anim, SceneNode* movableS
 	m_anim = anim;
 
 	Event::init(m_anim->getStartingTime(), m_anim->getDuration());
-	m_reanimate = m_anim->getRepeat();
+	m_reanimate = true;
 	m_associatedNodes.emplaceBack(getAllocator(), movableSceneNode);
 
 	return Error::NONE;

+ 1 - 0
src/anki/util/StdTypes.h

@@ -76,6 +76,7 @@ using Bool32 = I32; ///< A 32bit boolean
 
 using Second = F64; ///< The base time unit is second.
 const Second MAX_SECOND = MAX_F64;
+const Second MIN_SECOND = MIN_F64;
 
 using Timestamp = U64; ///< Timestamp type.
 const Timestamp MAX_TIMESTAMP = MAX_U64;

+ 1 - 1
tools/scene/Exporter.cpp

@@ -340,7 +340,7 @@ void Exporter::exportSkeleton(const aiMesh& mesh) const
 		// <name>
 		file << "\t\t\t<name>" << bone.mName.C_Str() << "</name>\n";
 
-		// <bontTransform>
+		// <boneTransform>
 		aiMatrix4x4 akMat = toAnkiMatrix(bone.mOffsetMatrix);
 		file << "\t\t\t<boneTransform>";
 		for(unsigned j = 0; j < 4; j++)