123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- using UnityEngine;
- using System.Collections.Generic;
- [ExecuteInEditMode]
- public class MegaWrapRef : MonoBehaviour
- {
- public float gap = 0.0f;
- public float shrink = 1.0f;
- public Vector3[] skinnedVerts;
- public Mesh mesh = null;
- public Vector3 offset = Vector3.zero;
- public bool targetIsSkin = false;
- public bool sourceIsSkin = false;
- public int nomapcount = 0;
- public Matrix4x4[] bindposes;
- public Transform[] bones;
- public float size = 0.01f;
- public int vertindex = 0;
- public Vector3[] verts;
- public MegaModifyObject target;
- public float maxdist = 0.25f;
- public int maxpoints = 4;
- public bool WrapEnabled = true;
- public MegaWrap source;
- public MegaNormalMethod NormalMethod = MegaNormalMethod.Unity;
- //struct MegaCloseFace
- //{
- //public int face;
- //public float dist;
- //}
- [ContextMenu("Help")]
- public void Help()
- {
- Application.OpenURL("http://www.west-racing.com/mf/?page_id=3709");
- }
- Vector4 Plane(Vector3 v1, Vector3 v2, Vector3 v3)
- {
- Vector3 normal = Vector4.zero;
- normal.x = (v2.y - v1.y) * (v3.z - v1.z) - (v2.z - v1.z) * (v3.y - v1.y);
- normal.y = (v2.z - v1.z) * (v3.x - v1.x) - (v2.x - v1.x) * (v3.z - v1.z);
- normal.z = (v2.x - v1.x) * (v3.y - v1.y) - (v2.y - v1.y) * (v3.x - v1.x);
- normal = normal.normalized;
- return new Vector4(normal.x, normal.y, normal.z, -Vector3.Dot(v2, normal));
- }
- float PlaneDist(Vector3 p, Vector4 plane)
- {
- Vector3 n = plane;
- return Vector3.Dot(n, p) + plane.w;
- }
- float GetDistance(Vector3 p, Vector3 p0, Vector3 p1, Vector3 p2)
- {
- return MegaNearestPointTest.DistPoint3Triangle3Dbl(p, p0, p1, p2);
- }
- float GetPlaneDistance(Vector3 p, Vector3 p0, Vector3 p1, Vector3 p2)
- {
- Vector4 pl = Plane(p0, p1, p2);
- return PlaneDist(p, pl);
- }
- public Vector3 MyBary(Vector3 p, Vector3 p0, Vector3 p1, Vector3 p2)
- {
- Vector3 bary = Vector3.zero;
- Vector3 normal = FaceNormal(p0, p1, p2);
- float areaABC = Vector3.Dot(normal, Vector3.Cross((p1 - p0), (p2 - p0)));
- float areaPBC = Vector3.Dot(normal, Vector3.Cross((p1 - p), (p2 - p)));
- float areaPCA = Vector3.Dot(normal, Vector3.Cross((p2 - p), (p0 - p)));
- bary.x = areaPBC / areaABC; // alpha
- bary.y = areaPCA / areaABC; // beta
- bary.z = 1.0f - bary.x - bary.y; // gamma
- return bary;
- }
- public Vector3 MyBary1(Vector3 p, Vector3 a, Vector3 b, Vector3 c)
- {
- Vector3 v0 = b - a, v1 = c - a, v2 = p - a;
- float d00 = Vector3.Dot(v0, v0);
- float d01 = Vector3.Dot(v0, v1);
- float d11 = Vector3.Dot(v1, v1);
- float d20 = Vector3.Dot(v2, v0);
- float d21 = Vector3.Dot(v2, v1);
- float denom = d00 * d11 - d01 * d01;
- float w = (d11 * d20 - d01 * d21) / denom;
- float v = (d00 * d21 - d01 * d20) / denom;
- float u = 1.0f - v - w;
- return new Vector3(u, v, w);
- }
- public Vector3 CalcBary(Vector3 p, Vector3 p0, Vector3 p1, Vector3 p2)
- {
- return MyBary(p, p0, p1, p2);
- }
- public float CalcArea(Vector3 p0, Vector3 p1, Vector3 p2)
- {
- Vector3 e1 = p1 - p0;
- Vector3 e2 = p2 - p0;
- Vector3 e3 = Vector3.Cross(e1, e2);
- return 0.5f * e3.magnitude;
- }
- public Vector3 FaceNormal(Vector3 p0, Vector3 p1, Vector3 p2)
- {
- Vector3 e1 = p1 - p0;
- Vector3 e2 = p2 - p0;
- return Vector3.Cross(e1, e2);
- }
- static void CopyBlendShapes(Mesh mesh1, Mesh clonemesh)
- {
- #if UNITY_5_3 || UNITY_5_4 || UNITY_5_5 || UNITY_5_6 || UNITY_2017 || UNITY_2018 || UNITY_2019 || UNITY_2020
- int bcount = mesh1.blendShapeCount; //GetBlendShapeFrameCount();
- Vector3[] deltaverts = new Vector3[mesh1.vertexCount];
- Vector3[] deltanorms = new Vector3[mesh1.vertexCount];
- Vector3[] deltatans = new Vector3[mesh1.vertexCount];
- for ( int j = 0; j < bcount; j++ )
- {
- int frames = mesh1.GetBlendShapeFrameCount(j);
- string bname = mesh1.GetBlendShapeName(j);
- for ( int f = 0; f < frames; f++ )
- {
- mesh1.GetBlendShapeFrameVertices(j, f, deltaverts, deltanorms, deltatans);
- float weight = mesh1.GetBlendShapeFrameWeight(j, f);
- clonemesh.AddBlendShapeFrame(bname, weight, deltaverts, deltanorms, deltatans);
- }
- }
- #endif
- }
- Mesh CloneMesh(Mesh m)
- {
- Mesh clonemesh = new Mesh();
- clonemesh.vertices = m.vertices;
- #if UNITY_5_0 || UNITY_5_1 || UNITY_5 || UNITY_2017 || UNITY_2018 || UNITY_2019 || UNITY_2020
- clonemesh.uv2 = m.uv2;
- clonemesh.uv3 = m.uv3;
- clonemesh.uv4 = m.uv4;
- #else
- clonemesh.uv1 = m.uv1;
- clonemesh.uv2 = m.uv2;
- #endif
- clonemesh.uv = m.uv;
- clonemesh.normals = m.normals;
- clonemesh.tangents = m.tangents;
- clonemesh.colors = m.colors;
- clonemesh.subMeshCount = m.subMeshCount;
- for ( int s = 0; s < m.subMeshCount; s++ )
- clonemesh.SetTriangles(m.GetTriangles(s), s);
- CopyBlendShapes(m, clonemesh);
- clonemesh.boneWeights = m.boneWeights;
- clonemesh.bindposes = m.bindposes;
- clonemesh.name = m.name; // + "_copy";
- clonemesh.RecalculateBounds();
- return clonemesh;
- }
- [ContextMenu("Reset Mesh")]
- public void ResetMesh()
- {
- if ( mesh && source )
- {
- mesh.vertices = source.startverts;
- mesh.RecalculateBounds();
- RecalcNormals();
- }
- target = null;
- }
- public void Attach(MegaModifyObject modobj)
- {
- targetIsSkin = false;
- sourceIsSkin = false;
- nomapcount = 0;
- MeshFilter mf = GetComponent<MeshFilter>();
- Mesh srcmesh = null;
- if ( mf != null )
- srcmesh = mf.mesh;
- else
- {
- SkinnedMeshRenderer smesh = (SkinnedMeshRenderer)GetComponent(typeof(SkinnedMeshRenderer));
- if ( smesh != null )
- {
- srcmesh = smesh.sharedMesh;
- sourceIsSkin = true;
- }
- }
- if ( mesh == null )
- mesh = CloneMesh(srcmesh); //mf.mesh);
- if ( mf )
- mf.mesh = mesh;
- else
- {
- SkinnedMeshRenderer smesh = (SkinnedMeshRenderer)GetComponent(typeof(SkinnedMeshRenderer));
- smesh.sharedMesh = mesh;
- }
- if ( sourceIsSkin == false )
- {
- SkinnedMeshRenderer tmesh = (SkinnedMeshRenderer)modobj.GetComponent(typeof(SkinnedMeshRenderer));
- if ( tmesh != null )
- {
- targetIsSkin = true;
- if ( !sourceIsSkin )
- {
- Mesh sm = tmesh.sharedMesh;
- bindposes = sm.bindposes;
- bones = tmesh.bones;
- skinnedVerts = sm.vertices; //new Vector3[sm.vertexCount];
- }
- }
- }
- verts = mesh.vertices;
- }
- void LateUpdate()
- {
- DoUpdate();
- }
- Vector3 GetSkinPos(MegaWrap src, int i)
- {
- Vector3 pos = target.sverts[i];
- Vector3 bpos = bindposes[src.boneweights[i].boneIndex0].MultiplyPoint(pos);
- Vector3 p = bones[src.boneweights[i].boneIndex0].TransformPoint(bpos) * src.boneweights[i].weight0;
- bpos = bindposes[src.boneweights[i].boneIndex1].MultiplyPoint(pos);
- p += bones[src.boneweights[i].boneIndex1].TransformPoint(bpos) * src.boneweights[i].weight1;
- bpos = bindposes[src.boneweights[i].boneIndex2].MultiplyPoint(pos);
- p += bones[src.boneweights[i].boneIndex2].TransformPoint(bpos) * src.boneweights[i].weight2;
- bpos = bindposes[src.boneweights[i].boneIndex3].MultiplyPoint(pos);
- p += bones[src.boneweights[i].boneIndex3].TransformPoint(bpos) * src.boneweights[i].weight3;
- return p;
- }
- public Vector3 GetCoordMine(Vector3 A, Vector3 B, Vector3 C, Vector3 bary)
- {
- Vector3 p = Vector3.zero;
- p.x = (bary.x * A.x) + (bary.y * B.x) + (bary.z * C.x);
- p.y = (bary.x * A.y) + (bary.y * B.y) + (bary.z * C.y);
- p.z = (bary.x * A.z) + (bary.y * B.z) + (bary.z * C.z);
- return p;
- }
- void DoUpdate()
- {
- if ( source == null || WrapEnabled == false || target == null || source.bindverts == null ) //|| bindposes == null )
- return;
- if ( targetIsSkin && source.neededVerts != null && source.neededVerts.Count > 0 )
- {
- if ( source.boneweights == null )
- {
- SkinnedMeshRenderer tmesh = (SkinnedMeshRenderer)target.GetComponent(typeof(SkinnedMeshRenderer));
- if ( tmesh != null )
- {
- if ( !sourceIsSkin )
- {
- Mesh sm = tmesh.sharedMesh;
- bindposes = sm.bindposes;
- source.boneweights = sm.boneWeights;
- }
- }
- }
- for ( int i = 0; i < source.neededVerts.Count; i++ )
- skinnedVerts[source.neededVerts[i]] = GetSkinPos(source, source.neededVerts[i]);
- }
- Vector3 p = Vector3.zero;
- if ( targetIsSkin && !sourceIsSkin )
- {
- for ( int i = 0; i < source.bindverts.Length; i++ )
- {
- if ( source.bindverts[i].verts.Count > 0 )
- {
- p = Vector3.zero;
- for ( int j = 0; j < source.bindverts[i].verts.Count; j++ )
- {
- MegaBindInf bi = source.bindverts[i].verts[j];
- Vector3 p0 = skinnedVerts[bi.i0];
- Vector3 p1 = skinnedVerts[bi.i1];
- Vector3 p2 = skinnedVerts[bi.i2];
- Vector3 cp = GetCoordMine(p0, p1, p2, bi.bary);
- Vector3 norm = FaceNormal(p0, p1, p2);
- cp += ((bi.dist * shrink) + gap) * norm.normalized;
- p += cp * (bi.weight / source.bindverts[i].weight);
- }
- verts[i] = transform.InverseTransformPoint(p) + offset;
- }
- }
- }
- else
- {
- for ( int i = 0; i < source.bindverts.Length; i++ )
- {
- if ( source.bindverts[i].verts.Count > 0 )
- {
- p = Vector3.zero;
- for ( int j = 0; j < source.bindverts[i].verts.Count; j++ )
- {
- MegaBindInf bi = source.bindverts[i].verts[j];
- Vector3 p0 = target.sverts[bi.i0];
- Vector3 p1 = target.sverts[bi.i1];
- Vector3 p2 = target.sverts[bi.i2];
- Vector3 cp = GetCoordMine(p0, p1, p2, bi.bary);
- Vector3 norm = FaceNormal(p0, p1, p2);
- cp += ((bi.dist * shrink) + gap) * norm.normalized;
- p += cp * (bi.weight / source.bindverts[i].weight);
- }
- }
- else
- p = source.freeverts[i]; //startverts[i];
- p = target.transform.TransformPoint(p);
- verts[i] = transform.InverseTransformPoint(p) + offset;
- }
- }
- mesh.vertices = verts;
- RecalcNormals();
- mesh.RecalculateBounds();
- }
- [HideInInspector]
- public MegaNormMap[] mapping;
- [HideInInspector]
- public int[] tris;
- [HideInInspector]
- public Vector3[] facenorms;
- [HideInInspector]
- public Vector3[] norms;
- int[] FindFacesUsing(Vector3 p, Vector3 n)
- {
- List<int> faces = new List<int>();
- Vector3 v = Vector3.zero;
- for ( int i = 0; i < tris.Length; i += 3 )
- {
- v = verts[tris[i]];
- if ( v.x == p.x && v.y == p.y && v.z == p.z )
- {
- if ( n.Equals(norms[tris[i]]) )
- faces.Add(i / 3);
- }
- else
- {
- v = verts[tris[i + 1]];
- if ( v.x == p.x && v.y == p.y && v.z == p.z )
- {
- if ( n.Equals(norms[tris[i + 1]]) )
- faces.Add(i / 3);
- }
- else
- {
- v = verts[tris[i + 2]];
- if ( v.x == p.x && v.y == p.y && v.z == p.z )
- {
- if ( n.Equals(norms[tris[i + 2]]) )
- faces.Add(i / 3);
- }
- }
- }
- }
- return faces.ToArray();
- }
- // Should call this from inspector when we change to mega
- public void BuildNormalMapping(Mesh mesh, bool force)
- {
- if ( mapping == null || mapping.Length == 0 || force )
- {
- // so for each normal we have a vertex, so find all faces that share that vertex
- tris = mesh.triangles;
- norms = mesh.normals;
- facenorms = new Vector3[tris.Length / 3];
- mapping = new MegaNormMap[verts.Length];
- for ( int i = 0; i < verts.Length; i++ )
- {
- mapping[i] = new MegaNormMap();
- mapping[i].faces = FindFacesUsing(verts[i], norms[i]);
- }
- }
- }
- public void RecalcNormals()
- {
- if ( NormalMethod == MegaNormalMethod.Unity ) //|| mapping == null )
- mesh.RecalculateNormals();
- else
- {
- if ( mapping == null )
- BuildNormalMapping(mesh, false);
- RecalcNormals(mesh, verts);
- }
- }
- public void RecalcNormals(Mesh ms, Vector3[] _verts)
- {
- int index = 0;
- Vector3 v30 = Vector3.zero;
- Vector3 v31 = Vector3.zero;
- Vector3 v32 = Vector3.zero;
- Vector3 va = Vector3.zero;
- Vector3 vb = Vector3.zero;
- for ( int f = 0; f < tris.Length; f += 3 )
- {
- v30 = _verts[tris[f]];
- v31 = _verts[tris[f + 1]];
- v32 = _verts[tris[f + 2]];
- va.x = v31.x - v30.x;
- va.y = v31.y - v30.y;
- va.z = v31.z - v30.z;
- vb.x = v32.x - v31.x;
- vb.y = v32.y - v31.y;
- vb.z = v32.z - v31.z;
- v30.x = va.y * vb.z - va.z * vb.y;
- v30.y = va.z * vb.x - va.x * vb.z;
- v30.z = va.x * vb.y - va.y * vb.x;
- // 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;
- facenorms[index++] = v30;
- }
- for ( int n = 0; n < norms.Length; n++ )
- {
- if ( mapping[n].faces.Length > 0 )
- {
- Vector3 norm = facenorms[mapping[n].faces[0]];
- for ( int i = 1; i < mapping[n].faces.Length; i++ )
- {
- v30 = facenorms[mapping[n].faces[i]];
- norm.x += v30.x;
- norm.y += v30.y;
- norm.z += v30.z;
- }
- float l = norm.x * norm.x + norm.y * norm.y + norm.z * norm.z;
- l = 1.0f / Mathf.Sqrt(l);
- norm.x *= l;
- norm.y *= l;
- norm.z *= l;
- norms[n] = norm;
- }
- else
- norms[n] = Vector3.up;
- }
- ms.normals = norms;
- }
- }
|