123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 |
- using UnityEngine;
- [ExecuteInEditMode]
- public class MegaAttach : MonoBehaviour
- {
- public MegaModifiers target;
- [HideInInspector]
- public Vector3 BaryCoord = Vector3.zero;
- [HideInInspector]
- public int[] BaryVerts = new int[3];
- [HideInInspector]
- public bool attached = false;
- [HideInInspector]
- public Vector3 BaryCoord1 = Vector3.zero;
- [HideInInspector]
- public int[] BaryVerts1 = new int[3];
- public Vector3 attachforward = Vector3.forward;
- public Vector3 AxisRot = Vector3.zero;
- public float radius = 0.1f;
- public Vector3 up = Vector3.up;
- public bool worldSpace = false;
- Vector3 pt = Vector3.zero;
- Vector3 norm = Vector3.zero;
- public bool skinned;
- #if UNITY_5_OR_NEWER
- public bool usebakedmesh = true;
- #endif
- [ContextMenu("Help")]
- public void Help()
- {
- Application.OpenURL("http://www.west-racing.com/mf/?page_id=2645");
- }
-
- public void DetachIt()
- {
- attached = false;
- }
- public void AttachIt()
- {
- if ( target )
- {
- attached = true;
- if ( !InitSkin() )
- {
- Mesh mesh = target.mesh;
- Vector3 objSpacePt = target.transform.InverseTransformPoint(pt);
- Vector3[] verts = target.sverts;
- int[] tris = mesh.triangles;
- int index = -1;
- MegaNearestPointTest.NearestPointOnMesh1(objSpacePt, verts, tris, ref index, ref BaryCoord);
- if ( index >= 0 )
- {
- BaryVerts[0] = tris[index];
- BaryVerts[1] = tris[index + 1];
- BaryVerts[2] = tris[index + 2];
- }
- MegaNearestPointTest.NearestPointOnMesh1(objSpacePt + attachforward, verts, tris, ref index, ref BaryCoord1);
- if ( index >= 0 )
- {
- BaryVerts1[0] = tris[index];
- BaryVerts1[1] = tris[index + 1];
- BaryVerts1[2] = tris[index + 2];
- }
- }
- }
- }
- public void AttachIt(Vector3 pos)
- {
- pt = pos;
- AttachIt();
- }
- void OnDrawGizmosSelected()
- {
- pt = transform.position;
- Gizmos.color = Color.white;
- Gizmos.DrawSphere(pt, radius);
- if ( target )
- {
- if ( attached )
- {
- SkinnedMeshRenderer skin = target.GetComponent<SkinnedMeshRenderer>();
- if ( skin )
- {
- Vector3 pos = transform.position;
- Vector3 worldPt = pos;
- Gizmos.color = Color.green;
- Gizmos.DrawSphere(worldPt, radius);
- }
- else
- {
- Vector3 pos = GetCoordMine(target.sverts[BaryVerts[0]], target.sverts[BaryVerts[1]], target.sverts[BaryVerts[2]], BaryCoord);
- Vector3 worldPt = target.transform.TransformPoint(pos);
- Gizmos.color = Color.green;
- Gizmos.DrawSphere(worldPt, radius);
- Vector3 nw = target.transform.TransformDirection(norm * 40.0f);
- Gizmos.DrawLine(worldPt, worldPt + nw);
- }
- }
- else
- {
- SkinnedMeshRenderer skin = target.GetComponent<SkinnedMeshRenderer>();
- if ( skin )
- {
- CalcSkinVerts();
- Mesh mesh = target.mesh;
- Vector3 objSpacePt = pt;
- Vector3[] verts = calcskinverts;
- int[] tris = mesh.triangles;
- int index = -1;
- Vector3 tribary = Vector3.zero;
- Vector3 meshPt = MegaNearestPointTest.NearestPointOnMesh1(objSpacePt, verts, tris, ref index, ref tribary);
- Vector3 worldPt = target.transform.TransformPoint(meshPt);
- if ( index >= 0 )
- {
- Vector3 cp2 = GetCoordMine(verts[tris[index]], verts[tris[index + 1]], verts[tris[index + 2]], tribary);
- worldPt = cp2;
- }
- Gizmos.color = Color.red;
- Gizmos.DrawSphere(worldPt, radius);
- Gizmos.color = Color.blue;
- meshPt = MegaNearestPointTest.NearestPointOnMesh1(objSpacePt + attachforward, verts, tris, ref index, ref tribary);
- Vector3 worldPt1 = meshPt;
- Gizmos.DrawSphere(worldPt1, radius);
- Gizmos.color = Color.yellow;
- Gizmos.DrawLine(worldPt, worldPt1);
- }
- else
- {
- Mesh mesh = target.mesh;
- Vector3 objSpacePt = target.transform.InverseTransformPoint(pt);
- Vector3[] verts = target.sverts;
- int[] tris = mesh.triangles;
- int index = -1;
- Vector3 tribary = Vector3.zero;
- Vector3 meshPt = MegaNearestPointTest.NearestPointOnMesh1(objSpacePt, verts, tris, ref index, ref tribary);
- Vector3 worldPt = target.transform.TransformPoint(meshPt);
- if ( index >= 0 )
- {
- Vector3 cp2 = GetCoordMine(verts[tris[index]], verts[tris[index + 1]], verts[tris[index + 2]], tribary);
- worldPt = target.transform.TransformPoint(cp2);
- }
- Gizmos.color = Color.red;
- Gizmos.DrawSphere(worldPt, radius);
- Gizmos.color = Color.blue;
- meshPt = MegaNearestPointTest.NearestPointOnMesh1(objSpacePt + attachforward, verts, tris, ref index, ref tribary);
- Vector3 worldPt1 = target.transform.TransformPoint(meshPt);
- Gizmos.DrawSphere(worldPt1, radius);
- Gizmos.color = Color.yellow;
- Gizmos.DrawLine(worldPt, worldPt1);
- }
- }
- }
- }
- void LateUpdate()
- {
- if ( attached )
- {
- if ( skinned )
- {
- GetSkinPos1();
- return;
- }
- if ( worldSpace )
- {
- Vector3 v0 = target.sverts[BaryVerts[0]];
- Vector3 v1 = target.sverts[BaryVerts[1]];
- Vector3 v2 = target.sverts[BaryVerts[2]];
- Vector3 pos = target.transform.localToWorldMatrix.MultiplyPoint(GetCoordMine(v0, v1, v2, BaryCoord));
- transform.position = pos;
- // Rotation
- Vector3 va = v1 - v0;
- Vector3 vb = v2 - v1;
- norm = Vector3.Cross(va, vb);
- v0 = target.sverts[BaryVerts1[0]];
- v1 = target.sverts[BaryVerts1[1]];
- v2 = target.sverts[BaryVerts1[2]];
- Vector3 fwd = target.transform.localToWorldMatrix.MultiplyPoint(GetCoordMine(v0, v1, v2, BaryCoord1)) - pos;
- Quaternion erot = Quaternion.Euler(AxisRot);
- Quaternion rot = Quaternion.LookRotation(fwd, norm) * erot;
- transform.rotation = rot;
- }
- else
- {
- Vector3 v0 = target.sverts[BaryVerts[0]];
- Vector3 v1 = target.sverts[BaryVerts[1]];
- Vector3 v2 = target.sverts[BaryVerts[2]];
- Vector3 pos = GetCoordMine(v0, v1, v2, BaryCoord);
- transform.localPosition = pos;
- // Rotation
- Vector3 va = v1 - v0;
- Vector3 vb = v2 - v1;
- norm = Vector3.Cross(va, vb);
- v0 = target.sverts[BaryVerts1[0]];
- v1 = target.sverts[BaryVerts1[1]];
- v2 = target.sverts[BaryVerts1[2]];
- Vector3 fwd = GetCoordMine(v0, v1, v2, BaryCoord1) - pos;
- Quaternion erot = Quaternion.Euler(AxisRot);
- Quaternion rot = Quaternion.LookRotation(fwd, norm) * erot;
- transform.localRotation = rot;
- }
- }
- }
- 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;
- }
- [System.Serializable]
- public class MegaSkinVert
- {
- public MegaSkinVert()
- {
- weights = new float[4];
- bones = new Transform[4];
- bindposes = new Matrix4x4[4];
- }
- public float[] weights;
- public Transform[] bones;
- public Matrix4x4[] bindposes;
- public int vert;
- }
- public MegaSkinVert[] skinverts;
- bool InitSkin()
- {
- if ( target )
- {
- SkinnedMeshRenderer skin = target.GetComponent<SkinnedMeshRenderer>();
- if ( skin )
- {
- Quaternion rot = transform.rotation;
- attachrot = Quaternion.identity;
- skinned = true;
- Mesh ms = skin.sharedMesh;
- Vector3 pt = transform.position;
- CalcSkinVerts();
- Vector3 objSpacePt = pt;
- Vector3[] verts = calcskinverts;
- int[] tris = ms.triangles;
- int index = -1;
- MegaNearestPointTest.NearestPointOnMesh1(objSpacePt, verts, tris, ref index, ref BaryCoord); //ref tribary);
- if ( index >= 0 )
- {
- BaryVerts[0] = tris[index];
- BaryVerts[1] = tris[index + 1];
- BaryVerts[2] = tris[index + 2];
- }
- MegaNearestPointTest.NearestPointOnMesh1(objSpacePt + attachforward, verts, tris, ref index, ref BaryCoord1);
- if ( index >= 0 )
- {
- BaryVerts1[0] = tris[index];
- BaryVerts1[1] = tris[index + 1];
- BaryVerts1[2] = tris[index + 2];
- }
- skinverts = new MegaSkinVert[6];
- for ( int i = 0; i < 3; i++ )
- {
- int vert = BaryVerts[i];
- BoneWeight bw = ms.boneWeights[vert];
- skinverts[i] = new MegaSkinVert();
- skinverts[i].vert = vert;
- skinverts[i].weights[0] = bw.weight0;
- skinverts[i].weights[1] = bw.weight1;
- skinverts[i].weights[2] = bw.weight2;
- skinverts[i].weights[3] = bw.weight3;
- skinverts[i].bones[0] = skin.bones[bw.boneIndex0];
- skinverts[i].bones[1] = skin.bones[bw.boneIndex1];
- skinverts[i].bones[2] = skin.bones[bw.boneIndex2];
- skinverts[i].bones[3] = skin.bones[bw.boneIndex3];
- skinverts[i].bindposes[0] = ms.bindposes[bw.boneIndex0];
- skinverts[i].bindposes[1] = ms.bindposes[bw.boneIndex1];
- skinverts[i].bindposes[2] = ms.bindposes[bw.boneIndex2];
- skinverts[i].bindposes[3] = ms.bindposes[bw.boneIndex3];
- }
- for ( int i = 3; i < 6; i++ )
- {
- int vert = BaryVerts1[i - 3];
- BoneWeight bw = ms.boneWeights[vert];
- skinverts[i] = new MegaSkinVert();
- skinverts[i].vert = vert;
- skinverts[i].weights[0] = bw.weight0;
- skinverts[i].weights[1] = bw.weight1;
- skinverts[i].weights[2] = bw.weight2;
- skinverts[i].weights[3] = bw.weight3;
- skinverts[i].bones[0] = skin.bones[bw.boneIndex0];
- skinverts[i].bones[1] = skin.bones[bw.boneIndex1];
- skinverts[i].bones[2] = skin.bones[bw.boneIndex2];
- skinverts[i].bones[3] = skin.bones[bw.boneIndex3];
- skinverts[i].bindposes[0] = ms.bindposes[bw.boneIndex0];
- skinverts[i].bindposes[1] = ms.bindposes[bw.boneIndex1];
- skinverts[i].bindposes[2] = ms.bindposes[bw.boneIndex2];
- skinverts[i].bindposes[3] = ms.bindposes[bw.boneIndex3];
- }
- GetSkinPos1();
- attachrot = Quaternion.Inverse(transform.rotation) * rot;
- return true;
- }
- else
- skinned = false;
- }
- return false;
- }
- public Quaternion attachrot = Quaternion.identity;
- Vector3 GetSkinPos(int i)
- {
- Vector3 pos = target.sverts[skinverts[i].vert];
- Vector3 bpos = skinverts[i].bindposes[0].MultiplyPoint(pos);
- Vector3 p = skinverts[i].bones[0].TransformPoint(bpos) * skinverts[i].weights[0];
- bpos = skinverts[i].bindposes[1].MultiplyPoint(pos);
- p += skinverts[i].bones[1].TransformPoint(bpos) * skinverts[i].weights[1];
- bpos = skinverts[i].bindposes[2].MultiplyPoint(pos);
- p += skinverts[i].bones[2].TransformPoint(bpos) * skinverts[i].weights[2];
- bpos = skinverts[i].bindposes[3].MultiplyPoint(pos);
- p += skinverts[i].bones[3].TransformPoint(bpos) * skinverts[i].weights[3];
- return p;
- }
- Vector3[] calcskinverts;
- void CalcSkinVerts()
- {
- if ( calcskinverts == null || calcskinverts.Length != target.sverts.Length )
- calcskinverts = new Vector3[target.sverts.Length];
- SkinnedMeshRenderer skin = target.GetComponent<SkinnedMeshRenderer>();
- Mesh mesh = target.mesh;
- Matrix4x4[] bindposes = mesh.bindposes;
- BoneWeight[] boneweights = mesh.boneWeights;
- for ( int i = 0; i < target.sverts.Length; i++ )
- {
- Vector3 p = Vector3.zero;
- Vector3 pos = target.sverts[i];
- Vector3 bpos = bindposes[boneweights[i].boneIndex0].MultiplyPoint(pos);
- p += skin.bones[boneweights[i].boneIndex0].TransformPoint(bpos) * boneweights[i].weight0;
- bpos = bindposes[boneweights[i].boneIndex1].MultiplyPoint(pos);
- p += skin.bones[boneweights[i].boneIndex1].TransformPoint(bpos) * boneweights[i].weight1;
- bpos = bindposes[boneweights[i].boneIndex2].MultiplyPoint(pos);
- p += skin.bones[boneweights[i].boneIndex2].TransformPoint(bpos) * boneweights[i].weight2;
- bpos = bindposes[boneweights[i].boneIndex3].MultiplyPoint(pos);
- p += skin.bones[boneweights[i].boneIndex3].TransformPoint(bpos) * boneweights[i].weight3;
- calcskinverts[i] = p;
- }
- }
- void GetSkinPos1()
- {
- Vector3 v0 = GetSkinPos(0);
- Vector3 v1 = GetSkinPos(1);
- Vector3 v2 = GetSkinPos(2);
- Vector3 pos = GetCoordMine(v0, v1, v2, BaryCoord);
- transform.position = pos;
- Vector3 va = v1 - v0;
- Vector3 vb = v2 - v1;
- norm = Vector3.Cross(va, vb);
- v0 = GetSkinPos(3);
- v1 = GetSkinPos(4);
- v2 = GetSkinPos(5);
- Vector3 fwd = GetCoordMine(v0, v1, v2, BaryCoord1) - pos;
- Quaternion erot = Quaternion.Euler(AxisRot);
- Quaternion rot = Quaternion.LookRotation(fwd, norm) * erot * attachrot;
- transform.rotation = rot;
- }
- }
|