123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479 |
- #if true
- using UnityEngine;
- using System.Collections.Generic;
- [System.Serializable]
- public class MegaColliderMesh
- {
- public int[] tris;
- public Vector3[] verts;
- public Vector3[] normals;
- public Mesh mesh;
- public GameObject obj;
- }
- public enum MegaDeformType
- {
- Old,
- RayCast,
- NearPoint,
- }
- #if true
- [AddComponentMenu("Modifiers/Collision Deform")]
- public class MegaCollisionDeform : MegaModifier
- {
- public GameObject obj;
- public float decay = 1.0f;
- public bool usedecay = false;
- public Vector3 normal = Vector3.up;
- List<int> affected = new List<int>();
- List<float> distances = new List<float>();
- Matrix4x4 mat = new Matrix4x4();
- Vector3[] offsets;
- Vector3[] normals;
- public override string ModName() { return "Deform"; }
- public override string GetHelpURL() { return "Deform.htm"; }
- public MegaColliderMesh colmesh;
- void DeformMeshMine()
- {
- if ( col == null )
- return;
- for ( int i = 0; i < verts.Length; i++ )
- {
- Vector3 p = verts[i] + offsets[i];
- Vector3 origin = transform.TransformPoint(p);
- if ( col.bounds.Contains(origin) )
- {
- RaycastHit hit;
- // Do ray from a distance away to the point, if hit then inside mesh
- Ray ray = new Ray(origin, normals[i]);
- if ( col.Raycast(ray, out hit, 10.0f) )
- {
- if ( hit.distance < 10.0f ) //&& hit.distance > 0.0f )
- {
- penetration[i] = hit.distance; //pen;
- offsets[i] = -(normals[i] * (hit.distance + 0.01f)); //pen); //(10.0f - hit.distance));
- }
- }
- }
- }
- if ( !usedecay )
- {
- for ( int i = 0; i < verts.Length; i++ )
- {
- sverts[i].x = verts[i].x + offsets[i].x;
- sverts[i].y = verts[i].y + offsets[i].y;
- sverts[i].z = verts[i].z + offsets[i].z;
- }
- }
- else
- {
- for ( int i = 0; i < verts.Length; i++ )
- {
- offsets[i].x *= decay;
- offsets[i].y *= decay;
- offsets[i].z *= decay;
- sverts[i].x = verts[i].x + offsets[i].x;
- sverts[i].y = verts[i].y + offsets[i].y;
- sverts[i].z = verts[i].z + offsets[i].z;
- }
- }
- }
- public MegaDeformType method = MegaDeformType.NearPoint;
- public float distance = 0.0f;
- public float bulgeExtendValue = 0.0f;
- public float bulgeValue = 0.0f;
- public bool bulge = false;
- public AnimationCurve bulgeCrv = new AnimationCurve(new Keyframe(0, 0), new Keyframe(1, 1));
- // To do falloff we need connected verts to each vert then just need to do recursive check until none effected
- void DeformMesh()
- {
- float dst = distance * 0.001f;
- int index = -1;
- Vector3 bary = Vector3.zero;
- bool collision = false;
- for ( int i = 0; i < verts.Length; i++ )
- {
- Vector3 p = verts[i]; // + offsets[i];
- Vector3 origin = transform.TransformPoint(p + (normals[i] * dst));
- if ( col.bounds.Contains(origin) )
- {
- // Point in collider space
- Vector3 lp = col.transform.worldToLocalMatrix.MultiplyPoint(origin);
- Vector3 np = MegaNearestPointTest.NearestPointOnMesh1(lp, colmesh.verts, colmesh.tris, ref index, ref bary);
- Vector3 dir = lp - np;
- Vector3 norm = FaceNormal(colmesh.verts, colmesh.tris, index);
- if ( Vector3.Dot(norm, dir) < 0.0f )
- {
- np = col.transform.localToWorldMatrix.MultiplyPoint(np);
- sverts[i] = transform.worldToLocalMatrix.MultiplyPoint(np);
- sverts[i] = sverts[i] - (normals[i] * dst);
- collision = true;
- }
- else
- sverts[i] = verts[i];
- //np = col.transform.localToWorldMatrix.MultiplyPoint(np);
- //sverts[i] = transform.worldToLocalMatrix.MultiplyPoint(np);
- }
- else
- {
- sverts[i] = verts[i];
- }
- }
- if ( collision && bulge )
- {
- for ( int i = 0; i < verts.Length; i++ )
- {
- Vector3 p = verts[i]; // + offsets[i];
- Vector3 origin = transform.TransformPoint(p + (normals[i] * dst));
- Vector3 lp = col.transform.worldToLocalMatrix.MultiplyPoint(origin);
- Vector3 np = MegaNearestPointTest.NearestPointOnMesh1(lp, colmesh.verts, colmesh.tris, ref index, ref bary);
- float bulgeDist = Vector3.Distance(lp, np);
- float relativedistance = bulgeDist / (bulgeExtendValue + 0.00001f);
-
- // get the bulge curve
- float bulgeAmount = bulgeCrv.Evaluate(relativedistance);
-
- float delta = bulgeAmount * bulgeValue;
- // set the point position for indirect collision deformation
- sverts[i].x = sverts[i].x + normals[i].x * delta; //bulgeExtendValue * (bulgeValue / 5.0f) * envelopeValue*bulgeAmount * maxdeformation;
- sverts[i].y = sverts[i].y + normals[i].y * delta; //bulgeExtendValue * (bulgeValue / 5.0f) * envelopeValue*bulgeAmount * maxdeformation;
- sverts[i].z = sverts[i].z + normals[i].z * delta; //bulgeExtendValue * (bulgeValue / 5.0f) * envelopeValue*bulgeAmount * maxdeformation;
- //sverts[i] = verts[i];
- }
- }
- }
- float[] vertdist;
- Vector3[] vertoffsets;
- Vector3[] nearest;
- Vector3[] vels;
- [ContextMenu("Reset Offsets")]
- public void ResetOffsets()
- {
- vertdist = null;
- }
- 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 dst = distance * 0.001f;
- int index = -1;
- Vector3 bary = Vector3.zero;
- //bool collision = false;
- float totalpen = 0.0f;
- int count = 0;
- for ( int i = 0; i < verts.Length; i++ )
- {
- Vector3 p = verts[i]; // + offsets[i];
- Vector3 origin = transform.TransformPoint(p + (normals[i] * dst));
- if ( col.bounds.Contains(origin) )
- {
- Vector3 lp = col.transform.worldToLocalMatrix.MultiplyPoint(origin);
- Vector3 np = MegaNearestPointTest.NearestPointOnMesh1(lp, colmesh.verts, colmesh.tris, ref index, ref bary);
- Vector3 dir = lp - np;
- float dist = Vector3.Distance(lp, np);
- Vector3 norm = FaceNormal(colmesh.verts, colmesh.tris, index);
- if ( Vector3.Dot(norm, dir) < 0.0f )
- {
- totalpen += dist;
- dist = -dist;
- //collision = true;
- }
- np = col.transform.localToWorldMatrix.MultiplyPoint(np);
- nearest[i] = transform.worldToLocalMatrix.MultiplyPoint(np);
- //if ( dist < vertdist[i] )
- {
- vertdist[i] = dist;
- //vertoffsets[i] = nearest[i] - verts[i];
- }
- }
- else
- {
- Vector3 lp = col.transform.worldToLocalMatrix.MultiplyPoint(origin);
- // Distance is calculated in here
- Vector3 np = MegaNearestPointTest.NearestPointOnMesh1(lp, colmesh.verts, colmesh.tris, ref index, ref bary);
- float dist = Vector3.Distance(lp, np);
- //if ( dist < vertdist[i] )
- {
- vertdist[i] = dist;
- }
- //vertdist[i] = Vector3.Distance(lp, np); // out of range
- np = col.transform.localToWorldMatrix.MultiplyPoint(np);
- nearest[i] = transform.worldToLocalMatrix.MultiplyPoint(np);
- count++;
- }
- }
- if ( totalpen == 0.0f )
- {
- for ( int i = 0; i < verts.Length; i++ )
- {
- //sverts[i] = verts[i];
- sverts[i] = verts[i] + vertoffsets[i];
- vertoffsets[i] *= retspd;
- }
- }
- else
- {
- for ( int i = 0; i < verts.Length; i++ )
- {
- if ( vertdist[i] < 0.0f )
- vertoffsets[i] = nearest[i] - verts[i];
- else
- {
- Vector3 newpos = normals[i] * ((totalpen / (float)count) * bulgeValue);
- vertoffsets[i] = Vector3.SmoothDamp(vertoffsets[i], newpos, ref vels[i], btime); //normals[i] * ((totalpen / (float)count) * bulgeValue);
- //vertoffsets[i] = Vector3.zero;
- }
- sverts[i] = verts[i] + vertoffsets[i];
- vertoffsets[i] *= retspd;
- }
- }
- }
- public float btime = 1.0f;
- public float retspd = 1.0f;
- // So per point see if inside colliding mesh
- Vector3 FaceNormal(Vector3[] verts, int[] tris, int f)
- {
- Vector3 v30 = verts[tris[f]];
- Vector3 v31 = verts[tris[f + 1]];
- Vector3 v32 = verts[tris[f + 2]];
- float vax = v31.x - v30.x;
- float vay = v31.y - v30.y;
- float vaz = v31.z - v30.z;
- float vbx = v32.x - v31.x;
- float vby = v32.y - v31.y;
- float vbz = v32.z - v31.z;
- v30.x = vay * vbz - vaz * vby;
- v30.y = vaz * vbx - vax * vbz;
- v30.z = vax * vby - vay * vbx;
- // Uncomment this if you dont want normals weighted by poly size
- //float l = v30.x * v30.x + v30.y * v30.y + v30.z * v30.z;
- //l = 1.0f / Mathf.Sqrt(l);
- //v30.x *= l;
- //v30.y *= l;
- //v30.z *= l;
- return v30;
- }
- public override void Modify(MegaModifiers mc)
- {
- switch ( method )
- {
- case MegaDeformType.Old:
- DeformMesh();
- break;
- case MegaDeformType.RayCast:
- DeformMeshMine();
- break;
- case MegaDeformType.NearPoint:
- DeformMeshNew();
- break;
- default:
- break;
- }
- }
- // How to do this, (a) ray from each p along its normal and check for hit mesh, only need to do if point in
- // collider.bounds, need in local space
- // maybe best to use a sphere for first test
- public override bool ModLateUpdate(MegaModContext mc)
- {
- return Prepare(mc);
- }
- Collider col;
- float[] penetration;
- // Need to support multiple objects
- public GameObject hitObject;
- public override bool Prepare(MegaModContext mc)
- {
- if ( colmesh == null )
- colmesh = new MegaColliderMesh();
- if ( colmesh.obj != hitObject && hitObject != null )
- {
- colmesh = new MegaColliderMesh();
- // This is colldier mesh not this mesh
- colmesh.mesh = MegaUtils.GetMesh(hitObject);
- colmesh.verts = colmesh.mesh.vertices;
- colmesh.tris = colmesh.mesh.triangles;
- colmesh.normals = colmesh.mesh.normals;
- colmesh.obj = hitObject;
- }
- if ( hitObject )
- {
- //localPos = transform.worldToLocalMatrix.MultiplyPoint(hitObject.transform.position);
- 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; // get current 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);
- }
- // Collision
- const float EPSILON = 0.000001f;
- int intersect_triangle(Vector3 orig, Vector3 dir, Vector3 vert0, Vector3 vert1, Vector3 vert2, out float t, out float u, out float v)
- {
- Vector3 edge1,edge2,tvec,pvec,qvec;
- float det,inv_det;
- // find vectors for two edges sharing vert0
- edge1 = vert1 - vert0;
- edge2 = vert2 - vert0;
-
- /* begin calculating determinant - also used to calculate U parameter */
- pvec = Vector3.Cross(dir, edge2);
- /* if determinant is near zero, ray lies in plane of triangle */
- det = Vector3.Dot(edge1, pvec);
- t = u = v = 0.0f; // or use ref
- #if TEST_CULL // define TEST_CULL if culling is desired
- if ( det < EPSILON )
- return 0;
- // calculate distance from vert0 to ray origin
- //SUB(tvec, orig, vert0);
- tvec = orig - vert0;
- /* calculate U parameter and test bounds */
- //*u = DOT(tvec, pvec);
- u = Vector3.Dot(tvec, pvec);
- if ( u < 0.0f || u > det )
- return 0;
- /* prepare to test V parameter */
- //CROSS(qvec, tvec, edge1);
- qvec = Vector3.Cross(tvec, edge1);
- /* calculate V parameter and test bounds */
- //*v = DOT(dir, qvec);
- v = Vector3.Dot(dir, qvec);
- if ( v < 0.0f || u + v > det )
- return 0;
- /* calculate t, scale parameters, ray intersects triangle */
- //*t = DOT(edge2, qvec);
- t = Vector3.Dot(edge2, qvec);
- inv_det = 1.0f / det;
- t *= inv_det;
- u *= inv_det;
- v *= inv_det;
- #else // the non-culling branch
- if ( det > -EPSILON && det < EPSILON )
- return 0;
- inv_det = 1.0f / det;
- /* calculate distance from vert0 to ray origin */
- tvec = orig - vert0;
- /* calculate U parameter and test bounds */
- u = Vector3.Dot(tvec, pvec) * inv_det;
- if ( u < 0.0f || u > 1.0f )
- return 0;
- /* prepare to test V parameter */
- qvec = Vector3.Cross(tvec, edge1);
- /* calculate V parameter and test bounds */
- v = Vector3.Dot(dir, qvec) * inv_det;
- if ( v < 0.0f || u + v > 1.0f )
- return 0;
- /* calculate t, ray intersects triangle */
- t = Vector3.Dot(edge2, qvec) * inv_det;
- #endif
- return 1;
- }
- }
- #endif
- #endif
|