Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        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;
                }
            }
        }