209 lines
4.4 KiB
C#
209 lines
4.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
[AddComponentMenu("Modifiers/Paint")]
|
|
public class MegaPaint : MegaModifier
|
|
{
|
|
public float radius = 1f;
|
|
|
|
public float amount = 10f;
|
|
|
|
public float decay = 1f;
|
|
|
|
public bool usedecay;
|
|
|
|
public MegaFallOff fallOff;
|
|
|
|
public float gaussc = 0.25f;
|
|
|
|
public bool useAvgNorm;
|
|
|
|
public Vector3 normal = Vector3.up;
|
|
|
|
public MegaPaintMode mode;
|
|
|
|
private bool hadahit;
|
|
|
|
private Vector3 relativePoint = Vector3.zero;
|
|
|
|
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;
|
|
|
|
private Collider mycollider;
|
|
|
|
public override string ModName()
|
|
{
|
|
return "Paint";
|
|
}
|
|
|
|
public override string GetHelpURL()
|
|
{
|
|
return "?page_id=1292";
|
|
}
|
|
|
|
private static float LinearFalloff(float distance, float inRadius)
|
|
{
|
|
return Mathf.Clamp01(1f - distance / inRadius);
|
|
}
|
|
|
|
private static float PointFalloff(float dist, float inRadius)
|
|
{
|
|
return (0f - dist * dist) / (inRadius * inRadius) + 1f;
|
|
}
|
|
|
|
public static float GaussFalloff(float v, float c)
|
|
{
|
|
float f = (float)Math.E;
|
|
float num = 1f;
|
|
float num2 = 0.5f;
|
|
float num3 = (v - num2) * (v - num2);
|
|
float num4 = 2f * c * c;
|
|
return num * Mathf.Pow(f, 0f - num3 / num4);
|
|
}
|
|
|
|
private float Gaussian(float dist, float width)
|
|
{
|
|
return Mathf.Exp((0f - dist) * dist / width);
|
|
}
|
|
|
|
private void DeformMesh(Vector3 position, float power, float inRadius)
|
|
{
|
|
if (hadahit)
|
|
{
|
|
float num = inRadius * inRadius;
|
|
Vector3 zero = Vector3.zero;
|
|
for (int i = 0; i < verts.Length; i++)
|
|
{
|
|
Vector3 vector = verts[i];
|
|
float sqrMagnitude = (vector - position).sqrMagnitude;
|
|
if (!(sqrMagnitude > num))
|
|
{
|
|
affected.Add(i);
|
|
float num2 = Mathf.Sqrt(sqrMagnitude);
|
|
distances.Add(num2);
|
|
if (useAvgNorm)
|
|
{
|
|
float num3 = LinearFalloff(num2, inRadius);
|
|
zero += num3 * normals[i];
|
|
}
|
|
}
|
|
}
|
|
zero = ((!useAvgNorm) ? normal : zero.normalized);
|
|
for (int j = 0; j < affected.Count; j++)
|
|
{
|
|
float num4 = 0f;
|
|
switch (fallOff)
|
|
{
|
|
case MegaFallOff.Gauss:
|
|
num4 = GaussFalloff(distances[j], inRadius);
|
|
break;
|
|
case MegaFallOff.Point:
|
|
num4 = PointFalloff(distances[j], inRadius);
|
|
break;
|
|
default:
|
|
num4 = LinearFalloff(distances[j], inRadius);
|
|
break;
|
|
}
|
|
switch (mode)
|
|
{
|
|
case MegaPaintMode.Add:
|
|
offsets[affected[j]] += zero * num4 * power;
|
|
break;
|
|
case MegaPaintMode.Subtract:
|
|
offsets[affected[j]] -= zero * num4 * power;
|
|
break;
|
|
case MegaPaintMode.Set:
|
|
offsets[affected[j]] = zero * amount;
|
|
break;
|
|
case MegaPaintMode.Multiply:
|
|
offsets[affected[j]] = Vector3.Scale(offsets[affected[j]], zero * (1f + num4 * power));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!usedecay)
|
|
{
|
|
for (int k = 0; k < verts.Length; k++)
|
|
{
|
|
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;
|
|
}
|
|
return;
|
|
}
|
|
for (int l = 0; l < verts.Length; l++)
|
|
{
|
|
offsets[l].x *= decay;
|
|
offsets[l].y *= decay;
|
|
offsets[l].z *= decay;
|
|
sverts[l].x = verts[l].x + offsets[l].x;
|
|
sverts[l].y = verts[l].y + offsets[l].y;
|
|
sverts[l].z = verts[l].z + offsets[l].z;
|
|
}
|
|
}
|
|
|
|
public override void Modify(MegaModifiers mc)
|
|
{
|
|
DeformMesh(relativePoint, amount * Time.deltaTime, radius);
|
|
}
|
|
|
|
public override Vector3 Map(int i, Vector3 p)
|
|
{
|
|
return p;
|
|
}
|
|
|
|
public override bool ModLateUpdate(MegaModContext mc)
|
|
{
|
|
return Prepare(mc);
|
|
}
|
|
|
|
public override bool Prepare(MegaModContext mc)
|
|
{
|
|
if (mycollider == null)
|
|
{
|
|
mycollider = GetComponent<Collider>();
|
|
}
|
|
affected.Clear();
|
|
distances.Clear();
|
|
if (offsets == null || offsets.Length != mc.mod.verts.Length)
|
|
{
|
|
offsets = new Vector3[mc.mod.verts.Length];
|
|
}
|
|
normals = mc.mod.mesh.normals;
|
|
mat = Matrix4x4.identity;
|
|
SetAxis(mat);
|
|
hadahit = false;
|
|
if (Input.GetMouseButton(0))
|
|
{
|
|
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
|
RaycastHit hitInfo;
|
|
if (Physics.Raycast(ray, out hitInfo) && hitInfo.collider == mycollider)
|
|
{
|
|
hadahit = true;
|
|
relativePoint = hitInfo.collider.transform.InverseTransformPoint(hitInfo.point);
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
}
|