public List <List <LinkedShape> > FormGroupsWithNeighbors(float propagate, Vector3 propagationDirection, int maxGroupSize, Vector3 originPoint) { List <LinkedShape> picked = new List <LinkedShape>(); List <LinkedShape> potentials = new List <LinkedShape>(); propagationDirection.Normalize(); //propagate *= 0.6f; this.cost = 0; potentials.Add(this); bool hasPicked = true; while (hasPicked) { hasPicked = false; LinkedShape recorder = null; float record = propagate; //Trouve le potentiel noeud le moins cher. Les noeuds avec un coup plus grand que 'propagate' ne seront jamais choisient foreach (LinkedShape item in potentials) { if (item.cost <= record) { record = item.cost; recorder = item; } } //Ajoue d'un nouveau noeud if (recorder != null) { potentials.Remove(recorder); recorder.AddToPickedList(picked, potentials, propagationDirection, originPoint); hasPicked = true; } } List <List <LinkedShape> > groupList = new List <List <LinkedShape> >(); foreach (LinkedShape item in picked) { groupList.Add(new List <LinkedShape>(1) { item }); } return(groupList); }
void OnCollisionEnter(Collision collision) { if (collision.impulse.magnitude < hardness * massPerBlock || linkedShapes.Count <= 1) { return; } //Ignore la collision avec sois meme if (collision.transform != null && collision.transform.GetComponent <FragmentTree>() != null) { if (collision.transform.GetComponent <FragmentTree>().original == original) { return; } } //Trouve la piece qui s'est fait frappé LinkedShape hitShape = null; foreach (LinkedShape shape in linkedShapes) { if (shape.shape.tr == collision.contacts[0].thisCollider.transform) { hitShape = shape; break; } } if (hitShape == null) { return; } float quantitéDeMouvement = 0; if (collision.rigidbody != null) { quantitéDeMouvement = collision.relativeVelocity.magnitude * collision.rigidbody.mass; } else { quantitéDeMouvement = collision.relativeVelocity.magnitude * myRb.mass; } //Pour fix le 'je tombe sur le sol et je me fait propulsé dans les airs' Vector3 otherVel = wasVel + collision.relativeVelocity; bool addVelocity = myRb.velocity.magnitude < otherVel.magnitude; Break(hitShape, collision.contacts[0].point, -collision.impulse, quantitéDeMouvement, addVelocity); }
void Break(LinkedShape shape, Vector3 point, Vector3 force, float quantitéDeMouvement, bool addVelocity) { if (linkedShapes.Count <= 1) { return; } if (intactVisual != null) { intactVisual.enabled = false; } //double time1 = EditorApplication.timeSinceStartup; Vector3 dir = force.normalized; float propagation = Mathf.Max(0, 0.025f * force.magnitude / (0.5f + elasticity) / massPerBlock); List <List <LinkedShape> > groups = shape.FormGroupsWithNeighbors(propagation, force.normalized, Mathf.Max(linkedShapes.Count / 2, 1), point); //Validate neighbors int totalInGroups = 0; for (int i = 0; i < groups.Count; i++) { totalInGroups += groups[i].Count; foreach (LinkedShape item in groups[i]) { item.ValidateNeighbors(groups[i]); } } int skipLastGroup = linkedShapes.Count > totalInGroups ? 0 : 1; //Remove groups from list for (int i = 0; i < groups.Count - skipLastGroup; i++) { List <LinkedShape> group = groups[i]; foreach (LinkedShape item in group) { linkedShapes.Remove(item); } } //Parcourt de l'arbre pour séparé les région qui ne sont plus en contact List <List <LinkedShape> > newGroups = FindSeperatedRegions(); for (int i = 0; i < newGroups.Count; i++) { totalInGroups += newGroups[i].Count; foreach (LinkedShape item in newGroups[i]) { item.ValidateNeighbors(newGroups[i]); } } //Remove newGroups from list for (int i = 0; i < newGroups.Count; i++) { foreach (LinkedShape item in newGroups[i]) { linkedShapes.Remove(item); } } //Ajoute les nouveaux groupes à la liste groups.AddRange(newGroups); //Kinematic settings bool resetKinematic = false; if (myRb.isKinematic) { resetKinematic = true; myRb.isKinematic = false; } Vector3 oldMassCenter = myRb.worldCenterOfMass; float velocityChange = quantitéDeMouvement / (totalInGroups * massPerBlock); //Nouveaux blocka for (int i = 0; i < groups.Count - skipLastGroup; i++) { List <LinkedShape> group = groups[i]; FragmentTree newTree = Instantiate(newChunkPrefab.gameObject).GetComponent <FragmentTree>(); newTree.linkedShapes = group; newTree.hardness = hardness; newTree.debugDraw = debugDraw; newTree.relinkTree = false; newTree.newChunkPrefab = newChunkPrefab; newTree.elasticity = elasticity; newTree.original = original; newTree.massPerBlock = massPerBlock; Rigidbody rb = newTree.GetComponent <Rigidbody>(); rb.velocity = myRb.velocity; rb.angularVelocity = myRb.angularVelocity; rb.mass = newTree.linkedShapes.Count * massPerBlock; rb.drag = myRb.drag; rb.angularDrag = myRb.angularDrag; rb.ResetCenterOfMass(); foreach (LinkedShape item in group) { item.shape.tr.SetParent(newTree.transform, true); } Vector3 dist = rb.worldCenterOfMass - point; float alignment = Vector3.Dot(dist.normalized, dir); //de 0 à 1 //float forceRatio = Mathf.Max(1.5f + 0.5f*alignment, 0.1f); // REMOVE float distanceFactor = Mathf.Pow(1 / (dist.magnitude + 1), elasticity); // de 0 à 1 Vector3 addVel = dir * velocityChange * alignment * distanceFactor * 2; //print("remains: " + alignment * distanceFactor + " vel: " + addVel); if (addVelocity) { rb.AddForceAtPosition(addVel, point, ForceMode.VelocityChange); } //rb.AddExplosionForce(force.magnitude*forceRatio, point, 10, 0); } //Reset mass settings myRb.ResetCenterOfMass(); myRb.mass = linkedShapes.Count * massPerBlock; if (resetKinematic) { Vector3 newCenterOfMass = myRb.worldCenterOfMass; if (oldMassCenter.y < newCenterOfMass.y) { myRb.isKinematic = false; } else { myRb.isKinematic = true; } } }