using UnityEngine; using System.Collections.Generic; public class SwarmSystem : MonoBehaviour { public GameObject swarmPrefab; public int size = 1; public bool showGuides = false; private List units = new List(); private List boneStarts = new List(); private List boneEnds = new List(); private List boneTransforms = new List(); private List boneTips = new List(); private List boneCenterStarts = new List(); private List boneCenterDists = new List(); private SkinnedMeshRenderer meshRender; private List unitTris = new List(); private List> triGraph; private Mesh getCurrentMesh() { Mesh mesh = new Mesh(); meshRender.BakeMesh(mesh); return mesh; } private bool triangleIntersection(Vector3 p1, Vector3 p2, Vector3 p3, Ray ray, out Vector3 intersect) { Vector3 e1, e2; Vector3 p, q, t; float det, invDet, u, v; float Epsilon = 0.001f; intersect = Vector3.zero; e1 = p2 - p1; e2 = p3 - p1; //calculating determinant p = Vector3.Cross(ray.direction, e2); det = Vector3.Dot(e1, p); //if determinant is near zero, ray lies in plane of triangle otherwise not if (det > -Epsilon && det < Epsilon) return false; invDet = 1.0f / det; t = ray.origin - p1; u = Vector3.Dot(t, p) * invDet; //Check for ray hit if (u < 0 || u > 1) return false; //Prepare to test v parameter q = Vector3.Cross(t, e1); v = Vector3.Dot(ray.direction, q) * invDet; //Check for ray hit if (v < 0 || u + v > 1) return false; //ray does intersect if ((Vector3.Dot(e2, q) * invDet) > Epsilon) { intersect = ray.origin + ray.direction * (Vector3.Dot(e2, q)*invDet); return true; } // No hit at all return false; } private bool triangleIndexIntersection(int idx, Vector3[] vertices, int[] triangles, Ray ray, out Vector3 intersect) { return triangleIntersection(meshRender.transform.TransformPoint(vertices[triangles[idx*3]]), meshRender.transform.TransformPoint(vertices[triangles[idx*3+1]]), meshRender.transform.TransformPoint(vertices[triangles[idx*3+2]]), ray, out intersect); } private Vector3 meshIntersection(int unitIdx, Vector3[] vertices, int[] triangles, Vector3 boneCenter) { Transform unit = units[unitIdx]; Vector3 intersect; Ray ray = new Ray(boneCenter, unit.position-boneCenter); if(unitTris[unitIdx] != -1) { if(triangleIndexIntersection(unitTris[unitIdx], vertices, triangles, ray, out intersect)) { return intersect; } foreach(int tri in triGraph[unitTris[unitIdx]]) { if(triangleIndexIntersection(tri, vertices, triangles, ray, out intersect)) { unitTris[unitIdx] = tri; return intersect; } } } for(int i=0; i>(); Dictionary vertexAlias = new Dictionary(); List vertexByMag = new List(); for(int i=0; i vertices[x].magnitude.CompareTo(vertices[y].magnitude)); for(int i=0; i= 0 && vertices[i].magnitude-vertices[j].magnitude < epsilon) { if((vertices[i]-vertices[j]).magnitude < epsilon) minEq = j; j--; } vertexAlias.Add(i, minEq); } List> vertexTouch = new List>(); for(int i=0; i()); for(int i=0; i tris = new List(); for(int k=0; k<3; k++) { foreach(int tri in vertexTouch[vertexAlias[mesh.triangles[i+k]]]) { if(tri != i/3 && !tris.Contains(tri)) tris.Add(tri); } } triGraph.Add(tris); } } private void mapBones() { boneTips.Clear(); foreach(Transform b in meshRender.bones) { boneTransforms.Add(b.parent); if(b.GetChild(0).childCount == 0) { boneTransforms.Add(b); boneTips.Add(b); } } Debug.Log(boneTips.Count); } private void refreshMesh() { boneStarts.Clear(); boneEnds.Clear(); foreach(Transform b in meshRender.bones) { boneStarts.Add(b.parent.position); boneEnds.Add(b.position); if(boneTips.Contains(b)) { boneStarts.Add(b.position); boneEnds.Add(b.GetChild(0).position); } } } private void calculateBoneCenters() { boneCenterStarts.Clear(); boneCenterDists.Clear(); foreach(Transform unit in units) { float minDist = float.PositiveInfinity; Vector3 boneCenter = transform.position; int boneIdx = 0; for(int i=0; i accTriSizes = new List(); for(int i=0; i0) prev = accTriSizes[(i/3)-1]; float area = Vector3.Cross(mesh.vertices[mesh.triangles[i+1]]-mesh.vertices[mesh.triangles[i]], mesh.vertices[mesh.triangles[i+2]]-mesh.vertices[mesh.triangles[i]]).magnitude/2; accTriSizes.Add(prev+area); } float outOf = accTriSizes[accTriSizes.Count-1]; for(int i=0; i(); mapBones(); refreshMesh(); calculateTriGraph(); randomMeshSpawn(); calculateBoneCenters(); } void FixedUpdate() { refreshMesh(); Mesh mesh = getCurrentMesh(); Vector3[] vertices = mesh.vertices; int[] triangles = mesh.triangles; for(int u=0; u(); mapBones(); refreshMesh(); Gizmos.color = Color.cyan; for(int i=0; i