Skip to content

Upgrade workshop project to Unity 6. #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 40 additions & 42 deletions Assets/AnimationRiggingWorkshop/Constraints/ConstraintsUtils.cs
Original file line number Diff line number Diff line change
@@ -1,64 +1,62 @@
using System;
using System.Collections.Generic;
using UnityEngine;

namespace UnityEngine.Animations.Rigging
static class ConstraintsUtils
{
static class ConstraintsUtils
public static Transform[] ExtractChain(Transform root, Transform tip)
{
public static Transform[] ExtractChain(Transform root, Transform tip)
{
if (!tip.IsChildOf(root))
return new Transform[0]{};

var chain = new List<Transform>();
if (!tip.IsChildOf(root))
return new Transform[0]{};

Transform tmp = tip;
while (tmp != root)
{
chain.Add(tmp);
tmp = tmp.parent;
}
chain.Add(root);
chain.Reverse();
var chain = new List<Transform>();

return chain.ToArray();
Transform tmp = tip;
while (tmp != root)
{
chain.Add(tmp);
tmp = tmp.parent;
}
chain.Add(root);
chain.Reverse();

public static float[] ExtractLengths(Transform[] chain)
{
float[] lengths = new float[chain.Length];
lengths[0] = 0f;
return chain.ToArray();
}

// Evaluate lengths as distance between each transform in the chain.
for (int i = 1; i < chain.Length; ++i)
{
lengths[i] = chain[i].localPosition.magnitude;
}
public static float[] ExtractLengths(Transform[] chain)
{
float[] lengths = new float[chain.Length];
lengths[0] = 0f;

return lengths;
// Evaluate lengths as distance between each transform in the chain.
for (int i = 1; i < chain.Length; ++i)
{
lengths[i] = chain[i].localPosition.magnitude;
}

public static float[] ExtractSteps(Transform[] chain)
{
float[] lengths = ExtractLengths(chain);
return lengths;
}

float totalLength = 0f;
Array.ForEach(lengths, (length) => totalLength += length);
public static float[] ExtractSteps(Transform[] chain)
{
float[] lengths = ExtractLengths(chain);

float[] steps = new float[lengths.Length];
float totalLength = 0f;
Array.ForEach(lengths, (length) => totalLength += length);

// Evaluate weights and steps based on curve.
float cumulativeLength = 0.0f;
for (int i = 0; i < lengths.Length; ++i)
{
cumulativeLength += lengths[i];
float[] steps = new float[lengths.Length];

float t = cumulativeLength / totalLength;
// Evaluate weights and steps based on curve.
float cumulativeLength = 0.0f;
for (int i = 0; i < lengths.Length; ++i)
{
cumulativeLength += lengths[i];

steps[i] = t;
}
float t = cumulativeLength / totalLength;

return steps;
steps[i] = t;
}

return steps;
}
}
4 changes: 2 additions & 2 deletions Assets/AnimationRiggingWorkshop/Constraints/CopyLocation.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using UnityEngine;
using UnityEngine.Animations.Rigging;
using UnityEngine.Experimental.Animations;
using UnityEngine.Animations;
using Unity.Burst;
using Unity.Mathematics;

Expand Down Expand Up @@ -72,7 +72,7 @@ public override CopyLocationJob Create(Animator animator, ref CopyLocationData d
source = ReadOnlyTransformHandle.Bind(animator, data.sourceObject),

// Bind data.invert to job.invert so values can be resolved from the AnimationStream
invert = Vector3BoolProperty.Bind(animator, component, PropertyUtils.ConstructConstraintDataPropertyName(nameof(data.invert)))
invert = Vector3BoolProperty.Bind(animator, component, UnityEngine.Animations.Rigging.ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(data.invert)))
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using UnityEngine;
using UnityEngine.Animations.Rigging;
using UnityEngine.Experimental.Animations;
using UnityEngine.Animations;
using Unity.Burst;
using Unity.Mathematics;

Expand Down
4 changes: 2 additions & 2 deletions Assets/AnimationRiggingWorkshop/Constraints/HelloWorld.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using UnityEngine;
using UnityEngine.Animations.Rigging;
using UnityEngine.Experimental.Animations;
using UnityEngine.Animations;
using Unity.Burst;
using Unity.Mathematics;

Expand All @@ -9,7 +9,7 @@ public struct HelloWorldJob : IWeightedAnimationJob
{
public ReadWriteTransformHandle constrained;
public ReadOnlyTransformHandle source;

public FloatProperty jobWeight { get; set; }

public void ProcessRootMotion(AnimationStream stream) { }
Expand Down
173 changes: 85 additions & 88 deletions Assets/AnimationRiggingWorkshop/Constraints/TwistChain.cs
Original file line number Diff line number Diff line change
@@ -1,118 +1,115 @@
using System.Collections.Generic;
using Unity.Collections;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Animations.Rigging;

namespace UnityEngine.Animations.Rigging
[Unity.Burst.BurstCompile]
public struct TwistChainJob : IWeightedAnimationJob
{
using Experimental.Animations;
public ReadWriteTransformHandle rootTarget;
public ReadWriteTransformHandle tipTarget;

[Unity.Burst.BurstCompile]
public struct TwistChainJob : IWeightedAnimationJob
{
public ReadWriteTransformHandle rootTarget;
public ReadWriteTransformHandle tipTarget;

public NativeArray<ReadWriteTransformHandle> chain;
public NativeArray<ReadWriteTransformHandle> chain;

public NativeArray<float> steps;
public NativeArray<float> weights;
public NativeArray<float> steps;
public NativeArray<float> weights;

public FloatProperty jobWeight { get; set; }
public FloatProperty jobWeight { get; set; }

public void ProcessRootMotion(AnimationStream stream) { }

public void ProcessAnimation(AnimationStream stream)
{
// Retrieve root and tip rotation.
Quaternion rootRotation = rootTarget.GetRotation(stream);
Quaternion tipRotation = tipTarget.GetRotation(stream);
public void ProcessRootMotion(AnimationStream stream) { }

float mainWeight = jobWeight.Get(stream);
public void ProcessAnimation(AnimationStream stream)
{
// Retrieve root and tip rotation.
Quaternion rootRotation = rootTarget.GetRotation(stream);
Quaternion tipRotation = tipTarget.GetRotation(stream);

// Interpolate rotation on chain.
for (int i = 0; i < chain.Length; ++i)
{
chain[i].SetRotation(stream, Quaternion.Lerp(chain[i].GetRotation(stream), Quaternion.Lerp(rootRotation, tipRotation, weights[i]), mainWeight));
}
float mainWeight = jobWeight.Get(stream);

// Update position of tip handle for easier visualization.
rootTarget.SetPosition(stream, chain[0].GetPosition(stream));
tipTarget.SetPosition(stream, chain[chain.Length - 1].GetPosition(stream));
// Interpolate rotation on chain.
for (int i = 0; i < chain.Length; ++i)
{
chain[i].SetRotation(stream, Quaternion.Lerp(chain[i].GetRotation(stream), Quaternion.Lerp(rootRotation, tipRotation, weights[i]), mainWeight));
}

// Update position of tip handle for easier visualization.
rootTarget.SetPosition(stream, chain[0].GetPosition(stream));
tipTarget.SetPosition(stream, chain[chain.Length - 1].GetPosition(stream));
}
}

[System.Serializable]
public struct TwistChainData : IAnimationJobData
{
public Transform root;
public Transform tip;
[System.Serializable]
public struct TwistChainData : IAnimationJobData
{
public Transform root;
public Transform tip;

[SyncSceneToStream] public Transform rootTarget;
[SyncSceneToStream] public Transform tipTarget;
[SyncSceneToStream] public Transform rootTarget;
[SyncSceneToStream] public Transform tipTarget;

public AnimationCurve curve;
public AnimationCurve curve;

bool IAnimationJobData.IsValid() => !(root == null || tip == null || !tip.IsChildOf(root) || rootTarget == null || tipTarget == null || curve == null);
bool IAnimationJobData.IsValid() => !(root == null || tip == null || !tip.IsChildOf(root) || rootTarget == null || tipTarget == null || curve == null);

void IAnimationJobData.SetDefaultValues()
{
root = tip = rootTarget = tipTarget = null;
curve = AnimationCurve.Linear(0f, 0f, 1f, 1f);
}
void IAnimationJobData.SetDefaultValues()
{
root = tip = rootTarget = tipTarget = null;
curve = AnimationCurve.Linear(0f, 0f, 1f, 1f);
}
}


public class TwistChainJobBinder : AnimationJobBinder<TwistChainJob, TwistChainData>
public class TwistChainJobBinder : AnimationJobBinder<TwistChainJob, TwistChainData>
{
public override TwistChainJob Create(Animator animator, ref TwistChainData data, Component component)
{
public override TwistChainJob Create(Animator animator, ref TwistChainData data, Component component)
// Retrieve chain in-between root and tip transforms.
Transform[] chain = ConstraintsUtils.ExtractChain(data.root, data.tip);

// Extract steps from chain.
float[] steps = ConstraintsUtils.ExtractSteps(chain);

// Build Job.
var job = new TwistChainJob();
job.chain = new NativeArray<ReadWriteTransformHandle>(chain.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
job.steps = new NativeArray<float>(chain.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
job.weights = new NativeArray<float>(chain.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
job.rootTarget = ReadWriteTransformHandle.Bind(animator, data.rootTarget);
job.tipTarget = ReadWriteTransformHandle.Bind(animator, data.tipTarget);

// Set values in NativeArray.
for (int i = 0; i < chain.Length; ++i)
{
// Retrieve chain in-between root and tip transforms.
Transform[] chain = ConstraintsUtils.ExtractChain(data.root, data.tip);

// Extract steps from chain.
float[] steps = ConstraintsUtils.ExtractSteps(chain);

// Build Job.
var job = new TwistChainJob();
job.chain = new NativeArray<ReadWriteTransformHandle>(chain.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
job.steps = new NativeArray<float>(chain.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
job.weights = new NativeArray<float>(chain.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
job.rootTarget = ReadWriteTransformHandle.Bind(animator, data.rootTarget);
job.tipTarget = ReadWriteTransformHandle.Bind(animator, data.tipTarget);

// Set values in NativeArray.
for (int i = 0; i < chain.Length; ++i)
{
job.chain[i] = ReadWriteTransformHandle.Bind(animator, chain[i]);
job.steps[i] = steps[i];
job.weights[i] = Mathf.Clamp01(data.curve.Evaluate(steps[i]));
}

return job;
job.chain[i] = ReadWriteTransformHandle.Bind(animator, chain[i]);
job.steps[i] = steps[i];
job.weights[i] = Mathf.Clamp01(data.curve.Evaluate(steps[i]));
}

public override void Destroy(TwistChainJob job)
{
job.chain.Dispose();
job.weights.Dispose();
job.steps.Dispose();
}
return job;
}

public override void Update(TwistChainJob job, ref TwistChainData data)
{
// Update weights based on curve.
for (int i = 0; i < job.steps.Length; ++i)
{
job.weights[i] = Mathf.Clamp01(data.curve.Evaluate(job.steps[i]));
}
}
public override void Destroy(TwistChainJob job)
{
job.chain.Dispose();
job.weights.Dispose();
job.steps.Dispose();
}

[DisallowMultipleComponent, AddComponentMenu("SIGGRAPH 2019/Twist Chain Final")]
public class TwistChain : RigConstraint<
TwistChainJob,
TwistChainData,
TwistChainJobBinder
>
public override void Update(TwistChainJob job, ref TwistChainData data)
{
// Update weights based on curve.
for (int i = 0; i < job.steps.Length; ++i)
{
job.weights[i] = Mathf.Clamp01(data.curve.Evaluate(job.steps[i]));
}
}
}

[DisallowMultipleComponent, AddComponentMenu("SIGGRAPH 2019/Twist Chain Final")]
public class TwistChain : RigConstraint<
TwistChainJob,
TwistChainData,
TwistChainJobBinder
>
{
}
Loading