// Prepare shards. Set bounds, set neibs static void SetShardsByRigids(RFCluster cluster, List <RayfireRigid> rigidList, ConnectivityType connectivity) { for (int i = 0; i < rigidList.Count; i++) { // Get mesh filter MeshFilter mf = rigidList[i].GetComponent <MeshFilter>(); // Child has no mesh if (mf == null) { continue; } // Create new shard RFShard shard = new RFShard(rigidList[i].transform, i); shard.cluster = cluster; shard.rigid = rigidList[i]; shard.uny = rigidList[i].activation.unyielding; shard.col = rigidList[i].physics.meshCollider; // Set faces data for connectivity if (connectivity == ConnectivityType.ByMesh) { RFTriangle.SetTriangles(shard, mf); } // Collect shard cluster.shards.Add(shard); } }
// Prepare shards. Set bounds, set neibs public static List <RFShard> GetShards(List <RayfireRigid> rigidList, ConnectivityType connectivity) { List <RFShard> shardList = new List <RFShard>(); for (int i = 0; i < rigidList.Count; i++) { // Get mesh filter MeshFilter mf = rigidList[i].GetComponent <MeshFilter>(); // Child has no mesh if (mf == null) { continue; } // Create new shard RFShard shard = new RFShard(rigidList[i].transform, i); shard.rigid = rigidList[i]; // Set faces data for connectivity if (connectivity == ConnectivityType.ByMesh) { shard.tris = RFTriangle.SetTriangles(shard.tm, mf); } // Collect shard shardList.Add(shard); } return(shardList); }
// Prepare shards. Set bounds, set neibs public static void SetShardsByTransforms(RFCluster cluster, List <Transform> tmList, ConnectivityType connectivity, bool setRigid = false) { cluster.shards = new List <RFShard>(); for (int i = 0; i < tmList.Count; i++) { // Get mesh filter MeshFilter mf = tmList[i].GetComponent <MeshFilter>(); // Child has no mesh if (mf == null) { continue; } // Has no mesh if (mf.sharedMesh == null) { continue; } // Create new shard RFShard shard = new RFShard(tmList[i], i); shard.cluster = cluster; // Set faces data for connectivity if (connectivity == ConnectivityType.ByMesh || connectivity == ConnectivityType.ByBoundingBoxAndMesh) { RFTriangle.SetTriangles(shard, mf); } // Collect shard cluster.shards.Add(shard); } // Set rigid component if (setRigid == true) { for (int i = 0; i < cluster.shards.Count; i++) { cluster.shards[i].rigid = cluster.shards[i].tm.GetComponent <RayfireRigid>(); } } }
// Get all face in mesh by triangles. IMPORTANT turn on triangle neib calculation in RFTriangle List <RFFace> GetFaces(List <RFTriangle> Triangles) { List <int> checkedTris = new List <int>(); List <RFFace> localFaces = new List <RFFace>(); // Check every triangle int faceId = 0; foreach (RFTriangle tri in Triangles) { // Skip triangle if it is already part of face if (checkedTris.Contains(tri.id) == false) { // Mark tri as checked checkedTris.Add(tri.id); // Create face RFFace face = new RFFace(faceId, tri.area, tri.normal); face.pos = tri.pos; faceId++; face.tris.Add(tri.id); // List of all triangles to check List <RFTriangle> trisToCheck = new List <RFTriangle>(); trisToCheck.Add(tri); // Check all neibs while (trisToCheck.Count > 0) { // Check neib tris foreach (int neibId in trisToCheck[0].neibs) { if (checkedTris.Contains(neibId) == false) { // Get neib tri RFTriangle neibTri = Triangles[neibId]; // Compare normals if (tri.normal == neibTri.normal) { face.area += neibTri.area; face.pos += neibTri.pos; face.tris.Add(neibId); checkedTris.Add(neibId); trisToCheck.Add(neibTri); } } } trisToCheck.RemoveAt(0); } // Set pos face.pos /= face.tris.Count; // Collect face localFaces.Add(face); } } return(localFaces); }
// Get all triangles by mesh public static List <RFTriangle> GetTriangles(Mesh mesh, Transform tm) { // List of all triangles List <RFTriangle> localTriangles = new List <RFTriangle>(); for (int i = 0; i < mesh.triangles.Length; i += 3) { // Vertex indexes int i1 = mesh.triangles[i]; int i2 = mesh.triangles[i + 1]; int i3 = mesh.triangles[i + 2]; // Get vertices position and area Vector3 v1 = tm.TransformPoint(mesh.vertices[i1]); Vector3 v2 = tm.TransformPoint(mesh.vertices[i2]); Vector3 v3 = tm.TransformPoint(mesh.vertices[i3]); Vector3 cross = Vector3.Cross(v1 - v2, v1 - v3); float area = cross.magnitude * 0.5f; // Set position Vector3 pos = (v1 + v2 + v3) / 3f; // Create triangle and collect it RFTriangle triangle = new RFTriangle(i / 3, area, mesh.normals[i1], pos, new List <int> { i1, i2, i3 }); localTriangles.Add(triangle); } //Set triangle neibs //for (int i = 0; i < localTriangles.Count; i++) //{ // RFTriangle tri1 = localTriangles[i]; // for (int t = 0; t < localTriangles.Count; t++) // { // if (i != t && tri1.neibs.Count < 3) // { // Check tri for neib state // RFTriangle tri2 = localTriangles[t]; // Tri1 and tri2 is not neibs already // if (tri2.neibs.Contains(tri1.id) == false) // { // Amount of neib verts // int vertsMatch = 0; // Check for same verts // foreach (int vertInd in tri1.verts) // if (tri2.verts.Contains(vertInd) == true) // vertsMatch++; // Tri is neib // if (vertsMatch > 1) // { // tri1.neibs.Add(tri2.id); // tri2.neibs.Add(tri1.id); // } // } // } // } //} return(localTriangles); }
// Set shard neibs public static void SetShardNeibs(List <RFShard> shards, ConnectivityType type, float minArea = 0, float minSize = 0, int perc = 0, int seed = 0) { // Set list for (int i = 0; i < shards.Count; i++) { shards[i].neibShards = new List <RFShard>(); shards[i].nArea = new List <float>(); shards[i].nIds = new List <int>(); shards[i].nAm = 0; } // Set neib and area info for (int i = 0; i < shards.Count; i++) { // Skip by size if (minSize > 0 && shards[i].sz < minSize) { continue; } for (int s = 0; s < shards.Count; s++) { // Skip itself if (s != i) { // Skip by size if (minSize > 0 && shards[s].sz < minSize) { continue; } // Set random state for same pair if (perc > 0) { Random.InitState(shards[i].id + shards[s].id + seed); if (Random.Range(0, 100) < perc) { continue; } } // Check if shard was not added as neib before if (shards[s].nIds.Contains(shards[i].id) == false) { // Bounding box intersection check if (shards[i].bnd.Intersects(shards[s].bnd) == true) { // Get areas float area = 0; if (type != ConnectivityType.ByBoundingBox) { area = shards[i].NeibArea(shards[s]); } if (type != ConnectivityType.ByMesh) { area = (shards[i].sz + shards[s].sz) / 4f; } // Skip low area neibs TODO filter after all connected, leave one biggest ?? if (minArea > 0 && area < minArea) { continue; } // Collect if (area > 0) { shards[i].neibShards.Add(shards[s]); shards[i].nArea.Add(area); shards[i].nIds.Add(shards[s].id); shards[s].neibShards.Add(shards[i]); shards[s].nArea.Add(area); shards[s].nIds.Add(shards[i].id); } } } } } // Set original neib amount to know if neibs was removed shards[i].nAm = shards[i].nIds.Count; } // Clear triangles data if (type == ConnectivityType.ByMesh) { for (int i = 0; i < shards.Count; i++) { RFTriangle.Clear(shards[i]); } } }