Beispiel #1
0
        public static FEMScene Create(Vector2f origin, float scale, int numPoints)
        {
            FEMScene Scene = new FEMScene();

            Scene.Substeps   = 40;
            Scene.Drag       = 1.0f;
            Scene.LameLambda = 10000.0f;
            Scene.LameMu     = 10000.0f;
            Scene.Damping    = 80.0f;
            Scene.Friction   = 0.95f;
            Scene.Toughness  = 20000.0f;

            List <Vector2f> points = new List <Vector2f>();

            //Random.InitState(0);

            for (int i = 0; i < numPoints; ++i)
            {
                float rx = Random.Range(-scale, scale) * 0.5f;
                float ry = Random.Range(-scale, scale) * 0.5f;

                points.Add(origin + new Vector2f(rx, ry));
            }

            List <Vector2f> verts;
            List <int>      tris;

            Mesher.TriangulateDelaunay(points, out verts, out tris);

            // generate elements
            for (int i = 0; i < verts.Count; ++i)
            {
                Scene.Particles.Add(new FEMParticle(verts[i], 1.0f));
            }

            for (int i = 0; i < tris.Count / 3; ++i)
            {
                Scene.Triangles.Add(new Triangle(tris[i * 3], tris[i * 3 + 1], tris[i * 3 + 2]));
            }

            // assign index to particles
            for (int i = 0; i < Scene.Particles.Count; ++i)
            {
                Scene.Particles[i].index = i;
            }

            Scene.CreateElements();

            return(Scene);
        }
Beispiel #2
0
        public static FEMScene Create(Vector2f origin, float inner, float outer, int segments)
        {
            FEMScene Scene = new FEMScene();

            Scene.Substeps   = 40;
            Scene.Drag       = 1.0f;
            Scene.LameLambda = 10000.0f;
            Scene.LameMu     = 10000.0f;
            Scene.Damping    = 80.0f;
            Scene.Friction   = 0.95f;
            Scene.Toughness  = 20000.0f;

            List <Vector2f> verts = new List <Vector2f>();
            List <int>      tris  = new List <int>();

            Mesher.CreateTorus(verts, tris, inner, outer, segments);

            // generate elements
            for (int i = 0; i < verts.Count; ++i)
            {
                Scene.Particles.Add(new FEMParticle(origin + verts[i], 1.0f));
            }

            for (int i = 0; i < tris.Count / 3; ++i)
            {
                Scene.Triangles.Add(new Triangle(tris[i * 3], tris[i * 3 + 1], tris[i * 3 + 2]));
            }

            // assign index to particles
            for (int i = 0; i < Scene.Particles.Count; ++i)
            {
                Scene.Particles[i].index = i;
            }

            Scene.CreateElements();

            return(Scene);
        }
Beispiel #3
0
        public static FEMScene Create(Texture2D img)
        {
            FEMScene Scene = new FEMScene();

            if (img == null)
            {
                return(Scene);
            }

            Scene.Substeps   = 80;
            Scene.Drag       = 0.1f;
            Scene.LameLambda = 42000.0f;
            Scene.LameMu     = 42000.0f;
            Scene.Damping    = 250.0f;
            Scene.Friction   = 0.8f;
            Scene.Toughness  = 40000.0f;

            List <Vector2f> points  = new List <Vector2f>();
            List <Vector2f> bpoints = new List <Vector2f>();

            // controls how finely the object is sampled
            aspect = (float)img.height / img.width;

            float fw = img.width;
            float fh = img.height;

            int inc    = Mathf.FloorToInt(img.width * resolution);
            int margin = Mathf.Max((inc - 1) / 2, 1);

            // distribute points interior to the object or near it's boundary
            for (int y = 0; y < img.height; y += inc)
            {
                for (int x = 0; x < img.width; x += inc)
                {
                    // if value non-zero then add a point
                    int n = Neighbours(img, x, y, margin);

                    if (n > 0)
                    {
                        Vector2f uv = new Vector2f(x / fw, y / fh);
                        points.Add(uv);
                    }
                }
            }

            // distribute points on the boundary
            for (int y = 0; y < img.height; y++)
            {
                for (int x = 0; x < img.width; x++)
                {
                    if (EdgeDetect(img, x, y))
                    {
                        Vector2f uv = new Vector2f(x / fw, y / fh);
                        bpoints.Add(uv);
                    }
                }
            }

            // triangulate
            int iterations = 7;

            List <Vector2f> verts;
            List <int>      tris;

            Mesher.TriangulateVariational(points, bpoints, iterations, out verts, out tris);

            //no longer used
            points  = null;
            bpoints = null;

            // discard triangles whose centroid is not inside the shape
            for (int i = 0; i < tris.Count;)
            {
                Vector2f p = verts[tris[i + 0]];
                Vector2f q = verts[tris[i + 1]];
                Vector2f r = verts[tris[i + 2]];

                Vector2f c = (p + q + r) / 3.0f;

                //int x = Mathf.FloorToInt(c.x * fw);
                //int y = Mathf.FloorToInt(c.y * fh);
                //Color col = img.GetPixel(x, y);

                Color col = img.GetPixelBilinear(c.x, c.y);

                if (col.grayscale == 0.0f)
                {
                    tris.RemoveRange(i, 3);
                }
                else
                {
                    i += 3;
                }
            }

            // generate particles
            for (int i = 0; i < verts.Count; ++i)
            {
                Vector2f uv = verts[i];
                Scene.Particles.Add(new FEMParticle(ToWorldPos(uv), uv, 0.0f));
            }

            // generate elements and assign mass based on connected area
            for (int t = 0; t < tris.Count; t += 3)
            {
                int i = tris[t];
                int j = tris[t + 1];
                int k = tris[t + 2];

                // calculate tri area
                Vector2f a = Scene.Particles[i].p;
                Vector2f b = Scene.Particles[j].p;
                Vector2f c = Scene.Particles[k].p;

                float area = 0.5f * Vector2f.Cross(b - a, c - a);
                float mass = density * area / 3.0f;

                Scene.Particles[i].invMass += mass;
                Scene.Particles[j].invMass += mass;
                Scene.Particles[k].invMass += mass;

                Scene.Triangles.Add(new Triangle(i, j, k));
            }

            // convert mass to invmass
            for (int i = 0; i < Scene.Particles.Count; ++i)
            {
                if (Scene.Particles[i].invMass > 0.0f)
                {
                    Scene.Particles[i].invMass = 1.0f / Scene.Particles[i].invMass;
                }
            }

            // assign index to particles
            for (int i = 0; i < Scene.Particles.Count; ++i)
            {
                Scene.Particles[i].index = i;
            }

            Scene.CreateElements();

            return(Scene);
        }