Add a SimCharacterComponent class and handle 1F animation channels

This commit is contained in:
Ammar Askar 2023-08-19 02:37:50 -04:00
parent 9dd80da480
commit 4685e52efd
4 changed files with 69 additions and 0 deletions

View file

@ -0,0 +1,41 @@
using OpenTS2.Common;
using OpenTS2.Content;
using OpenTS2.Content.DBPF.Scenegraph;
using OpenTS2.Files.Formats.DBPF;
using UnityEngine;
namespace OpenTS2.Components
{
/// <summary>
/// This component represents a rendered out sims character with their head, hair and body meshes in place under one
/// scenegraph component.
/// </summary>
public class SimCharacterComponent : MonoBehaviour
{
public static SimCharacterComponent CreateNakedBaseSim()
{
const string nakedBodyResourceName = "amBodyNaked_cres";
var resource = ContentProvider.Get().GetAsset<ScenegraphResourceAsset>(
new ResourceKey(nakedBodyResourceName, GroupIDs.Scenegraph, TypeIDs.SCENEGRAPH_CRES));
var bodyObject = resource.CreateRootGameObject();
var scenegraph = bodyObject.GetComponentInChildren<ScenegraphComponent>();
var gameObject = new GameObject("sim_character", typeof(SimCharacterComponent));
bodyObject.transform.parent = gameObject.transform;
return gameObject.GetComponent<SimCharacterComponent>();
/*
resourceName = "amBodyNaked_cres";
resource = contentProvider.GetAsset<ScenegraphResourceAsset>(
new ResourceKey(resourceName, GroupIDs.Scenegraph, TypeIDs.SCENEGRAPH_CRES));
var bodyObject = resource.CreateRootGameObject();
resourceName = "amHairBald_cres";
resource = contentProvider.GetAsset<ScenegraphResourceAsset>(
new ResourceKey(resourceName, GroupIDs.Scenegraph, TypeIDs.SCENEGRAPH_CRES));
var hairObject = resource.CreateRootGameObject();
*/
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 051a53674f9e4ac6abc2a0e607175833
timeCreated: 1692399867

View file

@ -96,6 +96,16 @@ namespace OpenTS2.Content.DBPF.Scenegraph
new AnimationCurve(CreateKeyFramesForComponent(channel.DurationTicks, channel.Components[2]));
clip.SetCurve(relativePathToBone, typeof(Transform), "localPosition.z", curveZ);
}
else if (channel.Type == AnimResourceConstBlock.ChannelType.Float1)
{
// Only seen this where the length is 1 and it sets all values of the transform to zero. Assert here in
// case we see another case and its not related to position.
Debug.Assert(channel.Components[0].NumKeyFrames == 1);
var curve = new AnimationCurve(CreateKeyFramesForComponent(channel.DurationTicks, channel.Components[0]));
clip.SetCurve(relativePathToBone, typeof(Transform), "localPosition.x", curve);
clip.SetCurve(relativePathToBone, typeof(Transform), "localPosition.y", curve);
clip.SetCurve(relativePathToBone, typeof(Transform), "localPosition.z", curve);
}
else
{
throw new NotImplementedException($"Unsupported channel type: {channel.Type}");

View file

@ -84,4 +84,19 @@ public class ScenegraphAnimationCodecTest
Is.EqualTo(AnimResourceConstBlock.ChannelComponent.CurveType.BakedTangents));
Assert.That(bodyRotation.Components[2].KeyFrames.Length, Is.EqualTo(1));
}
[Test]
public void TestLoadsInverseKinematicChains()
{
var animationAsset = ContentProvider.Get()
.GetAsset<ScenegraphAnimationAsset>(new ResourceKey("a2o-pinball-play-lose_anim", GroupIDs.Scenegraph,
TypeIDs.SCENEGRAPH_ANIM));
var skeletonTarget = animationAsset.AnimResource.AnimTargets[0];
Assert.That(skeletonTarget.TagName, Is.EqualTo("auskel"));
Assert.That(skeletonTarget.IKChains.Length, Is.EqualTo(4));
var ikChain1 = skeletonTarget.IKChains[0];
Assert.That(ikChain1.IkTargets.Length, Is.EqualTo(1));
}
}