Files
Fishing2/Assets/KINEMATION/MagicBlend/Runtime/MagicBlendJobs.cs

192 lines
6.8 KiB
C#

// Designed by KINEMATION, 2025.
using KINEMATION.KAnimationCore.Runtime.Core;
using Unity.Collections;
using UnityEngine;
using UnityEngine.Animations;
namespace KINEMATION.MagicBlend.Runtime
{
// Processes base locomotion pose.
public struct PoseJob : IAnimationJob
{
[ReadOnly] public bool alwaysAnimate;
[ReadOnly] public bool readPose;
[ReadOnly] public TransformSceneHandle root;
public NativeArray<BlendStreamAtom> atoms;
public void ProcessAnimation(AnimationStream stream)
{
if (!alwaysAnimate && !readPose)
{
return;
}
KTransform rootTransform = new KTransform()
{
rotation = root.GetRotation(stream),
position = root.GetPosition(stream)
};
int num = atoms.Length;
for (int i = 0; i < num; i++)
{
var atom = atoms[i];
KTransform atomTransform = new KTransform()
{
position = atom.handle.GetPosition(stream),
rotation = atom.handle.GetRotation(stream)
};
atomTransform = rootTransform.GetRelativeTransform(atomTransform, false);
atom.activePose.basePose = atomTransform;
atom.activePose.basePose.position = atom.handle.GetLocalPosition(stream);
atoms[i] = atom;
}
}
public void ProcessRootMotion(AnimationStream stream)
{
}
}
// Processes active stream pose.
public struct OverlayJob : IAnimationJob
{
[ReadOnly] public bool alwaysAnimate;
[ReadOnly] public bool cachePose;
[ReadOnly] public TransformSceneHandle root;
public NativeArray<BlendStreamAtom> atoms;
public void ProcessAnimation(AnimationStream stream)
{
if (!alwaysAnimate && !cachePose)
{
return;
}
KTransform rootTransform = new KTransform()
{
rotation = root.GetRotation(stream),
position = root.GetPosition(stream)
};
int num = atoms.Length;
for (int i = 0; i < num; i++)
{
var atom = atoms[i];
KTransform atomTransform = new KTransform()
{
rotation = atom.handle.GetRotation(stream),
position = atom.handle.GetPosition(stream)
};
atomTransform = rootTransform.GetRelativeTransform(atomTransform, false);
atom.activePose.overlayPose = atomTransform;
atom.activePose.overlayPose.position = atom.handle.GetLocalPosition(stream);
atom.activePose.localOverlayRotation = atom.handle.GetLocalRotation(stream);
atoms[i] = atom;
}
}
public void ProcessRootMotion(AnimationStream stream)
{
}
}
// Processes final layering.
public struct LayeringJob : IAnimationJob
{
[ReadOnly] public float blendWeight;
[ReadOnly] public bool cachePose;
[ReadOnly] public TransformSceneHandle root;
public NativeArray<BlendStreamAtom> atoms;
public void ProcessAnimation(AnimationStream stream)
{
KTransform rootTransform = new KTransform()
{
rotation = root.GetRotation(stream),
position = root.GetPosition(stream)
};
int num = atoms.Length;
// Refresh the current pose.
for (int i = 0; i < num; i++)
{
var atom = atoms[i];
KTransform atomTransform = new KTransform()
{
rotation = atom.handle.GetRotation(stream),
position = atom.handle.GetPosition(stream),
scale = Vector3.one
};
atom.meshStreamPose = rootTransform.GetRelativeTransform(atomTransform, false);
atom.meshStreamPose.position = atom.handle.GetLocalPosition(stream);
atom.activePose.additiveWeight = atom.additiveWeight;
atom.activePose.baseWeight = atom.baseWeight;
atom.activePose.localWeight = atom.localWeight;
atoms[i] = atom;
}
// Apply mesh-space additive.
for (int i = 0; i < num; i++)
{
var atom = atoms[i];
AtomPose blendedPose = atom.GetBlendedAtomPose(blendWeight);
if (cachePose)
{
atom.cachedPose = blendedPose;
atoms[i] = atom;
}
KTransform meshBasePose = blendedPose.basePose;
KTransform meshOverlayPose = blendedPose.overlayPose;
Quaternion localOverlayRotation = blendedPose.localOverlayRotation;
float additiveWeight = blendedPose.additiveWeight;
float baseWeight = blendedPose.baseWeight;
float localWeight = blendedPose.localWeight;
KTransform additive = new KTransform()
{
rotation = atom.meshStreamPose.rotation * Quaternion.Inverse(meshBasePose.rotation),
position = atom.meshStreamPose.position - meshBasePose.position
};
Quaternion rotation = additive.rotation * meshOverlayPose.rotation;
// Blend additive.
rotation = Quaternion.Slerp(meshOverlayPose.rotation, rotation, additiveWeight);
// Blend locomotion pose.
rotation = Quaternion.Slerp(atom.meshStreamPose.rotation, rotation, baseWeight);
// Convert to world space.
rotation = rootTransform.rotation * rotation;
Vector3 position = meshOverlayPose.position + additive.position * additiveWeight;
position = Vector3.Lerp(atom.meshStreamPose.position, position, baseWeight);
atom.handle.SetRotation(stream, rotation);
rotation = Quaternion.Slerp(atom.handle.GetLocalRotation(stream), localOverlayRotation, localWeight);
atom.handle.SetLocalRotation(stream, rotation);
position = Vector3.Lerp(position, meshOverlayPose.position, localWeight);
atom.handle.SetLocalPosition(stream, position);
}
}
public void ProcessRootMotion(AnimationStream stream)
{
}
}
}