Created
October 10, 2018 16:25
-
-
Save JustinBeaudry/63f50019a0e97d2e4ab2c6f8bd25d947 to your computer and use it in GitHub Desktop.
Mesh Deformer C#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using Unity.Jobs; | |
using Unity.Burst; | |
using Unity.Collections; | |
using Unity.Mathematics; | |
using static Unity.Mathematics.math; | |
namespace Deform | |
{ | |
public class TwistDeformer : Deformer | |
{ | |
private const float MIN_RANGE = 0.001f; | |
public float StartAngle | |
{ | |
get { return startAngle; } | |
set { startAngle = value; } | |
} | |
public float EndAngle | |
{ | |
get { return endAngle; } | |
set { endAngle = value; } | |
} | |
public float Factor | |
{ | |
get { return factor; } | |
set { factor = value; } | |
} | |
public BoundsMode Mode | |
{ | |
get { return mode; } | |
set { mode = value; } | |
} | |
public bool Smooth | |
{ | |
get { return smooth; } | |
set { smooth = value; } | |
} | |
public float Top | |
{ | |
get { return top; } | |
set { top = Mathf.Clamp (value, Bottom, float.MaxValue); } | |
} | |
public float Bottom | |
{ | |
get { return bottom; } | |
set { bottom = Mathf.Clamp (value, float.MinValue, Top); } | |
} | |
public Transform Axis | |
{ | |
get { return (axis != null) ? axis : transform; } | |
set { axis = value; } | |
} | |
[SerializeField, HideInInspector] private float startAngle = 90f; | |
[SerializeField, HideInInspector] private float endAngle = -90f; | |
[SerializeField, HideInInspector] private float factor = 1f; | |
[SerializeField, HideInInspector] private BoundsMode mode; | |
[SerializeField, HideInInspector] private bool smooth = true; | |
[SerializeField, HideInInspector] private float top = 1f; | |
[SerializeField, HideInInspector] private float bottom = -1f; | |
[SerializeField, HideInInspector] private Transform axis; | |
public override JobHandle ProcessData (MeshData data, JobHandle dependency = default (JobHandle)) | |
{ | |
var targetTransform = data.target.GetTransform (); | |
var axisSpace = Axis.worldToLocalMatrix * targetTransform.localToWorldMatrix; | |
switch (mode) | |
{ | |
default: | |
return new UnlimitedTwistDeformJob | |
{ | |
startAngle = StartAngle * Factor, | |
endAngle = EndAngle * Factor, | |
top = Top, | |
bottom = Bottom, | |
axisSpace = axisSpace, | |
inverseAxisSpace = axisSpace.inverse, | |
vertices = data.dynamicNativeData.vertices | |
}.Schedule (data.length, batchCount, dependency); | |
case BoundsMode.Limited: | |
return new LimitedTwistDeformJob | |
{ | |
startAngle = StartAngle * Factor, | |
endAngle = EndAngle * Factor, | |
top = Top, | |
bottom = Bottom, | |
smooth = Smooth, | |
axisSpace = axisSpace, | |
inverseAxisSpace = axisSpace.inverse, | |
vertices = data.dynamicNativeData.vertices | |
}.Schedule (data.length, batchCount, dependency); | |
} | |
} | |
[BurstCompile (CompileSynchronously = COMPILE_SYNCHRONOUSLY)] | |
private struct UnlimitedTwistDeformJob : IJobParallelFor | |
{ | |
public float startAngle; | |
public float endAngle; | |
public float top; | |
public float bottom; | |
public float4x4 axisSpace; | |
public float4x4 inverseAxisSpace; | |
public NativeArray<float3> vertices; | |
public void Execute (int index) | |
{ | |
var range = abs (top - bottom); | |
if (range < MIN_RANGE) | |
top += MIN_RANGE; | |
var point = mul (axisSpace, float4 (vertices[index], 1f)); | |
var degrees = (point.z / range) * (endAngle - startAngle); | |
var rads = radians (startAngle + degrees) + (float)PI; | |
point.xy = float2 | |
( | |
-point.x * cos (rads) - point.y * sin (rads), | |
point.x * sin (rads) - point.y * cos (rads) | |
); | |
vertices[index] = mul (inverseAxisSpace, point).xyz; | |
} | |
} | |
[BurstCompile (CompileSynchronously = COMPILE_SYNCHRONOUSLY)] | |
private struct LimitedTwistDeformJob : IJobParallelFor | |
{ | |
public float startAngle; | |
public float endAngle; | |
public float top; | |
public float bottom; | |
public bool smooth; | |
public float4x4 axisSpace; | |
public float4x4 inverseAxisSpace; | |
public NativeArray<float3> vertices; | |
public void Execute (int index) | |
{ | |
var range = abs (top - bottom); | |
if (range < MIN_RANGE) | |
return; | |
var angleDifference = endAngle - startAngle; | |
var point = mul (axisSpace, float4 (vertices[index], 1f)); | |
var degrees = 0f; | |
if (smooth) | |
degrees = startAngle + smoothstep (bottom, top, clamp (point.z, bottom, top)) * angleDifference; | |
else | |
degrees = lerp (startAngle, endAngle, (clamp (point.z, bottom, top) - bottom) / range); | |
var rads = radians (degrees) + (float)PI; | |
point.xy = float2 | |
( | |
-point.x * cos (rads) - point.y * sin (rads), | |
point.x * sin (rads) - point.y * cos (rads) | |
); | |
vertices[index] = mul (inverseAxisSpace, point).xyz; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment