Skip to content

Instantly share code, notes, and snippets.

@JustinBeaudry
Created October 10, 2018 16:25
Show Gist options
  • Save JustinBeaudry/63f50019a0e97d2e4ab2c6f8bd25d947 to your computer and use it in GitHub Desktop.
Save JustinBeaudry/63f50019a0e97d2e4ab2c6f8bd25d947 to your computer and use it in GitHub Desktop.
Mesh Deformer C#
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