コード例 #1
0
        public static List <Fixture> TextureToPolygon(Texture2D texture, Vector2 scaling, BodyType bodyType, Vector2 position, float density)
        {
            uint[] data = new uint[texture.Width * texture.Height];
            texture.GetData(data);
            Vertices vertices      = PolygonTools.CreatePolygon(data, texture.Width, texture.Height, true);
            var      polygonOffset = new Vector2(-texture.Width / 2, -texture.Height / 2);

            vertices.Translate(ref polygonOffset);
            Vector2 scale = new Vector2(0.01f, 0.01f) * scaling;

            vertices.Scale(ref scale);

            List <Vertices> tempList = EarclipDecomposer.ConvexPartition(vertices);
            List <Vertices> toRemove = new List <Vertices>();

            foreach (Vertices item in tempList)
            {
                if (item.Count == 0)
                {
                    toRemove.Add(item);
                }
            }
            foreach (Vertices item in toRemove)
            {
                tempList.Remove(item);
            }

            List <Fixture> combine = FixtureFactory.CreateCompoundPolygon(Level.Physics, tempList, 1);

            combine[0].Body.BodyType = bodyType;
            combine[0].Body.Position = ToMeter(position);
            return(combine);
        }
コード例 #2
0
ファイル: PolygonCollider.cs プロジェクト: mikecrews/FFWD
        protected override void DoAddCollider(FarseerPhysics.Dynamics.Body body, float mass)
        {
            switch (plane2d)
            {
            case Plane2d.XY:
                to2dMode = Physics.To2dMode.DropZ;
                break;

            case Plane2d.XZ:
                to2dMode = Physics.To2dMode.DropY;
                break;

            case Plane2d.YZ:
                to2dMode = Physics.To2dMode.DropX;
                break;
            }
            connectedBody = body;
            Vector2  scale = VectorConverter.Convert(transform.lossyScale, to2dMode);
            Vertices v     = new Vertices();

            for (int i = 0; i < relativePoints.Length; i++)
            {
                v.Add(relativePoints[i] * scale);
            }
            Physics.AddMesh(body, isTrigger, EarclipDecomposer.ConvexPartition(v), mass);
        }
コード例 #3
0
        public ParkingSpaceObstacle(World world, Vector2 position, float rotation)
        {
            Vector2[] vertices = new Vector2[8];
            vertices[0] = new Vector2(-3.5f, 1.5f);
            vertices[1] = new Vector2(3.5f, 1.5f);
            vertices[2] = new Vector2(3.5f, -1.5f);
            vertices[3] = new Vector2(-3.5f, -1.5f);
            vertices[4] = new Vector2(-3.5f, -1.45f);
            vertices[5] = new Vector2(3.45f, -1.45f);
            vertices[6] = new Vector2(3.45f, 1.45f);
            vertices[7] = new Vector2(-3.45f, 1.45f);

            for (int i = 0; i < 8; i++)
            {
                vertices[i] *= 10;
            }

            LinkedList <Vertices> vertexSet = new LinkedList <Vertices>();

            vertexSet.AddAll(EarclipDecomposer.ConvexPartition(new Vertices(vertices)));

            foreach (Vertices v in vertexSet)
            {
                Body b = BodyFactory.CreatePolygon(world, v, 1f, position);
                b.BodyType = BodyType.Static;
                b.Rotation = rotation;

                Bodies.Add(b);
            }
        }
コード例 #4
0
        public static BreakableBody CreateBreakableBody(World world, Vertices vertices, float density)
        {
            List <Vertices> triangles;

            if (vertices.Count <= 10)
            {
                triangles = DelauneyTriangulate(vertices);
            }
            else
            {
                if (rand.RandomBoolean)
                {
                    triangles = DelauneyTriangulate(vertices);
                }
                else
                {
                    triangles = EarclipDecomposer.ConvexPartition(vertices);
                }
            }

            BreakableBody breakableBody = new BreakableBody(triangles, world, density);

            world.AddBreakableBody(breakableBody);

            return(breakableBody);
        }
コード例 #5
0
ファイル: AssetCreator.cs プロジェクト: bsimser/cdx
        /// <summary>
        /// </summary>
        /// <param name = "vertices"></param>
        /// <param name = "type"></param>
        /// <param name = "color"></param>
        /// <param name = "materialScale"></param>
        /// <returns></returns>
        public Texture2D TextureFromVertices(Vertices vertices, MaterialType type, Color color, float materialScale)
        {
            // copy vertices
            var verts = new Vertices(vertices);

            // scale to display units (i.e. pixels) for rendering to texture
            var scale = ConvertUnits.ToDisplayUnits(Vector2.One);

            verts.Scale(ref scale);

            // translate the boundingbox center to the texture center
            // because we use an orthographic projection for rendering later
            var vertsBounds = verts.GetCollisionBox();

            verts.Translate(-vertsBounds.Center);

            var decomposedVerts = !verts.IsConvex() ? EarclipDecomposer.ConvexPartition(verts) : new List <Vertices> {
                verts
            };
            var verticesFill =
                new List <VertexPositionColorTexture[]>(decomposedVerts.Count);

            materialScale /= _materials[type].Width;

            for (var i = 0; i < decomposedVerts.Count; ++i)
            {
                verticesFill.Add(new VertexPositionColorTexture[3 * (decomposedVerts[i].Count - 2)]);
                for (var j = 0; j < decomposedVerts[i].Count - 2; ++j)
                {
                    // fill vertices
                    verticesFill[i][3 * j].Position              = new Vector3(decomposedVerts[i][0], 0f);
                    verticesFill[i][3 * j + 1].Position          = new Vector3(decomposedVerts[i].NextVertex(j), 0f);
                    verticesFill[i][3 * j + 2].Position          = new Vector3(decomposedVerts[i].NextVertex(j + 1), 0f);
                    verticesFill[i][3 * j].TextureCoordinate     = decomposedVerts[i][0] * materialScale;
                    verticesFill[i][3 * j + 1].TextureCoordinate = decomposedVerts[i].NextVertex(j) * materialScale;
                    verticesFill[i][3 * j + 2].TextureCoordinate = decomposedVerts[i].NextVertex(j + 1) * materialScale;
                    verticesFill[i][3 * j].Color         =
                        verticesFill[i][3 * j + 1].Color = verticesFill[i][3 * j + 2].Color = color;
                }
            }

            // calculate outline
            var verticesOutline = new VertexPositionColor[2 * verts.Count];

            for (var i = 0; i < verts.Count; ++i)
            {
                verticesOutline[2 * i].Position     = new Vector3(verts[i], 0f);
                verticesOutline[2 * i + 1].Position = new Vector3(verts.NextVertex(i), 0f);
                verticesOutline[2 * i].Color        = verticesOutline[2 * i + 1].Color = Color.Black;
            }

            var vertsSize = new Vector2(vertsBounds.UpperBound.X - vertsBounds.LowerBound.X,
                                        vertsBounds.UpperBound.Y - vertsBounds.LowerBound.Y);

            return(RenderTexture((int)vertsSize.X, (int)vertsSize.Y,
                                 _materials[type], verticesFill, verticesOutline));
        }
コード例 #6
0
        /// <summary>
        /// Creates a breakable body. You would want to remove collinear points before using this.
        /// </summary>
        /// <param name="world">The world.</param>
        /// <param name="vertices">The vertices.</param>
        /// <param name="density">The density.</param>
        /// <param name="position">The position.</param>
        /// <returns></returns>
        public static BreakableBody CreateBreakableBody(World world, Vertices vertices, float density, Vector2 position)
        {
            List <Vertices> triangles = EarclipDecomposer.ConvexPartition(vertices);

            BreakableBody breakableBody = new BreakableBody(triangles, world, density);

            breakableBody.MainBody.Position = position;
            world.AddBreakableBody(breakableBody);

            return(breakableBody);
        }
コード例 #7
0
ファイル: BodyFactory.cs プロジェクト: migreva/CocoBounce
        /// <summary>
        /// Creates a breakable body. You would want to remove collinear points before using this.
        /// </summary>
        /// <param name="world">The world.</param>
        /// <param name="vertices">The vertices.</param>
        /// <param name="density">The density.</param>
        /// <param name="position">The position.</param>
        /// <returns></returns>
        public static FSBreakableBody CreateBreakableBody(FSWorld world, Vertices vertices, float density, FVector2 position,
                                                          object userData)
        {
            List <Vertices> triangles = EarclipDecomposer.ConvexPartition(vertices);

            FSBreakableBody breakableBody = new FSBreakableBody(triangles, world, density, userData);

            breakableBody.MainBody.Position = position;
            world.AddBreakableBody(breakableBody);

            return(breakableBody);
        }
コード例 #8
0
        /// <summary>
        /// Creates a breakable body. You would want to remove collinear points before using this.
        /// </summary>
        /// <param name="world">The world.</param>
        /// <param name="vertices">The vertices.</param>
        /// <param name="density">The density.</param>
        /// <param name="position">The position.</param>
        /// <returns></returns>
        public static BreakableBody CreateBreakableBody(World world, Vertices vertices, float density, Vector2 position,
                                                        PressPlay.FFWD.Components.Collider userData)
        {
            List <Vertices> triangles = EarclipDecomposer.ConvexPartition(vertices);

            BreakableBody breakableBody = new BreakableBody(triangles, world, density, userData);

            breakableBody.MainBody.Position = position;
            world.AddBreakableBody(breakableBody);

            return(breakableBody);
        }
コード例 #9
0
ファイル: FixtureFactory.cs プロジェクト: mikecrews/FFWD
        public static List <Fixture> AttachSolidArc(float density, float radians, int sides, float radius, Vector2 position, float angle, Body body)
        {
            Vertices arc = PolygonTools.CreateArc(radians, sides, radius);

            arc.Rotate((MathHelper.Pi - radians) / 2 + angle);

            arc.Translate(ref position);

            //Close the arc
            arc.Add(arc[0]);

            List <Vertices> triangles = EarclipDecomposer.ConvexPartition(arc);

            return(AttachCompoundPolygon(triangles, density, body));
        }
コード例 #10
0
ファイル: SpinAssist.cs プロジェクト: KingpinBen/Spin-Doctor
        public static TexVertOutput TexToVert(World world, Texture2D texture, float mass, bool useCentroid, float scale)
        {
            Vertices      verts;
            TexVertOutput output = new TexVertOutput();

            //  Creates an array for every pixel in the texture
            uint[] data = new uint[texture.Width * texture.Height];

            texture.GetData(data);

            verts = PolygonTools.CreatePolygon(data, texture.Width, false);

            Vector2 centroid = Vector2.Zero;

            //  Origin needs to be altered so it uses the origin of the verts
            //  rather than the texture's centre.
            if (useCentroid)
            {
                centroid = -verts.GetCentroid();
                verts.Translate(ref centroid);
            }
            else
            {
                centroid = ConvertUnits.ToSimUnits(new Vector2(texture.Width, texture.Height) * 0.5f);
            }


            float   simScale = ConvertUnits.ToSimUnits(scale);
            Vector2 Scale    = new Vector2(simScale, simScale);

            verts.Scale(ref Scale);

            verts = SimplifyTools.ReduceByDistance(verts, ConvertUnits.ToSimUnits(4f));

            Body body = BodyFactory.CreateCompoundPolygon(world, EarclipDecomposer.ConvexPartition(verts), mass);

            body.BodyType = BodyType.Dynamic;

            if (!useCentroid)
            {
                body.LocalCenter = centroid;
            }

            output.Body   = body;
            output.Origin = ConvertUnits.ToDisplayUnits(centroid);

            return(output);
        }
コード例 #11
0
        public void NextStep(Vector2 position)
        {
            switch (_step)
            {
            case 0:
                _finished      = false;
                _statusMessage = "Attaching fixture to body. Choose body...";
                _step++;
                break;

            case 1:
                _foundBody = CommonHelpers.FindBody(position, _world);
                if (_foundBody == null)
                {
                    _statusMessage = "Cant find body in this position. Choose Body...";
                    break;
                }
                _statusMessage = "Body has been selected. Choose fixture position...";
                _step++;
                break;

            case 2:
                Vector2  offset             = CommonHelpers.CalculateLocalPoint(position, _foundBody);
                Vertices _tempShapeVertices = new Vertices(_initialShapeVertices);
                _tempShapeVertices.Rotate(-_foundBody.Rotation);
                _tempShapeVertices.Rotate(_prototypeBody.Rotation);
                _tempShapeVertices.Translate(ref offset);

                List <Vertices> decomposedVerts = EarclipDecomposer.ConvexPartition(_tempShapeVertices);
                _resultShapeList = new List <Shape>(decomposedVerts.Count);

                foreach (Vertices vertices in decomposedVerts)
                {
                    if (vertices.Count == 2)
                    {
                        _resultShapeList.Add(new EdgeShape(vertices[0], vertices[1]));
                    }
                    else
                    {
                        _resultShapeList.Add(new PolygonShape(vertices, _prototypeBody.Density == null ? 1f : (float)_prototypeBody.Density));
                    }
                }
                _statusMessage = "Fixture has been created.";
                _finished      = true;
                _step          = 0;
                break;
            }
        }
コード例 #12
0
        public static Body CreateGear(World world, float radius, int numberOfTeeth, float tipPercentage,
                                      float toothHeight, float density, object userData)
        {
            Vertices gearPolygon = PolygonTools.CreateGear(radius, numberOfTeeth, tipPercentage, toothHeight);

            //Gears can in some cases be convex
            if (!gearPolygon.IsConvex())
            {
                //Decompose the gear:
                List <Vertices> list = EarclipDecomposer.ConvexPartition(gearPolygon);

                return(CreateCompoundPolygon(world, list, density, userData));
            }

            return(CreatePolygon(world, gearPolygon, density, userData));
        }
コード例 #13
0
        public void AddShadowForObject(Texture2D texture, Vector2 position)
        {
            uint[] data = new uint[texture.Width * texture.Height];
            texture.GetData <uint>(data);

            foreach (var poly in EarclipDecomposer.ConvexPartition(PolygonTools.CreatePolygon(data, texture.Width)))
            {
                if (poly.Count >= 3)
                {
                    var array = poly.ToArray();

                    var hull = ShadowHull.CreateConvex(ref array);
                    hull.Position = position;

                    _krypton.Hulls.Add(hull);
                }
            }
        }
コード例 #14
0
        /// <summary>
        /// Creates a rounded rectangle.
        /// Note: Automatically decomposes the capsule if it contains too many vertices (controlled by Settings.MaxPolygonVertices)
        /// </summary>
        /// <param name="world">The world.</param>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        /// <param name="xRadius">The x radius.</param>
        /// <param name="yRadius">The y radius.</param>
        /// <param name="segments">The segments.</param>
        /// <param name="density">The density.</param>
        /// <param name="position">The position.</param>
        /// <returns></returns>
        public static Body CreateRoundedRectangle(World world, float width, float height, float xRadius,
                                                  float yRadius,
                                                  int segments, float density, Vector2 position,
                                                  object userData)
        {
            Vertices verts = PolygonTools.CreateRoundedRectangle(width, height, xRadius, yRadius, segments);

            //There are too many vertices in the capsule. We decompose it.
            if (verts.Count >= Settings.MaxPolygonVertices)
            {
                List <Vertices> vertList = EarclipDecomposer.ConvexPartition(verts);
                Body            body     = CreateCompoundPolygon(world, vertList, density, userData);
                body.Position = position;
                return(body);
            }

            return(CreatePolygon(world, verts, density));
        }
コード例 #15
0
        /// <summary>
        /// Convert a closed path into a polygon.
        /// Convex decomposition is automatically performed.
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="body">The body.</param>
        /// <param name="density">The density.</param>
        /// <param name="subdivisions">The subdivisions.</param>
        public static void ConvertPathToPolygon(Path path, FSBody body, float density, int subdivisions)
        {
            if (!path.Closed)
            {
                throw new Exception("The path must be closed to convert to a polygon.");
            }

            List <FVector2> verts = path.GetVertices(subdivisions);

            List <Vertices> decomposedVerts = EarclipDecomposer.ConvexPartition(new Vertices(verts));

            //List<Vertices> decomposedVerts = BayazitDecomposer.ConvexPartition(new Vertices(verts));

            foreach (Vertices item in decomposedVerts)
            {
                body.CreateFixture(new PolygonShape(item, density));
            }
        }
コード例 #16
0
        /// <summary>
        /// Creates a rounded rectangle.
        /// Note: Automatically decomposes the capsule if it contains too many vertices (controlled by Settings.MaxPolygonVertices)
        /// </summary>
        /// <param name="world">The world.</param>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        /// <param name="xRadius">The x radius.</param>
        /// <param name="yRadius">The y radius.</param>
        /// <param name="segments">The segments.</param>
        /// <param name="density">The density.</param>
        /// <param name="position">The position.</param>
        /// <returns></returns>
        public static List <Fixture> CreateRoundedRectangle(World world, float width, float height, float xRadius,
                                                            float yRadius,
                                                            int segments, float density, Vector2 position)
        {
            Vertices verts = PolygonTools.CreateRoundedRectangle(width, height, xRadius, yRadius, segments);

            //There are too many vertices in the capsule. We decompose it.
            if (verts.Count >= Settings.MaxPolygonVertices)
            {
                List <Vertices> vertList    = EarclipDecomposer.ConvexPartition(verts);
                List <Fixture>  fixtureList = CreateCompoundPolygon(world, vertList, density);
                fixtureList[0].Body.Position = position;
                return(fixtureList);
            }

            return(new List <Fixture> {
                CreatePolygon(world, verts, density)
            });
        }
コード例 #17
0
        public static List <Fixture> CreateGear(World world, float radius, int numberOfTeeth, float tipPercentage,
                                                float toothHeight, float density)
        {
            Vertices gearPolygon = PolygonTools.CreateGear(radius, numberOfTeeth, tipPercentage, toothHeight);

            //Gears can in some cases be convex
            if (!gearPolygon.IsConvex())
            {
                //Decompose the gear:
                List <Vertices> list = EarclipDecomposer.ConvexPartition(gearPolygon);

                return(CreateCompoundPolygon(world, list, density));
            }

            List <Fixture> fixtures = new List <Fixture>();

            fixtures.Add(CreatePolygon(world, gearPolygon, density));
            return(fixtures);
        }
コード例 #18
0
        public override void LoadContent()
        {
            if (!isInitialized)
            {
                polygons = new List <Vector2[]>();
                vertices = new List <VertexPositionColor[]>();
                Vertices        tempVertices     = new Vertices(WorldPoints);
                List <Vertices> tempVerticesList = EarclipDecomposer.ConvexPartition(tempVertices);

                int index = 0;

                foreach (Vertices v in tempVerticesList)
                {
                    polygons.Add(new Vector2[v.Count]);

                    for (int i = 0; i < polygons[index].Length; i++)
                    {
                        polygons.ElementAt(index)[i] = v.ElementAt(i);
                    }
                    index++;
                }

                for (int i = 0; i < polygons.Count; i++)
                {
                    vertices.Add(new VertexPositionColor[polygons[i].Length * 3]);

                    for (int i2 = 1; i2 < polygons[i].Length - 1; i2++)
                    {
                        vertices.ElementAt(i)[(i2 - 1) * 3].Position = new Vector3(polygons.ElementAt(i)[0], 0.0f);
                        vertices.ElementAt(i)[(i2 - 1) * 3].Color    = color;

                        vertices.ElementAt(i)[(i2 - 1) * 3 + 1].Position = new Vector3(polygons.ElementAt(i)[i2], 0.0f);
                        vertices.ElementAt(i)[(i2 - 1) * 3 + 1].Color    = color;

                        vertices.ElementAt(i)[(i2 - 1) * 3 + 2].Position = new Vector3(polygons.ElementAt(i)[i2 + 1], 0.0f);
                        vertices.ElementAt(i)[(i2 - 1) * 3 + 2].Color    = color;
                    }
                }

                isInitialized = true;
            }
        }
コード例 #19
0
        /// <summary>
        /// Creates a capsule.
        /// Note: Automatically decomposes the capsule if it contains too many vertices (controlled by Settings.MaxPolygonVertices)
        /// </summary>
        /// <param name="world">The world.</param>
        /// <param name="height">The height.</param>
        /// <param name="topRadius">The top radius.</param>
        /// <param name="topEdges">The top edges.</param>
        /// <param name="bottomRadius">The bottom radius.</param>
        /// <param name="bottomEdges">The bottom edges.</param>
        /// <param name="density">The density.</param>
        /// <param name="position">The position.</param>
        /// <returns></returns>
        public static List <Fixture> CreateCapsule(World world, float height, float topRadius, int topEdges,
                                                   float bottomRadius,
                                                   int bottomEdges, float density, Vector2 position)
        {
            Vertices verts = PolygonTools.CreateCapsule(height, topRadius, topEdges, bottomRadius, bottomEdges);

            //There are too many vertices in the capsule. We decompose it.
            if (verts.Count >= Settings.MaxPolygonVertices)
            {
                List <Vertices> vertList    = EarclipDecomposer.ConvexPartition(verts);
                List <Fixture>  fixtureList = CreateCompoundPolygon(world, vertList, density);
                fixtureList[0].Body.Position = position;

                return(fixtureList);
            }

            return(new List <Fixture> {
                CreatePolygon(world, verts, density)
            });
        }
コード例 #20
0
        private void MakePolygon()
        {
            Vector2 avgLoc = new Vector2();

            foreach (Vector2 vert in polyPoints)
            {
                avgLoc += vert;
            }
            avgLoc /= polyPoints.Count;



            Vertices verts = new Vertices();

            foreach (Vector2 v in polyPoints)
            {
                verts.Add(v - avgLoc);
            }

            Body           b           = new Body(game.farseerManager.world);
            List <Fixture> composition = FixtureFactory.AttachCompoundPolygon(EarclipDecomposer.ConvexPartition(verts), 1, b);

            b.Position = avgLoc;

            foreach (Fixture triangle in composition)
            {
                FarseerTextures.ApplyTexture(triangle, FarseerTextures.TextureType.Normal);
            }

            if (composition.Count > 0)
            {
                FormManager.Property.setPendingObjects(new List <object>()
                {
                    composition[0].Body
                });
            }

            polyPoints.Clear();
        }
コード例 #21
0
        private void UpdatePolys()
        {
            World.Clear();
            _sw.Start();

            _aabb = new AABB {
                LowerBound = new Vector2(0, 0), UpperBound = new Vector2(_terrainTex.Width, _terrainTex.Height),
            };
            _polys = MarchingSquares.DetectSquares(_aabb, _gridSize, _gridSize, Eval, _level, _combine);

            _sw.Stop();
            _time = _sw.Elapsed.TotalMilliseconds;
            _sw.Reset();

            for (int i = 0; i < _polys.Count; i++)
            {
                Vertices poly = _polys[i];
                poly.Translate(ref _translate);

                poly.Scale(ref _scale);
                poly.ForceCounterClockWise();

                if (!poly.IsConvex())
                {
                    List <Vertices> verts = EarclipDecomposer.ConvexPartition(poly);

                    for (int j = 0; j < verts.Count; j++)
                    {
                        Vertices v = verts[j];
                        FixtureFactory.CreatePolygon(World, v, 1);
                    }
                }
                else
                {
                    FixtureFactory.CreatePolygon(World, poly, 1);
                }
            }
        }
コード例 #22
0
        /// <summary>
        /// Creates a capsule.
        /// Note: Automatically decomposes the capsule if it contains too many vertices (controlled by Settings.MaxPolygonVertices)
        /// </summary>
        /// <param name="world">The world.</param>
        /// <param name="height">The height.</param>
        /// <param name="topRadius">The top radius.</param>
        /// <param name="topEdges">The top edges.</param>
        /// <param name="bottomRadius">The bottom radius.</param>
        /// <param name="bottomEdges">The bottom edges.</param>
        /// <param name="density">The density.</param>
        /// <param name="position">The position.</param>
        /// <returns></returns>
        public static Body CreateCapsule(World world, float height, float topRadius, int topEdges,
                                         float bottomRadius,
                                         int bottomEdges, float density, Vector2 position, object userData)
        {
            Vertices verts = PolygonTools.CreateCapsule(height, topRadius, topEdges, bottomRadius, bottomEdges);

            Body body;

            //There are too many vertices in the capsule. We decompose it.
            if (verts.Count >= Settings.MaxPolygonVertices)
            {
                List <Vertices> vertList = EarclipDecomposer.ConvexPartition(verts);
                body          = CreateCompoundPolygon(world, vertList, density, userData);
                body.Position = position;

                return(body);
            }

            body          = CreatePolygon(world, verts, density, userData);
            body.Position = position;

            return(body);
        }
コード例 #23
0
ファイル: TextureGenerator.cs プロジェクト: neaket/Dragonfly
        public Texture2D TextureFromVertices(Vertices vertices, Texture2D material, Color fillColor, bool hasOutline, Color outlineColor, float materialScale)
        {
            Vertices verts = new Vertices(vertices);

            AABB vertsBounds = verts.GetCollisionBox();

            verts.Translate(-vertsBounds.Center);

            List <Vertices> decomposedVerts;

            if (!verts.IsConvex())
            {
                decomposedVerts = EarclipDecomposer.ConvexPartition(verts);
            }
            else
            {
                decomposedVerts = new List <Vertices>()
                {
                    verts
                };
            }

            //fill
            List <VertexPositionColorTexture[]> verticesFill = new List <VertexPositionColorTexture[]>(decomposedVerts.Count);

            for (int i = 0; i < decomposedVerts.Count; i++)
            {
                verticesFill.Add(new VertexPositionColorTexture[3 * (decomposedVerts[i].Count - 2)]);
                for (int j = 0; j < decomposedVerts[i].Count - 2; j++)
                {
                    verticesFill[i][3 * j].Position              = new Vector3(decomposedVerts[i][0], 0f);
                    verticesFill[i][3 * j + 1].Position          = new Vector3(decomposedVerts[i].NextVertex(j), 0f);
                    verticesFill[i][3 * j + 2].Position          = new Vector3(decomposedVerts[i].NextVertex(j + 1), 0f);
                    verticesFill[i][3 * j].TextureCoordinate     = decomposedVerts[i][0] * materialScale;
                    verticesFill[i][3 * j + 1].TextureCoordinate = decomposedVerts[i].NextVertex(j) * materialScale;
                    verticesFill[i][3 * j + 2].TextureCoordinate = decomposedVerts[i].NextVertex(j + 1) * materialScale;
                    verticesFill[i][3 * j].Color = verticesFill[i][3 * j + 1].Color = verticesFill[i][3 * j + 2].Color = fillColor;
                }
            }

            //outline
            VertexPositionColor[] verticesOutline;

            if (!hasOutline)
            {
                verticesOutline = new VertexPositionColor[0];
            }
            else
            {
                verticesOutline = new VertexPositionColor[2 * verts.Count];
                for (int i = 0; i < verts.Count; i++)
                {
                    verticesOutline[2 * i].Position     = new Vector3(verts[i], 0f);
                    verticesOutline[2 * i + 1].Position = new Vector3(verts.NextVertex(i), 0f);
                    verticesOutline[2 * i].Color        = verticesOutline[2 * i + 1].Color = outlineColor;
                }
            }

            Vector2 vertsSize = new Vector2(vertsBounds.UpperBound.X - vertsBounds.LowerBound.X, vertsBounds.UpperBound.Y - vertsBounds.LowerBound.Y);

            return(RenderTexture((int)System.Math.Ceiling(vertsSize.X), (int)System.Math.Ceiling(vertsSize.Y), material, verticesFill, hasOutline, verticesOutline));
        }
コード例 #24
0
        public static void ComputeProperties(this Rigidbody2D body, IList <Collider2D> shapes, ref MassData[] massData)
        {
            var totalMass = body.mass;
            var totalArea = 0.0f;

            // Calculate initial properties
            for (var i = 0; i < massData.Length; i++)
            {
                var shape = shapes[i];
                massData[i].shape = shape;

                var xf = shape.transform;
                massData[i].xf = xf;

                Vector2 scale = xf.lossyScale;
                scale.Set(Mathf.Abs(scale.x), Mathf.Abs(scale.y));

                if (!shape.enabled)
                {
                    massData[i].area = 0;
                    continue;
                }

                if (shape is CircleCollider2D)
                {
                    var   circle = shape as CircleCollider2D;
                    var   rad    = circle.radius * Mathf.Max(scale.x, scale.y);
                    float area   = Mathf.PI * rad * rad;
                    massData[i].area     = area;
                    massData[i].centroid = circle.offset;
                    totalArea           += area;
                }
                else if (shape is BoxCollider2D)
                {
                    var box = shape as BoxCollider2D;

                    var       area   = 0f;
                    var       I      = 0.0f;
                    var       center = Vector2.zero;
                    var       s      = Vector2.zero;
                    const int l      = 4;

                    var points = new Vector2[4];
                    var ex     = Vector2.Scale(box.size, scale) / 2f;
                    points[0] = box.offset + ex;
                    points[1] = box.offset + new Vector2(-ex.x, ex.y);
                    points[2] = box.offset - ex;
                    points[3] = box.offset + new Vector2(ex.x, -ex.y);

                    massData[i].points = points;
                    massData[i].depths = new float[4];

                    // This code would put the reference point inside the polygon
                    for (var j = 0; j < l; ++j)
                    {
                        s += points[i];
                    }
                    s *= 1.0f / l;

                    const float k_inv3 = 1.0f / 3.0f;

                    for (var j = 0; j < l; ++j)
                    {
                        // Triangle vertices
                        var e1 = points[j] - s;
                        var e2 = j + 1 < l ? points[j + 1] - s : points[0] - s;

                        var D = Cross(e1, e2);

                        float triangleArea = 0.5f * D;
                        area += triangleArea;

                        // Area weighted centroid
                        center += triangleArea * k_inv3 * (e1 + e2);

                        float ex1 = e1.x, ey1 = e1.y;
                        float ex2 = e2.x, ey2 = e2.y;

                        var intx2 = ex1 * ex1 + ex2 * ex1 + ex2 * ex2;
                        var inty2 = ey1 * ey1 + ey2 * ey1 + ey2 * ey2;

                        I += 0.25f * k_inv3 * D * (intx2 + inty2);
                    }

                    // Area
                    massData[i].area = area;
                    totalArea       += area;

                    // Center of mass
                    center *= 1.0f / area;
                    massData[i].centroid = center + s;

                    // For inertia calc
                    massData[i].center = center;
                    massData[i].i      = I;
                }
                else if (shape is EdgeCollider2D)
                {
                    // Edges have no area, therefore they don't have mass or
                    // contribute to center of mass
                    massData[i].area = 0;
                }
                else if (shape is PolygonCollider2D)
                {
                    var poly = shape as PolygonCollider2D;

                    var pathL = poly.pathCount;

                    for (int k = 0; k < pathL; ++k)
                    {
                        var decomposed = EarclipDecomposer.ConvexPartition(poly.GetPath(k));

                        var l = decomposed.Count;

                        // Resize array
                        System.Array.Resize(ref massData, massData.Length + (l - 1));

                        // Compute each path as a seperate set of mass data
                        for (var j = 0; j < l; ++j)
                        {
                            if (decomposed[j].Count < 3)
                            {
                                // Degenerate case
                                continue;
                            }
                            ComputePropertiesPoly(poly, decomposed[j], massData, scale, j, i, ref totalArea);
                        }

                        // Increase iterator
                        i += l - 1;
                    }
                }
            }

            for (var i = 0; i < massData.Length; i++)
            {
                var shape = massData[i].shape;

                if (!shape || !shape.enabled)
                {
                    massData[i].mass    = 0;
                    massData[i].inertia = 0;
                    continue;
                }

                massData[i].mass = (massData[i].area * totalMass) / totalArea;

                if (shape is CircleCollider2D)
                {
                    var circle = shape as CircleCollider2D;
                    // inertia about the local origin
                    massData[i].inertia = massData[i].mass * (0.5f * circle.radius * circle.radius + Vector2.Dot(circle.offset, circle.offset));
                }
                else if (shape is BoxCollider2D || shape is PolygonCollider2D)
                {
                    var density = massData[i].mass / massData[i].area;

                    // Inertia tensor relative to the local origin (point s).
                    massData[i].inertia = density * massData[i].i;

                    // Shift to center of mass then to original body origin.
                    massData[i].inertia += massData[i].mass * (Vector2.Dot(massData[i].centroid, massData[i].centroid) - Vector2.Dot(massData[i].center, massData[i].center));
                }
            }
        }
コード例 #25
0
        public static List <Vertices> ConvexPartition(Vertices vertices, TriangulationAlgorithm algorithm, bool discardAndFixInvalid = true, float tolerance = 0.001f)
        {
            if (vertices.Count <= 3)
            {
                return new List <Vertices> {
                           vertices
                }
            }
            ;

            List <Vertices> results = null;

            switch (algorithm)
            {
            case TriangulationAlgorithm.Earclip:
#pragma warning disable 162
                // ReSharper disable three ConditionIsAlwaysTrueOrFalse
                if (Settings.SkipSanityChecks)
                {
                    Debug.Assert(!vertices.IsCounterClockWise(), "The Ear-clip algorithm expects the polygon to be clockwise.");
                }
                else
                {
                    if (vertices.IsCounterClockWise())
                    {
                        Vertices temp = new Vertices(vertices);
                        temp.Reverse();
                        results = EarclipDecomposer.ConvexPartition(temp, tolerance);
                    }
                    else
                    {
                        results = EarclipDecomposer.ConvexPartition(vertices, tolerance);
                    }
                }
                break;

            case TriangulationAlgorithm.Bayazit:
                if (Settings.SkipSanityChecks)
                {
                    Debug.Assert(vertices.IsCounterClockWise(), "The polygon is not counter clockwise. This is needed for Bayazit to work correctly.");
                }
                else
                {
                    if (!vertices.IsCounterClockWise())
                    {
                        Vertices temp = new Vertices(vertices);
                        temp.Reverse();
                        results = BayazitDecomposer.ConvexPartition(temp);
                    }
                    else
                    {
                        results = BayazitDecomposer.ConvexPartition(vertices);
                    }
                }
                break;

            case TriangulationAlgorithm.Flipcode:
                if (Settings.SkipSanityChecks)
                {
                    Debug.Assert(vertices.IsCounterClockWise(), "The polygon is not counter clockwise. This is needed for Bayazit to work correctly.");
                }
#pragma warning restore 162
                else
                {
                    if (!vertices.IsCounterClockWise())
                    {
                        Vertices temp = new Vertices(vertices);
                        temp.Reverse();
                        results = FlipcodeDecomposer.ConvexPartition(temp);
                    }
                    else
                    {
                        results = FlipcodeDecomposer.ConvexPartition(vertices);
                    }
                }
                break;

            case TriangulationAlgorithm.Seidel:
                results = SeidelDecomposer.ConvexPartition(vertices, tolerance);
                break;

            case TriangulationAlgorithm.SeidelTrapezoids:
                results = SeidelDecomposer.ConvexPartitionTrapezoid(vertices, tolerance);
                break;

            case TriangulationAlgorithm.Delauny:
                results = CDTDecomposer.ConvexPartition(vertices);
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(algorithm));
            }

            if (discardAndFixInvalid)
            {
                for (int i = results.Count - 1; i >= 0; i--)
                {
                    Vertices polygon = results[i];

                    if (!ValidatePolygon(polygon))
                    {
                        results.RemoveAt(i);
                    }
                }
            }

            return(results);
        }
コード例 #26
0
        public static Texture2D PolygonTexture(Vertices vertices, string pattern, Color mainColor, Color patternColor, Color outlineColor, float materialScale)
        {
            if (_assetCreator != null)
            {
                if (!_materials.ContainsKey(pattern))
                {
                    pattern = "blank";
                }

                // copy vertices
                Vertices scaledVertices = new Vertices(vertices);

                // scale to display units (i.e. pixels) for rendering to texture
                Vector2 scale = ConvertUnits.ToDisplayUnits(Vector2.One);
                scaledVertices.Scale(ref scale);

                // translate the boundingbox center to the texture center
                // because we use an orthographic projection for rendering later
                AABB verticesBounds = scaledVertices.GetCollisionBox();
                scaledVertices.Translate(-verticesBounds.Center);

                List <Vertices> decomposedVertices;
                if (!scaledVertices.IsConvex())
                {
                    decomposedVertices = EarclipDecomposer.ConvexPartition(scaledVertices);
                }
                else
                {
                    decomposedVertices = new List <Vertices>();
                    decomposedVertices.Add(scaledVertices);
                }

                List <VertexPositionColorTexture[]> verticesFill = new List <VertexPositionColorTexture[]>(decomposedVertices.Count);

                materialScale /= _materials[pattern].Width;

                for (int i = 0; i < decomposedVertices.Count; i++)
                {
                    verticesFill.Add(new VertexPositionColorTexture[3 * (decomposedVertices[i].Count - 2)]);
                    for (int j = 0; j < decomposedVertices[i].Count - 2; j++)
                    {
                        // fill vertices
                        verticesFill[i][3 * j].Position              = new Vector3(decomposedVertices[i][0], 0f);
                        verticesFill[i][3 * j + 1].Position          = new Vector3(decomposedVertices[i].NextVertex(j), 0f);
                        verticesFill[i][3 * j + 2].Position          = new Vector3(decomposedVertices[i].NextVertex(j + 1), 0f);
                        verticesFill[i][3 * j].TextureCoordinate     = decomposedVertices[i][0] * materialScale;
                        verticesFill[i][3 * j + 1].TextureCoordinate = decomposedVertices[i].NextVertex(j) * materialScale;
                        verticesFill[i][3 * j + 2].TextureCoordinate = decomposedVertices[i].NextVertex(j + 1) * materialScale;
                        verticesFill[i][3 * j].Color = verticesFill[i][3 * j + 1].Color = verticesFill[i][3 * j + 2].Color = mainColor;
                    }
                }

                // calculate outline
                VertexPositionColor[] verticesOutline = new VertexPositionColor[2 * scaledVertices.Count];
                for (int i = 0; i < scaledVertices.Count; i++)
                {
                    verticesOutline[2 * i].Position     = new Vector3(scaledVertices[i], 0f);
                    verticesOutline[2 * i + 1].Position = new Vector3(scaledVertices.NextVertex(i), 0f);
                    verticesOutline[2 * i].Color        = verticesOutline[2 * i + 1].Color = outlineColor;
                }

                Vector2 vertsSize = new Vector2(verticesBounds.UpperBound.X - verticesBounds.LowerBound.X, verticesBounds.UpperBound.Y - verticesBounds.LowerBound.Y);

                if (pattern == "blank")
                {
                    return(_assetCreator.RenderTexture((int)vertsSize.X, (int)vertsSize.Y, null, Color.Transparent, verticesFill, verticesOutline));
                }
                else
                {
                    return(_assetCreator.RenderTexture((int)vertsSize.X, (int)vertsSize.Y, _materials[pattern], patternColor, verticesFill, verticesOutline));
                }
            }
            return(null);
        }
コード例 #27
0
        /// <summary>
        /// Old relic before the soft time
        /// </summary>
        public override void CreateBody()
        {
            uint[] data = new uint[_cellTexture.Width * _cellTexture.Height];

            _cellTexture.GetData(data);

            //Find the vertices that makes up the outline of the shape in the texture
            Vertices textureVertices = PolygonTools.CreatePolygon(data, _cellTexture.Width, false);

            //The tool return vertices as they were found in the texture.
            //We need to find the real center (centroid) of the vertices for 2 reasons:

            //1. To translate the vertices so the polygon is centered around the centroid.
            Vector2 centroid = -textureVertices.GetCentroid();

            textureVertices.Translate(ref centroid);

            //2. To draw the texture the correct place.
            _origin = -centroid;
            _spriteDict[PlayerSprites.Cell].Origin = _origin;

            float scale = _spriteDict[PlayerSprites.Cell].Scale.X;

            foreach (PlayerSprites sprite in Enum.GetValues(typeof(PlayerSprites)))
            {
                if (sprite == PlayerSprites.Cell)
                {
                    continue;
                }
                else
                {
                    _spriteDict[sprite].Position -= _origin * scale;
                }
            }

            //We simplify the vertices found in the texture.
            textureVertices = SimplifyTools.ReduceByDistance(textureVertices, 4f);

            //Since it is a concave polygon, we need to partition it into several smaller convex polygons
            List <Vertices> list = EarclipDecomposer.ConvexPartition(textureVertices);

            //scale the vertices from graphics space to sim space
            Vector2 vertScale = ConvertUnits.ToSimUnits(new Vector2(1)) * scale;

            foreach (Vertices vertices in list)
            {
                vertices.Scale(ref vertScale);
            }

            //Create a single body with multiple fixtures
            Body                     = BodyFactory.CreateCompoundPolygon(PlayWindow.World, list, 1f, BodyType.Dynamic);
            Body.Position            = ConvertUnits.ToSimUnits(Position);
            Body.BodyType            = BodyType.Dynamic;
            Body.CollisionCategories = Category.Cat10;
            Body.CollidesWith        = Category.All;
            Body.OnCollision        += ObjectCollision;
            Body.Friction            = 0.1f;
            Body.FixedRotation       = true;
            Body.Mass                = 2f;
            Body.LinearDamping       = 1;
        }
コード例 #28
0
        internal Texture2D TextureFromVertices(Vertices vertices, Color color, float materialScale, Texture2D tex = null)
        {
            // copy vertices
            Vertices verts = new Vertices(vertices);

            // scale to display units (i.e. pixels) for rendering to texture
            //Vector2 scale = ConvertUnits.ToDisplayUnits(Vector2.One);
            //verts.Scale(ref scale);

            // translate the boundingbox center to the texture center
            // because we use an orthographic projection for rendering later
            AABB vertsBounds = verts.GetCollisionBox();

            verts.Translate(-vertsBounds.Center);

            List <Vertices> decomposedVerts;

            if (!verts.IsConvex())
            {
                decomposedVerts = EarclipDecomposer.ConvexPartition(verts);
            }
            else
            {
                decomposedVerts = new List <Vertices>();
                decomposedVerts.Add(verts);
            }
            List <VertexPositionColorTexture[]> verticesFill =
                new List <VertexPositionColorTexture[]>(decomposedVerts.Count);

            if (tex != null)
            {
                materialScale /= tex.Width;
            }

            for (int i = 0; i < decomposedVerts.Count; ++i)
            {
                verticesFill.Add(new VertexPositionColorTexture[3 * (decomposedVerts[i].Count - 2)]);
                for (int j = 0; j < decomposedVerts[i].Count - 2; ++j)
                {
                    // fill vertices
                    verticesFill[i][3 * j].Position              = new Vector3(decomposedVerts[i][0], 0f);
                    verticesFill[i][3 * j + 1].Position          = new Vector3(decomposedVerts[i].NextVertex(j), 0f);
                    verticesFill[i][3 * j + 2].Position          = new Vector3(decomposedVerts[i].NextVertex(j + 1), 0f);
                    verticesFill[i][3 * j].TextureCoordinate     = decomposedVerts[i][0] * materialScale;
                    verticesFill[i][3 * j + 1].TextureCoordinate = decomposedVerts[i].NextVertex(j) * materialScale;
                    verticesFill[i][3 * j + 2].TextureCoordinate = decomposedVerts[i].NextVertex(j + 1) * materialScale;
                    verticesFill[i][3 * j].Color         =
                        verticesFill[i][3 * j + 1].Color = verticesFill[i][3 * j + 2].Color = color;
                }
            }

            // calculate outline
            VertexPositionColor[] verticesOutline = new VertexPositionColor[2 * verts.Count];
            for (int i = 0; i < verts.Count; ++i)
            {
                verticesOutline[2 * i].Position     = new Vector3(verts[i], 0f);
                verticesOutline[2 * i + 1].Position = new Vector3(verts.NextVertex(i), 0f);
                verticesOutline[2 * i].Color        = verticesOutline[2 * i + 1].Color = Color.Black;
            }

            Vector2 vertsSize = new Vector2(vertsBounds.UpperBound.X - vertsBounds.LowerBound.X,
                                            vertsBounds.UpperBound.Y - vertsBounds.LowerBound.Y);

            return(RenderTexture((int)vertsSize.X, (int)vertsSize.Y,
                                 tex, verticesFill, verticesOutline, tex == null));
        }