浏览代码

Simplified TwistChain by moving more code to ConstraintsUtils.

/main
Simon Bouvier-Zappa 6 年前
当前提交
7ca5e160
共有 3 个文件被更改,包括 70 次插入60 次删除
  1. 48
      Assets/Constraints/ConstraintsUtils.cs
  2. 75
      Assets/Constraints/TwistChain.cs
  3. 7
      Assets/Constraints/TwistChainStep1.cs

48
Assets/Constraints/ConstraintsUtils.cs


using System;
using System.Collections.Generic;
using UnityEditor;
using Unity.Collections;

static class ConstraintsUtils
{
public static List<Transform> ExtractChain(Transform root, Transform tip)
public static Transform[] ExtractChain(Transform root, Transform tip)
var chain = new List<Transform>();
return chain;
return new Transform[0]{};
var chain = new List<Transform>();
Transform tmp = tip;
while (tmp != root)

chain.Add(root);
chain.Reverse();
return chain;
return chain.ToArray();
}
public static float[] ExtractLengths(Transform[] chain)
{
float[] lengths = new float[chain.Length];
lengths[0] = 0f;
// Evaluate lengths as distance between each transform in the chain.
for (int i = 1; i < chain.Length; ++i)
{
lengths[i] = chain[i].localPosition.magnitude;
}
return lengths;
}
public static float[] ExtractSteps(Transform[] chain)
{
float[] lengths = ExtractLengths(chain);
float totalLength = 0f;
Array.ForEach(lengths, (length) => totalLength += length);
float[] steps = new float[lengths.Length];
// Evaluate weights and steps based on curve.
float cumulativeLength = 0.0f;
for (int i = 0; i < lengths.Length; ++i)
{
cumulativeLength += lengths[i];
float t = cumulativeLength / totalLength;
steps[i] = t;
}
return steps;
}
}
}

75
Assets/Constraints/TwistChain.cs


public void ProcessAnimation(AnimationStream stream)
{
float w = jobWeight.Get(stream);
if (w > 0f)
{
// Retrieve root and tip rotation.
Quaternion rootRotation = rootTarget.GetRotation(stream);
Quaternion tipRotation = tipTarget.GetRotation(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]), w));
}
float mainWeight = jobWeight.Get(stream);
// Update position of handles for easier
rootTarget.SetPosition(stream, chain[0].GetPosition(stream));
tipTarget.SetPosition(stream, chain[chain.Length - 1].GetPosition(stream));
}
else
// Interpolate rotation on chain.
for (int i = 0; i < chain.Length; ++i)
for (int i = 0; i < chain.Length; ++i)
AnimationRuntimeUtils.PassThrough(stream, chain[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));
}
}

public override TwistChainJob Create(Animator animator, ref TwistChainData data, Component component)
{
// Retrieve chain in-between root and tip transforms.
List<Transform> chain = new List<Transform>();
Transform tmp = data.tip;
while (tmp != data.root)
{
chain.Add(tmp);
tmp = tmp.parent;
}
chain.Add(data.root);
chain.Reverse();
Transform[] chain = ConstraintsUtils.ExtractChain(data.root, data.tip);
job.chain = new NativeArray<ReadWriteTransformHandle>(chain.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
job.steps = new NativeArray<float>(chain.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
job.weights = new NativeArray<float>(chain.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
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);
for (int i = 0; i < chain.Count; ++i)
for (int i = 0; i < chain.Length; ++i)
// Extract lengths from chain.
float totalLength = 0f;
// Extract steps from chain.
float[] steps = ConstraintsUtils.ExtractSteps(chain);
float[] lengths = new float[chain.Count];
lengths[0] = 0f;
for (int i = 1; i < chain.Count; ++i)
// Update weights based on curve.
for (int i = 0; i < steps.Length; ++i)
lengths[i] = chain[i].localPosition.magnitude;
totalLength += lengths[i];
}
// Evaluate weights and steps based on curve.
float cumulativeLength = 0.0f;
for (int i = 0; i < lengths.Length; ++i)
{
cumulativeLength += lengths[i];
float t = cumulativeLength / totalLength;
job.steps[i] = t;
job.weights[i] = Mathf.Clamp01(data.curve.Evaluate(t));
job.steps[i] = steps[i];
job.weights[i] = Mathf.Clamp01(data.curve.Evaluate(steps[i]));
}
return job;

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

7
Assets/Constraints/TwistChainStep1.cs


void IAnimationJobData.SetDefaultValues()
{
// Default values.
root = null;
tip = null;

public override TwistChainStep1Job Create(Animator animator, ref TwistChainStep1Data data, Component component)
{
// Retrieve chain in-between root and tip transforms.
List<Transform> chain = ConstraintsUtils.ExtractChain(data.root, data.tip);
Transform[] chain = ConstraintsUtils.ExtractChain(data.root, data.tip);
job.chain = new NativeArray<ReadWriteTransformHandle>(chain.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
job.chain = new NativeArray<ReadWriteTransformHandle>(chain.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
for (int i = 0; i < chain.Count; ++i)
for (int i = 0; i < chain.Length; ++i)
job.chain[i] = ReadWriteTransformHandle.Bind(animator, chain[i]);
return job;

正在加载...
取消
保存