Files
UltimateFishing/Assets/Scripts/Assembly-CSharp/MegaCollisionDeform.cs
2026-02-21 16:45:37 +08:00

359 lines
8.8 KiB
C#

using System.Collections.Generic;
using UnityEngine;
[AddComponentMenu("Modifiers/Collision Deform")]
public class MegaCollisionDeform : MegaModifier
{
public GameObject obj;
public float decay = 1f;
public bool usedecay;
public Vector3 normal = Vector3.up;
private List<int> affected = new List<int>();
private List<float> distances = new List<float>();
private Matrix4x4 mat = default(Matrix4x4);
private Vector3[] offsets;
private Vector3[] normals;
public MegaColliderMesh colmesh;
public MegaDeformType method = MegaDeformType.NearPoint;
public float distance;
public float bulgeExtendValue;
public float bulgeValue;
public bool bulge;
public AnimationCurve bulgeCrv = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 1f));
private float[] vertdist;
private Vector3[] vertoffsets;
private Vector3[] nearest;
private Vector3[] vels;
public float btime = 1f;
public float retspd = 1f;
private Collider col;
private float[] penetration;
public GameObject hitObject;
private const float EPSILON = 1E-06f;
public override string ModName()
{
return "Deform";
}
public override string GetHelpURL()
{
return "Deform.htm";
}
private void DeformMeshMine()
{
if (col == null)
{
return;
}
for (int i = 0; i < verts.Length; i++)
{
Vector3 position = verts[i] + offsets[i];
Vector3 vector = base.transform.TransformPoint(position);
if (col.bounds.Contains(vector))
{
Ray ray = new Ray(vector, normals[i]);
RaycastHit hitInfo;
if (col.Raycast(ray, out hitInfo, 10f) && hitInfo.distance < 10f)
{
penetration[i] = hitInfo.distance;
offsets[i] = -(normals[i] * (hitInfo.distance + 0.01f));
}
}
}
if (!usedecay)
{
for (int j = 0; j < verts.Length; j++)
{
sverts[j].x = verts[j].x + offsets[j].x;
sverts[j].y = verts[j].y + offsets[j].y;
sverts[j].z = verts[j].z + offsets[j].z;
}
return;
}
for (int k = 0; k < verts.Length; k++)
{
offsets[k].x *= decay;
offsets[k].y *= decay;
offsets[k].z *= decay;
sverts[k].x = verts[k].x + offsets[k].x;
sverts[k].y = verts[k].y + offsets[k].y;
sverts[k].z = verts[k].z + offsets[k].z;
}
}
private void DeformMesh()
{
float num = distance * 0.001f;
int index = -1;
Vector3 bary = Vector3.zero;
bool flag = false;
for (int i = 0; i < verts.Length; i++)
{
Vector3 vector = verts[i];
Vector3 point = base.transform.TransformPoint(vector + normals[i] * num);
if (col.bounds.Contains(point))
{
Vector3 vector2 = col.transform.worldToLocalMatrix.MultiplyPoint(point);
Vector3 vector3 = MegaNearestPointTest.NearestPointOnMesh1(vector2, colmesh.verts, colmesh.tris, ref index, ref bary);
Vector3 rhs = vector2 - vector3;
Vector3 lhs = FaceNormal(colmesh.verts, colmesh.tris, index);
if (Vector3.Dot(lhs, rhs) < 0f)
{
vector3 = col.transform.localToWorldMatrix.MultiplyPoint(vector3);
sverts[i] = base.transform.worldToLocalMatrix.MultiplyPoint(vector3);
sverts[i] -= normals[i] * num;
flag = true;
}
else
{
sverts[i] = verts[i];
}
}
else
{
sverts[i] = verts[i];
}
}
if (flag && bulge)
{
for (int j = 0; j < verts.Length; j++)
{
Vector3 vector4 = verts[j];
Vector3 point2 = base.transform.TransformPoint(vector4 + normals[j] * num);
Vector3 vector5 = col.transform.worldToLocalMatrix.MultiplyPoint(point2);
Vector3 b = MegaNearestPointTest.NearestPointOnMesh1(vector5, colmesh.verts, colmesh.tris, ref index, ref bary);
float num2 = Vector3.Distance(vector5, b);
float time = num2 / (bulgeExtendValue + 1E-05f);
float num3 = bulgeCrv.Evaluate(time);
float num4 = num3 * bulgeValue;
sverts[j].x = sverts[j].x + normals[j].x * num4;
sverts[j].y = sverts[j].y + normals[j].y * num4;
sverts[j].z = sverts[j].z + normals[j].z * num4;
}
}
}
[ContextMenu("Reset Offsets")]
public void ResetOffsets()
{
vertdist = null;
}
private void DeformMeshNew()
{
if (vertdist == null || vertdist.Length != verts.Length)
{
vertdist = new float[verts.Length];
vertoffsets = new Vector3[verts.Length];
nearest = new Vector3[verts.Length];
vels = new Vector3[verts.Length];
}
float num = distance * 0.001f;
int index = -1;
Vector3 bary = Vector3.zero;
float num2 = 0f;
int num3 = 0;
for (int i = 0; i < verts.Length; i++)
{
Vector3 vector = verts[i];
Vector3 point = base.transform.TransformPoint(vector + normals[i] * num);
if (col.bounds.Contains(point))
{
Vector3 vector2 = col.transform.worldToLocalMatrix.MultiplyPoint(point);
Vector3 vector3 = MegaNearestPointTest.NearestPointOnMesh1(vector2, colmesh.verts, colmesh.tris, ref index, ref bary);
Vector3 rhs = vector2 - vector3;
float num4 = Vector3.Distance(vector2, vector3);
Vector3 lhs = FaceNormal(colmesh.verts, colmesh.tris, index);
if (Vector3.Dot(lhs, rhs) < 0f)
{
num2 += num4;
num4 = 0f - num4;
}
vector3 = col.transform.localToWorldMatrix.MultiplyPoint(vector3);
nearest[i] = base.transform.worldToLocalMatrix.MultiplyPoint(vector3);
vertdist[i] = num4;
}
else
{
Vector3 vector4 = col.transform.worldToLocalMatrix.MultiplyPoint(point);
Vector3 vector5 = MegaNearestPointTest.NearestPointOnMesh1(vector4, colmesh.verts, colmesh.tris, ref index, ref bary);
float num5 = Vector3.Distance(vector4, vector5);
vertdist[i] = num5;
vector5 = col.transform.localToWorldMatrix.MultiplyPoint(vector5);
nearest[i] = base.transform.worldToLocalMatrix.MultiplyPoint(vector5);
num3++;
}
}
if (num2 == 0f)
{
for (int j = 0; j < verts.Length; j++)
{
sverts[j] = verts[j] + vertoffsets[j];
vertoffsets[j] *= retspd;
}
return;
}
for (int k = 0; k < verts.Length; k++)
{
if (vertdist[k] < 0f)
{
vertoffsets[k] = nearest[k] - verts[k];
}
else
{
Vector3 target = normals[k] * (num2 / (float)num3 * bulgeValue);
vertoffsets[k] = Vector3.SmoothDamp(vertoffsets[k], target, ref vels[k], btime);
}
sverts[k] = verts[k] + vertoffsets[k];
vertoffsets[k] *= retspd;
}
}
private Vector3 FaceNormal(Vector3[] verts, int[] tris, int f)
{
Vector3 result = verts[tris[f]];
Vector3 vector = verts[tris[f + 1]];
Vector3 vector2 = verts[tris[f + 2]];
float num = vector.x - result.x;
float num2 = vector.y - result.y;
float num3 = vector.z - result.z;
float num4 = vector2.x - vector.x;
float num5 = vector2.y - vector.y;
float num6 = vector2.z - vector.z;
result.x = num2 * num6 - num3 * num5;
result.y = num3 * num4 - num * num6;
result.z = num * num5 - num2 * num4;
return result;
}
public override void Modify(MegaModifiers mc)
{
switch (method)
{
case MegaDeformType.Old:
DeformMesh();
break;
case MegaDeformType.RayCast:
DeformMeshMine();
break;
case MegaDeformType.NearPoint:
DeformMeshNew();
break;
}
}
public override bool ModLateUpdate(MegaModContext mc)
{
return Prepare(mc);
}
public override bool Prepare(MegaModContext mc)
{
if (colmesh == null)
{
colmesh = new MegaColliderMesh();
}
if (colmesh.obj != hitObject && hitObject != null)
{
colmesh = new MegaColliderMesh();
colmesh.mesh = MegaUtils.GetMesh(hitObject);
colmesh.verts = colmesh.mesh.vertices;
colmesh.tris = colmesh.mesh.triangles;
colmesh.normals = colmesh.mesh.normals;
colmesh.obj = hitObject;
}
if ((bool)hitObject)
{
col = hitObject.GetComponent<Collider>();
}
if (hitObject == null)
{
return false;
}
affected.Clear();
distances.Clear();
if (offsets == null || offsets.Length != mc.mod.verts.Length)
{
offsets = new Vector3[mc.mod.verts.Length];
}
if (normals == null || normals.Length != verts.Length)
{
normals = mc.mod.mesh.normals;
}
if (penetration == null || penetration.Length != mc.mod.verts.Length)
{
penetration = new float[mc.mod.verts.Length];
}
mat = Matrix4x4.identity;
SetAxis(mat);
return true;
}
public override void PrepareMT(MegaModifiers mc, int cores)
{
}
public override void DoWork(MegaModifiers mc, int index, int start, int end, int cores)
{
if (index == 0)
{
Modify(mc);
}
}
private int intersect_triangle(Vector3 orig, Vector3 dir, Vector3 vert0, Vector3 vert1, Vector3 vert2, out float t, out float u, out float v)
{
Vector3 vector = vert1 - vert0;
Vector3 vector2 = vert2 - vert0;
Vector3 rhs = Vector3.Cross(dir, vector2);
float num = Vector3.Dot(vector, rhs);
t = (u = (v = 0f));
if (num > -1E-06f && num < 1E-06f)
{
return 0;
}
float num2 = 1f / num;
Vector3 lhs = orig - vert0;
u = Vector3.Dot(lhs, rhs) * num2;
if (u < 0f || u > 1f)
{
return 0;
}
Vector3 rhs2 = Vector3.Cross(lhs, vector);
v = Vector3.Dot(dir, rhs2) * num2;
if (v < 0f || u + v > 1f)
{
return 0;
}
t = Vector3.Dot(vector2, rhs2) * num2;
return 1;
}
}