Fix rotation conversion to quaternions in animations

This commit is contained in:
Ammar Askar 2023-09-12 00:22:35 -04:00
parent 2475f1a8a5
commit 380b83ad7f
9 changed files with 61 additions and 18 deletions

View file

@ -265,7 +265,7 @@ namespace OpenTS2.Components
tip = tip,
target = Scenegraph.BoneCRC32ToTransform[target.TranslationCrc],
targetPositionWeight = 1.0f,
targetRotationWeight = 0.0f,
targetRotationWeight = 1.0f,
hintWeight = 1.0f,
};

View file

@ -2,6 +2,7 @@
using System.Collections.Generic;
using OpenTS2.Common.Utils;
using OpenTS2.Files.Formats.DBPF.Scenegraph.Block;
using OpenTS2.Files.Formats.DBPF.Types;
using UnityEngine;
using UnityEngine.Animations.Rigging;
@ -103,15 +104,41 @@ namespace OpenTS2.Content.DBPF.Scenegraph
{
if (channel.Type == AnimResourceConstBlock.ChannelType.EulerRotation)
{
var curveX =
new AnimationCurve(CreateKeyFramesForComponent(channel.DurationTicks, channel.Components[0]));
clip.SetCurve(relativePathToBone, typeof(Transform), "localEulerAngles.x", curveX);
var curveY =
new AnimationCurve(CreateKeyFramesForComponent(channel.DurationTicks, channel.Components[1]));
clip.SetCurve(relativePathToBone, typeof(Transform), "localEulerAngles.y", curveY);
var curveZ =
new AnimationCurve(CreateKeyFramesForComponent(channel.DurationTicks, channel.Components[2]));
clip.SetCurve(relativePathToBone, typeof(Transform), "localEulerAngles.z", curveZ);
var xFrames = CreateKeyFramesForComponent(channel.DurationTicks, channel.Components[0]);
var yFrames = CreateKeyFramesForComponent(channel.DurationTicks, channel.Components[1]);
var zFrames = CreateKeyFramesForComponent(channel.DurationTicks, channel.Components[2]);
var curveX = new AnimationCurve(xFrames);
var curveY = new AnimationCurve(yFrames);
var curveZ = new AnimationCurve(zFrames);
var quatX = new Keyframe[xFrames.Length];
var quatY = new Keyframe[xFrames.Length];
var quatZ = new Keyframe[xFrames.Length];
var quatW = new Keyframe[xFrames.Length];
// Convert from xyz euler rotations to quaternions.
for (var i = 0; i < curveX.keys.Length; i++)
{
var xFrame = curveX.keys[i];
var t = xFrame.time;
var (y, z) = (curveY.Evaluate(t), curveZ.Evaluate(t));
var quat = QuaternionSerializer.FromSims2EulerRotationDegrees(xFrame.value, y, z);
quatX[i] = new Keyframe(t, quat.x);
quatY[i] = new Keyframe(t, quat.y);
quatZ[i] = new Keyframe(t, quat.z);
quatW[i] = new Keyframe(t, quat.w);
}
curveX = new AnimationCurve(quatX);
curveY = new AnimationCurve(quatY);
curveZ = new AnimationCurve(quatZ);
var curveW = new AnimationCurve(quatW);
clip.SetCurve(relativePathToBone, typeof(Transform), "localRotation.x", curveX);
clip.SetCurve(relativePathToBone, typeof(Transform), "localRotation.y", curveY);
clip.SetCurve(relativePathToBone, typeof(Transform), "localRotation.z", curveZ);
clip.SetCurve(relativePathToBone, typeof(Transform), "localRotation.w", curveW);
}
else if (channel.Type == AnimResourceConstBlock.ChannelType.TransformXYZ)
{

View file

@ -61,14 +61,14 @@ namespace OpenTS2.Files.Formats.DBPF
}
var position = Vector3Serializer.Deserialize(reader);
var rotation = QuaterionSerialzier.Deserialize(reader);
var rotation = QuaternionSerializer.Deserialize(reader);
var numBones = reader.ReadUInt32();
for (var i = 0; i < numBones; i++)
{
var boneName = reader.ReadVariableLengthPascalString();
var bonePosition = Vector3Serializer.Deserialize(reader);
var boneRotation = QuaterionSerialzier.Deserialize(reader);
var boneRotation = QuaternionSerializer.Deserialize(reader);
}
return new LotObjectAsset.LotObject(resourceName, position, rotation);

View file

@ -142,7 +142,7 @@ namespace OpenTS2.Files.Formats.DBPF
var objectVersion = reader.ReadByte();
var positionOffset = Vector3Serializer.Deserialize(reader);
var modelOrientation = QuaterionSerialzier.Deserialize(reader);
var modelOrientation = QuaternionSerializer.Deserialize(reader);
// unknown
var unknown = Vector3Serializer.Deserialize(reader);

View file

@ -45,7 +45,7 @@ namespace OpenTS2.Files.Formats.DBPF.Scenegraph.Block
Quaternion jointOrientation = Quaternion.identity;
if (blockTypeInfo.Version > 3)
{
jointOrientation = QuaterionSerialzier.Deserialize(reader);
jointOrientation = QuaternionSerializer.Deserialize(reader);
}
return new BoneDataExtensionBlock(blockTypeInfo, headingOffsetAxis, mirrorAxis, stretchAxis, stretchFactor,

View file

@ -84,7 +84,7 @@ namespace OpenTS2.Files.Formats.DBPF.Scenegraph.Block
return new DataListValue<DataListValue[]>(name, items);
case 8:
// quanterion
return new DataListValue<Quaternion>(name, QuaterionSerialzier.Deserialize(reader));
return new DataListValue<Quaternion>(name, QuaternionSerializer.Deserialize(reader));
case 9:
// bytes
var len = reader.ReadUInt32();

View file

@ -278,7 +278,7 @@ namespace OpenTS2.Files.Formats.DBPF.Scenegraph.Block
var bindPoses = new GeometryDataContainerBlock.BindPose[reader.ReadUInt32()];
for (var i = 0; i < bindPoses.Length; i++)
{
var rotation = QuaterionSerialzier.Deserialize(reader);
var rotation = QuaternionSerializer.Deserialize(reader);
var position = Vector3Serializer.Deserialize(reader);
bindPoses[i] = new GeometryDataContainerBlock.BindPose(position, rotation);
}

View file

@ -43,7 +43,7 @@ namespace OpenTS2.Files.Formats.DBPF.Scenegraph.Block
var compositionTree = CompositionTreeNodeBlock.Deserialize(reader);
var transform = Vector3Serializer.Deserialize(reader);
var rotation = QuaterionSerialzier.Deserialize(reader);
var rotation = QuaternionSerializer.Deserialize(reader);
var boneId = reader.ReadUInt32();
return new TransformNodeBlock(blockTypeInfo, compositionTree, transform, rotation, boneId);
}

View file

@ -3,11 +3,27 @@ using UnityEngine;
namespace OpenTS2.Files.Formats.DBPF.Types
{
public class QuaterionSerialzier
public static class QuaternionSerializer
{
public static Quaternion Deserialize(IoBuffer reader)
{
return new Quaternion(reader.ReadFloat(), reader.ReadFloat(), reader.ReadFloat(), reader.ReadFloat());
}
public static Quaternion FromSims2EulerRotationDegrees(float x, float y, float z)
{
var sx = Mathf.Sin(x * 0.5f * Mathf.Deg2Rad);
var cx = Mathf.Cos(x * 0.5f * Mathf.Deg2Rad);
var sy = Mathf.Sin(y * 0.5f * Mathf.Deg2Rad);
var cy = Mathf.Cos(y * 0.5f * Mathf.Deg2Rad);
var sz = Mathf.Sin(z * 0.5f * Mathf.Deg2Rad);
var cz = Mathf.Cos(z * 0.5f * Mathf.Deg2Rad);
var quatX = (cz * (cy * sx)) - (sz * (cx * sy));
var quatY = (cz * (cx * sy)) + (sz * (cy * sx));
var quatZ = (sz * (cx * cy)) - (cz * (sx * sy));
var quatW = (cz * (cx * cy)) + (sz * (sx * sy));
return new Quaternion(quatX, quatY, quatZ, quatW);
}
}
}