From c8b116b800e8231e25cc077b732080535928af9e Mon Sep 17 00:00:00 2001 From: Mikkel Bybjerg Date: Fri, 26 Apr 2019 18:23:26 +0200 Subject: Swarm system script --- nGJ2019/Assets/Scripts/SwarmSystem.cs | 402 ++++++++++++++++++++++++++++++++++ 1 file changed, 402 insertions(+) create mode 100644 nGJ2019/Assets/Scripts/SwarmSystem.cs diff --git a/nGJ2019/Assets/Scripts/SwarmSystem.cs b/nGJ2019/Assets/Scripts/SwarmSystem.cs new file mode 100644 index 0000000..d33595a --- /dev/null +++ b/nGJ2019/Assets/Scripts/SwarmSystem.cs @@ -0,0 +1,402 @@ +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