Example #1
0
    private void CalculateTensilAndCompressive(Matrix <double> stress)
    {
        Evd <double>    evd         = stress.Evd();
        Matrix <double> tensileComp = Matrix <double> .Build.Dense(3, 3);

        Matrix <double> compressiveComp = Matrix <double> .Build.Dense(3, 3);

        for (int i = 0; i < 3; ++i)
        {
            double          eval = evd.EigenValues[i].Real;
            Matrix <double> m    = Utilities.BuildM(evd.EigenVectors.Column(i).Normalize(2));

            tensileComp     += System.Math.Max(0, eval) * m;
            compressiveComp += System.Math.Min(0, eval) * m;
        }

        for (int i = 0; i < 3; ++i)
        {
            Vector <double> ftensil = Vector <double> .Build.Dense(3);

            Vector <double> fcompressive = Vector <double> .Build.Dense(3);

            CalculatePointForce(ftensil, i, tensileComp);

            fcompressive = forcesP[i] - ftensil;

            FracParticle fp = p[i].GetComponent <FracParticle>();
            fp.AddTensilLoad(ftensil);
            fp.AddCompressiveLoad(fcompressive);
        }
    }
Example #2
0
    private void Fracture()
    {
        // Reinitialize force accumulators and fracturing information of all particles
        for (int i = 0; i < particles.Count; ++i)
        {
            particles[i].GetComponent <FracParticle>().Reinitialize();
        }

        // Compute all forces applied to a particle and update force accumulators
        for (int i = 0; i < triangles.Count; ++i)
        {
            triangles[i].CalculateForces();
        }

        // Check if there are fractures at a particle's point
        for (int i = 0; i < particles.Count; ++i)
        {
            List <Vector <double> > planes = new List <Vector <double> >();
            FracParticle            fpi    = particles[i].GetComponent <FracParticle>();

            if (fpi.isFracturing(tau, planes))
            {
                Vector3 planeN = new Vector3();
                planeN.x = (float)planes[0].At(0);
                planeN.y = (float)planes[0].At(1);
                planeN.z = (float)planes[0].At(2);

                // Calculate distance from plane to origin
                Vector3 pos = particles[i].transform.position;
                float   d   = Mathf.Sqrt(pos.x * pos.x + pos.y * pos.y + pos.z * pos.z);

                for (int tri = 0; tri < triangles.Count; ++tri)
                {
                    // Check for intersection and assign side; only test on first plane for now
                    Vector3    tip                = new Vector3();
                    GameObject particleOnPlane    = null;
                    bool       isIntersectingElem = triangles[tri].Intersects(planeN, particles[i], d, tip, ref particleOnPlane);

                    if (isIntersectingElem)
                    {
                        CutElement(i, tip, triangles[tri], particleOnPlane);
                    }
                }
            }
        }

        // 5. Recalculate the mesh
        Remeshing();
    }
Example #3
0
    public void Remeshing()
    {
        List <int> indices = new List <int>();

        for (int i = 0; i < triangles.Count; ++i)
        {
            GameObject[] p   = triangles[i].Points;
            FracParticle fp1 = p[0].GetComponent <FracParticle>();
            FracParticle fp2 = p[1].GetComponent <FracParticle>();
            FracParticle fp3 = p[2].GetComponent <FracParticle>();

            Vector3 A = p[0].transform.position;
            Vector3 B = p[1].transform.position;
            Vector3 C = p[2].transform.position;

            int p1 = fp1.Id;
            int p2 = fp2.Id;
            int p3 = fp3.Id;

            Vector3 n           = new Vector3(0, 1, 0);
            float   r           = Vector3.Dot(n, Vector3.Cross(A - C, B - C));
            bool    isClockwise = r > 0;

            if (!isClockwise)
            {
                p2 = fp3.Id;
                p3 = fp2.Id;
            }

            indices.Add(p1);
            indices.Add(p2);
            indices.Add(p3);
        }

        Vector3[] vertices = new Vector3[particles.Count];
        for (int i = 0; i < particles.Count; ++i)
        {
            vertices[i] = particles[i].transform.position;
        }

        // Create the mesh
        Mesh msh = new Mesh();

        msh.vertices  = vertices;
        msh.triangles = indices.ToArray();
        msh.RecalculateNormals();
        msh.RecalculateBounds();
    }
Example #4
0
    // Intesection accounts only for the triangles adjacent to the planePoint
    public bool Intersects(Vector3 planeNormal, GameObject fracturePoint, float d, Vector3 tip, ref GameObject intersectingPointIfOnPlane)
    {
        intersectingPointIfOnPlane = null;

        bool intersects = false;
        bool connected  = false;

        // Verify if one of the 3 points in the mesh are connected to the planepoint
        // If so, verify if plane intersects 2 other points. No need to continue loop afterward.
        for (int i = 0; !intersects && i < 3; ++i)
        {
            if (p[i] == fracturePoint)
            {
                connected = true;

                // Calculate id of 2 other points
                int id0 = (i + 1) % 3;
                int id1 = (i + 2) % 3;

                // Only have to test once against the 2 other points
                intersects = GetSegmentPlaneIntersection(id0, id1, planeNormal, d, tip, ref intersectingPointIfOnPlane);
            }
        }

        // If the triangle is connected to the plane point, whether there is an intersection of not, assign a side to the points
        for (int i = 0; connected && i < 3; ++i)
        {
            FracParticle fp = p[i].GetComponent <FracParticle>();

            if (!fp.SideIsSet)
            {
                float side = Vector3.Dot(p[i].transform.position - fracturePoint.transform.position, planeNormal);
                fp.Side = side > 0;
            }
        }

        return(intersects);
    }
Example #5
0
    public void CutElement(int fracturePointId, Vector3 p1, FracTriangle triangle, GameObject particleOnPlane)
    {
        // Duplicate Fracture point
        GameObject   originalP  = particles[fracturePointId];
        FracParticle fpOriginal = originalP.GetComponent <FracParticle>();

        // Duplicate Particle and assign side of plane.
        // The new particle is defined as always on the positive side of the plane
        GameObject   duplicateP   = DuplicateParticle(fracturePointId);
        FracParticle fpDupplicate = duplicateP.GetComponent <FracParticle>();

        fpOriginal.Side   = false;
        fpDupplicate.Side = true;

        // If the other point is an already existing particle, then no other points to create
        GameObject secondPoint;

        if (particleOnPlane != null)
        {
            secondPoint = particleOnPlane;

            // HACK: This is a poor way of doing this search. Just trying to make it work here first.
            // Check if a spring between the originalPoint and the second point already exists
            bool alreadyExists = false;
            for (int i = 0; i < fpOriginal.Springs.Count; ++i)
            {
                Spring s = fpOriginal.Springs[i];
                if ((s.P2.gameObject == secondPoint && s.P1.gameObject == originalP) ||
                    (s.P1.gameObject == secondPoint && s.P2.gameObject == originalP))
                {
                    alreadyExists = true;
                }
            }

            if (!alreadyExists)
            {
                Spring s = originalP.AddComponent <Spring>();
                s.Initialize(originalP.GetComponent <Rigidbody>(), secondPoint.GetComponent <Rigidbody>());
            }

            Spring ds = duplicateP.AddComponent <Spring>();
            ds.Initialize(duplicateP.GetComponent <Rigidbody>(), secondPoint.GetComponent <Rigidbody>());
        }

        else
        {
            secondPoint = CreateParticle(p1);
        }

        // Reassign springs
        for (int i = 0; i < fpOriginal.Springs.Count; ++i)
        {
            Spring       s          = fpOriginal.Springs[i];
            GameObject   otherPoint = s.GetOtherPoint(originalP);
            FracParticle sfp        = otherPoint.GetComponent <FracParticle>();

            if (sfp.gameObject == secondPoint)
            {
                continue;
            }
            else
            {
                Assert.IsTrue(sfp.SideIsSet, "FracMesh : CutElement : Side is not set. Can't reassign springs");
            }

            // if spring particle doesn't have the same side as the initial particle, then the spring must be
            // re-assigned to the duplicate. Otherwise, nothing to change
            if (sfp.Side != fpOriginal.Side)
            {
                s.Initialize(otherPoint.GetComponent <Rigidbody>(), duplicateP.GetComponent <Rigidbody>());
            }
        }
    }