382 lines
9.2 KiB
C#
382 lines
9.2 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
[AddComponentMenu("Modifiers/Rope Deform")]
|
|
public class MegaRopeDeform : MegaModifier
|
|
{
|
|
public float floorOff;
|
|
|
|
public int NumMasses = 8;
|
|
|
|
public MegaSoft2D soft = new MegaSoft2D();
|
|
|
|
public float timeStep = 0.01f;
|
|
|
|
public float Mass = 10f;
|
|
|
|
public MegaAxis axis = MegaAxis.Z;
|
|
|
|
public AnimationCurve stiffnessCrv = new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(1f, 1f));
|
|
|
|
public float stiffspring = 1f;
|
|
|
|
public float stiffdamp = 0.1f;
|
|
|
|
public float spring = 1f;
|
|
|
|
public float damp = 1f;
|
|
|
|
public float off;
|
|
|
|
public bool init;
|
|
|
|
public float SpringCompress = 1f;
|
|
|
|
public bool BendSprings = true;
|
|
|
|
public bool Constraints = true;
|
|
|
|
public float DampingRatio = 0.5f;
|
|
|
|
public int pconl;
|
|
|
|
public int pconr;
|
|
|
|
public bool DisplayDebug = true;
|
|
|
|
public int drawsteps = 20;
|
|
|
|
public float boxsize = 0.01f;
|
|
|
|
public Transform left;
|
|
|
|
public Transform right;
|
|
|
|
public float weight;
|
|
|
|
public float weightPos = 0.5f;
|
|
|
|
public Vector2[] masspos;
|
|
|
|
private int ax;
|
|
|
|
private float minx;
|
|
|
|
private float width;
|
|
|
|
public override string ModName()
|
|
{
|
|
return "RopeDeform";
|
|
}
|
|
|
|
public override string GetHelpURL()
|
|
{
|
|
return "?page_id=1524";
|
|
}
|
|
|
|
public override Vector3 Map(int i, Vector3 p)
|
|
{
|
|
p = tm.MultiplyPoint3x4(p);
|
|
float t = (p[ax] - minx) / width;
|
|
Vector2 vector = Interp1a(t);
|
|
p.y += vector.y + off * 0.01f;
|
|
p[ax] = vector.x;
|
|
return invtm.MultiplyPoint3x4(p);
|
|
}
|
|
|
|
public override bool ModLateUpdate(MegaModContext mc)
|
|
{
|
|
ax = (int)axis;
|
|
minx = bbox.min[ax];
|
|
width = bbox.max[ax] - bbox.min[ax];
|
|
if (init || NumMasses != soft.masses.Count)
|
|
{
|
|
init = false;
|
|
Init();
|
|
}
|
|
AddWeight();
|
|
UpdateRope();
|
|
return Prepare(mc);
|
|
}
|
|
|
|
public override bool Prepare(MegaModContext mc)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public void Build(MegaModContext mc)
|
|
{
|
|
}
|
|
|
|
public void UpdateRope()
|
|
{
|
|
if (soft != null)
|
|
{
|
|
soft.Update();
|
|
for (int i = 0; i < soft.masses.Count; i++)
|
|
{
|
|
masspos[i + 1] = soft.masses[i].pos;
|
|
soft.masses[i].forcec = Vector2.zero;
|
|
}
|
|
masspos[0] = soft.masses[0].pos - (soft.masses[1].pos - soft.masses[0].pos);
|
|
masspos[masspos.Length - 1] = soft.masses[soft.masses.Count - 1].pos + (soft.masses[soft.masses.Count - 1].pos - soft.masses[soft.masses.Count - 2].pos);
|
|
if (left != null)
|
|
{
|
|
Vector3 vector = base.transform.worldToLocalMatrix.MultiplyPoint(left.position);
|
|
soft.constraints[pconl].pos.x = vector[ax];
|
|
soft.constraints[pconl].pos.y = vector.y;
|
|
}
|
|
if (right != null)
|
|
{
|
|
Vector3 vector2 = base.transform.worldToLocalMatrix.MultiplyPoint(right.position);
|
|
soft.constraints[pconr].pos.x = vector2[ax];
|
|
soft.constraints[pconr].pos.y = vector2.y;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Init()
|
|
{
|
|
if (soft.masses == null)
|
|
{
|
|
soft.masses = new List<Mass2D>();
|
|
}
|
|
soft.masses.Clear();
|
|
float num = Mass / (float)NumMasses;
|
|
int index = (int)axis;
|
|
Vector2 zero = Vector2.zero;
|
|
damp = DampingRatio * 0.45f * (2f * Mathf.Sqrt(num * spring));
|
|
for (int i = 0; i < NumMasses; i++)
|
|
{
|
|
float t = (float)i / (float)(NumMasses - 1);
|
|
zero.x = Mathf.Lerp(bbox.min[index], bbox.max[index], t);
|
|
Mass2D item = new Mass2D(num, zero);
|
|
soft.masses.Add(item);
|
|
}
|
|
masspos = new Vector2[soft.masses.Count + 2];
|
|
for (int j = 0; j < soft.masses.Count; j++)
|
|
{
|
|
masspos[j + 1] = soft.masses[j].pos;
|
|
}
|
|
if (soft.springs == null)
|
|
{
|
|
soft.springs = new List<Spring2D>();
|
|
}
|
|
soft.springs.Clear();
|
|
if (soft.constraints == null)
|
|
{
|
|
soft.constraints = new List<Constraint2D>();
|
|
}
|
|
soft.constraints.Clear();
|
|
for (int k = 0; k < soft.masses.Count - 1; k++)
|
|
{
|
|
Spring2D spring2D = new Spring2D(k, k + 1, spring, damp, soft);
|
|
spring2D.restLen *= SpringCompress;
|
|
soft.springs.Add(spring2D);
|
|
if (Constraints)
|
|
{
|
|
Constraint2D item2 = Constraint2D.CreateLenCon(k, k + 1, spring2D.restLen);
|
|
soft.constraints.Add(item2);
|
|
}
|
|
}
|
|
if (BendSprings)
|
|
{
|
|
int num2 = 2;
|
|
for (int l = 0; l < soft.masses.Count - num2; l++)
|
|
{
|
|
float time = (float)l / (float)soft.masses.Count;
|
|
Spring2D spring2D2 = new Spring2D(l, l + num2, stiffspring * stiffnessCrv.Evaluate(time), stiffdamp * stiffnessCrv.Evaluate(time), soft);
|
|
soft.springs.Add(spring2D2);
|
|
Constraint2D item3 = Constraint2D.CreateLenCon(l, l + num2, spring2D2.restLen);
|
|
soft.constraints.Add(item3);
|
|
}
|
|
}
|
|
zero.x = bbox.min[index];
|
|
zero.y = 0f;
|
|
Constraint2D item4 = Constraint2D.CreatePointCon(0, zero);
|
|
pconl = soft.constraints.Count;
|
|
soft.constraints.Add(item4);
|
|
zero.x = bbox.max[index];
|
|
item4 = Constraint2D.CreatePointCon(soft.masses.Count - 1, zero);
|
|
pconr = soft.constraints.Count;
|
|
soft.constraints.Add(item4);
|
|
soft.DoConstraints();
|
|
}
|
|
|
|
private void DrawSpline(int steps)
|
|
{
|
|
if (soft.masses == null || soft.masses.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
Vector3 vector = Interp1a(0f);
|
|
if (ax == 2)
|
|
{
|
|
float x = vector.x;
|
|
vector.x = vector.z;
|
|
vector.z = x;
|
|
}
|
|
for (int i = 1; i <= steps; i++)
|
|
{
|
|
if ((i & 1) == 1)
|
|
{
|
|
Gizmos.color = Color.white;
|
|
}
|
|
else
|
|
{
|
|
Gizmos.color = Color.black;
|
|
}
|
|
float t = (float)i / (float)steps;
|
|
Vector3 vector2 = Interp1a(t);
|
|
if (ax == 2)
|
|
{
|
|
float x2 = vector2.x;
|
|
vector2.x = vector2.z;
|
|
vector2.z = x2;
|
|
}
|
|
Gizmos.DrawLine(vector, vector2);
|
|
vector = vector2;
|
|
}
|
|
}
|
|
|
|
public void OnDrawGizmos()
|
|
{
|
|
Display();
|
|
}
|
|
|
|
private void Display()
|
|
{
|
|
Gizmos.matrix = base.transform.localToWorldMatrix;
|
|
if (DisplayDebug && soft != null && soft.masses != null)
|
|
{
|
|
DrawSpline(drawsteps);
|
|
Vector3 zero = Vector3.zero;
|
|
Gizmos.color = Color.yellow;
|
|
for (int i = 0; i < soft.masses.Count; i++)
|
|
{
|
|
if (ax == 0)
|
|
{
|
|
zero.x = soft.masses[i].pos.x;
|
|
zero.y = soft.masses[i].pos.y;
|
|
zero.z = 0f;
|
|
}
|
|
else
|
|
{
|
|
zero.z = soft.masses[i].pos.x;
|
|
zero.y = soft.masses[i].pos.y;
|
|
zero.x = 0f;
|
|
}
|
|
Gizmos.DrawCube(zero, Vector3.one * boxsize * 0.1f);
|
|
}
|
|
if (weightPos >= 0f && weightPos < 100f)
|
|
{
|
|
Gizmos.color = Color.blue;
|
|
Vector2 vector = Interp1a(weightPos * 0.01f);
|
|
if (ax == 0)
|
|
{
|
|
zero.x = vector.x;
|
|
zero.y = vector.y;
|
|
zero.z = 0f;
|
|
}
|
|
else
|
|
{
|
|
zero.z = vector.x;
|
|
zero.y = vector.y;
|
|
zero.x = 0f;
|
|
}
|
|
Gizmos.DrawCube(zero, Vector3.one * boxsize * 0.2f);
|
|
}
|
|
}
|
|
Gizmos.matrix = Matrix4x4.identity;
|
|
}
|
|
|
|
public Vector2 Interp1(float t)
|
|
{
|
|
int num = soft.masses.Count - 3;
|
|
int num2 = Mathf.Min(Mathf.FloorToInt(t * (float)num), num - 1);
|
|
float num3 = t * (float)num - (float)num2;
|
|
Vector2 pos = soft.masses[num2].pos;
|
|
Vector2 pos2 = soft.masses[num2 + 1].pos;
|
|
Vector2 pos3 = soft.masses[num2 + 2].pos;
|
|
Vector2 pos4 = soft.masses[num2 + 3].pos;
|
|
return 0.5f * ((-pos + 3f * pos2 - 3f * pos3 + pos4) * (num3 * num3 * num3) + (2f * pos - 5f * pos2 + 4f * pos3 - pos4) * (num3 * num3) + (-pos + pos3) * num3 + 2f * pos2);
|
|
}
|
|
|
|
public Vector2 Interp1a(float t)
|
|
{
|
|
int num = masspos.Length - 3;
|
|
int num2 = Mathf.Min(Mathf.FloorToInt(t * (float)num), num - 1);
|
|
float num3 = t * (float)num - (float)num2;
|
|
Vector2 vector = masspos[num2];
|
|
Vector2 vector2 = masspos[num2 + 1];
|
|
Vector2 vector3 = masspos[num2 + 2];
|
|
Vector2 vector4 = masspos[num2 + 3];
|
|
return 0.5f * ((-vector + 3f * vector2 - 3f * vector3 + vector4) * (num3 * num3 * num3) + (2f * vector - 5f * vector2 + 4f * vector3 - vector4) * (num3 * num3) + (-vector + vector3) * num3 + 2f * vector2);
|
|
}
|
|
|
|
private void AddWeight()
|
|
{
|
|
if (weightPos >= 0f && weightPos < 100f)
|
|
{
|
|
float num = soft.masses.Count - 1;
|
|
int num2 = (int)(num * weightPos * 0.01f);
|
|
int index = num2 + 1;
|
|
float num3 = num * weightPos * 0.01f - (float)num2;
|
|
Vector3 vector = Vector2.zero;
|
|
vector.y = weight * (1f - num3);
|
|
soft.masses[num2].forcec = vector;
|
|
vector.y = weight * num3;
|
|
soft.masses[index].forcec = vector;
|
|
}
|
|
}
|
|
|
|
public float GetPos(float alpha)
|
|
{
|
|
return Interp1a(alpha).y;
|
|
}
|
|
|
|
public Vector2 GetPos2(float alpha)
|
|
{
|
|
return Interp1a(alpha);
|
|
}
|
|
|
|
public Vector2 GetPos3(float v)
|
|
{
|
|
for (int i = 1; i < masspos.Length - 1; i++)
|
|
{
|
|
if (v > masspos[i].x && v < masspos[i + 1].x)
|
|
{
|
|
float num = (v - masspos[i].x) / (masspos[i + 1].x - masspos[i].x);
|
|
Vector2 vector = masspos[i - 1];
|
|
Vector2 vector2 = masspos[i];
|
|
Vector2 vector3 = masspos[i + 1];
|
|
Vector2 vector4 = masspos[i + 2];
|
|
return 0.5f * ((-vector + 3f * vector2 - 3f * vector3 + vector4) * (num * num * num) + (2f * vector - 5f * vector2 + 4f * vector3 - vector4) * (num * num) + (-vector + vector3) * num + 2f * vector2);
|
|
}
|
|
}
|
|
return Vector2.zero;
|
|
}
|
|
|
|
public Vector2 SetWeight(float v, float weight)
|
|
{
|
|
for (int i = 1; i < masspos.Length - 2; i++)
|
|
{
|
|
if (v > masspos[i].x && v < masspos[i + 1].x)
|
|
{
|
|
float num = (v - masspos[i].x) / (masspos[i + 1].x - masspos[i].x);
|
|
Vector2 vector = masspos[i - 1];
|
|
Vector2 vector2 = masspos[i];
|
|
Vector2 vector3 = masspos[i + 1];
|
|
Vector2 vector4 = masspos[i + 2];
|
|
Vector2 zero = Vector2.zero;
|
|
zero.y = weight * (1f - num);
|
|
soft.masses[i - 1].forcec = zero;
|
|
zero.y = weight * num;
|
|
soft.masses[i].forcec = zero;
|
|
return 0.5f * ((-vector + 3f * vector2 - 3f * vector3 + vector4) * (num * num * num) + (2f * vector - 5f * vector2 + 4f * vector3 - vector4) * (num * num) + (-vector + vector3) * num + 2f * vector2);
|
|
}
|
|
}
|
|
return Vector2.zero;
|
|
}
|
|
}
|