/// <summary> /// Decompose the polygon into several smaller non-concave polygons. /// </summary> /// <param name="vertices">The polygon to decompose.</param> /// <param name="sheer">The sheer to use if you get bad results, try using a higher value.</param> /// <returns>A list of triangles</returns> public static List<Vertices> ConvexPartition(Vertices vertices, float sheer = 0.001f) { Debug.Assert(vertices.Count > 3); List<Point> compatList = new List<Point>(vertices.Count); foreach (Vector2 vertex in vertices) { compatList.Add(new Point(vertex.X, vertex.Y)); } Triangulator t = new Triangulator(compatList, sheer); List<Vertices> list = new List<Vertices>(); foreach (List<Point> triangle in t.Triangles) { Vertices outTriangles = new Vertices(triangle.Count); foreach (Point outTriangle in triangle) { outTriangles.Add(new Vector2(outTriangle.X, outTriangle.Y)); } list.Add(outTriangles); } return list; }
public RectanglePhysicsComponent(Engine engine, Rectangle rectangle, Vector2 gameWorldPosition, bool dynamic) : base(engine) { // create vertices to create a rectangle in the physics world with Vertices vertices = new Vertices(); vertices.Add(Engine.Physics.PositionToPhysicsWorld(new Vector2(rectangle.Left, rectangle.Top))); vertices.Add(Engine.Physics.PositionToPhysicsWorld(new Vector2(rectangle.Right, rectangle.Top))); vertices.Add(Engine.Physics.PositionToPhysicsWorld(new Vector2(rectangle.Right, rectangle.Bottom))); vertices.Add(Engine.Physics.PositionToPhysicsWorld(new Vector2(rectangle.Left, rectangle.Bottom))); MainFixture = FixtureFactory.CreatePolygon(Engine.Physics.World, vertices, 1.0f); MainFixture.Body.Position = Engine.Physics.PositionToPhysicsWorld(gameWorldPosition); if (dynamic) { MainFixture.Body.BodyType = BodyType.Dynamic; } else { MainFixture.Body.BodyType = BodyType.Static; } MainFixture.Restitution = 0.5f; // adding some linear damping gives a max speed and seems to smooth out player motion really well MainFixture.Body.LinearDamping = 1.0f; }
public NetworkCollisionRemnant(Vector2 position, float size, float angleOfStartForce, int ownerId, Color color, World world, Player creator) : base(position, size, color, null, creator) { OwnerId = ownerId; body = BodyFactory.CreateBody(world); body.BodyType = BodyType.Dynamic; body.Position = ConvertUnits.ToSimUnits(position); body.FixedRotation = true; body.LinearDamping = 0.8f; //Create the vertices that will create the collision shape Vertices verts = new Vertices(); verts.Add(new Vector2(-ConvertUnits.ToSimUnits(size / 2f), ConvertUnits.ToSimUnits(size / 2f))); verts.Add(new Vector2(-ConvertUnits.ToSimUnits(size / 2f), -ConvertUnits.ToSimUnits(size / 2f))); verts.Add(new Vector2(ConvertUnits.ToSimUnits(size / 2f), -ConvertUnits.ToSimUnits(size / 2f))); verts.Add(new Vector2(ConvertUnits.ToSimUnits(size / 2f), ConvertUnits.ToSimUnits(size / 2f))); //Create the shape and attach it to the body PolygonShape s = new PolygonShape(verts, 0); body.CreateFixture(s); body.FixtureList[0].IsSensor = true; body.UserData = this; body.CollidesWith = Category.Cat2; body.CollisionCategories = Category.Cat2; //body.OnSeparation += body_OnSeparation; body.ApplyLinearImpulse(new Vector2((float)Math.Cos(angleOfStartForce),(float)Math.Sin(angleOfStartForce)) * 10f); }
public Platform(float width, float height, Vector2 position, string name, bool slopeDirection) : base(position, name, "Slope") { Vector2 bottomLeft = new Vector2(-width/2, height/2) / Camera.PixelsPerMeter; Vector2 bottomRight = new Vector2(width / 2, height / 2) / Camera.PixelsPerMeter; Vector2 top = Vector2.Zero; if (slopeDirection) //SLOPE //Remove top left vertex { top = new Vector2(width / 2, -height / 2) / Camera.PixelsPerMeter; } else //INVERSLOPE //Remove top right vertex { top = new Vector2(-width / 2, -height / 2) / Camera.PixelsPerMeter; } Vertices vertices = new Vertices(3); vertices.Add(top); vertices.Add(bottomRight); vertices.Add(bottomLeft); Body body = BodyFactory.CreatePolygon(GameManager.game.world, vertices, 1f, position/ Camera.PixelsPerMeter); body.IsStatic = true; body.Restitution = 0f; body.Friction = 0.5f; this.AddBody(body); }
public Goalie(World world, GoalieData spawn) { var body = new Body(world); var angle = spawn.End - spawn.Begin; body.Rotation = FMath.Atan2(angle.Y, angle.X); segment.A = spawn.Begin; segment.B = spawn.End; var normal = new Vector2(-angle.Y, angle.X); normal.Normalize(); delta = normal * .5f; segmentOut.A = spawn.Begin + delta; segmentOut.B = spawn.End + delta; segmentIn.A = spawn.Begin - delta; segmentIn.B = spawn.End - delta; body.Position = spawn.Begin; var verts = new Vertices(); verts.Add(new Vector2(left, bottom)); verts.Add(new Vector2(right, bottom)); verts.Add(new Vector2(right, top)); verts.Add(new Vector2(left, top)); var shape = new PolygonShape(verts, 1f); body.FixedRotation = true; body.BodyType = BodyType.Dynamic; Fixture = body.CreateFixture(shape); }
public SquareStack(Vector2 pos, Vector2 size, Vector2 subSize, float rot, SpriteBatch batch, Texture2D texture, World world) : base(pos, batch, texture, world) { this.size = size; this.subSize = subSize; this.rot = rot; this.texture = texture; this.color = Color.Green; this.spriteOrigin = new Vector2(texture.Width / 2, texture.Height / 2); this.backCol = new Color(color.R / 2, color.G / 2, color.B / 2); rMat = Matrix.CreateRotationZ(rot); if (Settings.MaxPolygonVertices < 24) Settings.MaxPolygonVertices = 24; Vector2 leftTop = Vector2.Transform(new Vector2(-size.X / 2, -size.Y / 2), rMat); Vector2 rightTop = Vector2.Transform(new Vector2(size.X / 2, -size.Y / 2), rMat); Vector2 leftBottom = Vector2.Transform(new Vector2(-size.X / 2, size.Y / 2), rMat); Vector2 rightBottom = Vector2.Transform(new Vector2(size.X / 2, size.Y / 2), rMat); Vertices verts = new Vertices(); verts.Add(leftTop); verts.Add(rightTop); verts.Add(rightBottom); verts.Add(leftBottom); FixtureFactory.AttachPolygon(verts, density, body); this.width = max(max(leftTop.X, rightTop.X), max(leftBottom.X, rightBottom.X)) - min(min(leftTop.X, rightTop.X), min(leftBottom.X, rightBottom.X)); this.height = max(max(leftTop.Y, rightTop.Y), max(leftBottom.Y, rightBottom.Y)) - min(min(leftTop.Y, rightTop.Y), min(leftBottom.Y, rightBottom.Y)); }
public Border(World world, ScreenManager screenManager, Camera2D camera) { _screenManager = screenManager; _camera = camera; float halfWidth = ConvertUnits.ToSimUnits(screenManager.GraphicsDevice.Viewport.Width) / 2f - 0.75f; float halfHeight = ConvertUnits.ToSimUnits(screenManager.GraphicsDevice.Viewport.Height) / 2f - 0.75f; Vertices borders = new Vertices(4); borders.Add(new Vector2(-halfWidth, halfHeight)); borders.Add(new Vector2(halfWidth, halfHeight)); borders.Add(new Vector2(halfWidth, -halfHeight)); borders.Add(new Vector2(-halfWidth, -halfHeight)); _anchor = BodyFactory.CreateLoopShape(world, borders); _anchor.CollisionCategories = Category.All; _anchor.CollidesWith = Category.All; _basicEffect = new BasicEffect(screenManager.GraphicsDevice); _basicEffect.VertexColorEnabled = true; _basicEffect.TextureEnabled = true; _basicEffect.Texture = screenManager.Content.Load<Texture2D>("Materials/pavement"); VertexPositionColorTexture[] vertice = new VertexPositionColorTexture[8]; vertice[0] = new VertexPositionColorTexture(new Vector3(-halfWidth, -halfHeight, 0f), Color.LightGray, new Vector2(-halfWidth, -halfHeight) / 5.25f); vertice[1] = new VertexPositionColorTexture(new Vector3(halfWidth, -halfHeight, 0f), Color.LightGray, new Vector2(halfWidth, -halfHeight) / 5.25f); vertice[2] = new VertexPositionColorTexture(new Vector3(halfWidth, halfHeight, 0f), Color.LightGray, new Vector2(halfWidth, halfHeight) / 5.25f); vertice[3] = new VertexPositionColorTexture(new Vector3(-halfWidth, halfHeight, 0f), Color.LightGray, new Vector2(-halfWidth, halfHeight) / 5.25f); vertice[4] = new VertexPositionColorTexture(new Vector3(-halfWidth - 2f, -halfHeight - 2f, 0f), Color.LightGray, new Vector2(-halfWidth - 2f, -halfHeight - 2f) / 5.25f); vertice[5] = new VertexPositionColorTexture(new Vector3(halfWidth + 2f, -halfHeight - 2f, 0f), Color.LightGray, new Vector2(halfWidth + 2f, -halfHeight - 2f) / 5.25f); vertice[6] = new VertexPositionColorTexture(new Vector3(halfWidth + 2f, halfHeight + 2f, 0f), Color.LightGray, new Vector2(halfWidth + 2f, halfHeight + 2f) / 5.25f); vertice[7] = new VertexPositionColorTexture(new Vector3(-halfWidth - 2f, halfHeight + 2f, 0f), Color.LightGray, new Vector2(-halfWidth - 2f, halfHeight + 2f) / 5.25f); _borderVerts = new VertexPositionColorTexture[24]; _borderVerts[0] = vertice[0]; _borderVerts[1] = vertice[5]; _borderVerts[2] = vertice[4]; _borderVerts[3] = vertice[0]; _borderVerts[4] = vertice[1]; _borderVerts[5] = vertice[5]; _borderVerts[6] = vertice[1]; _borderVerts[7] = vertice[6]; _borderVerts[8] = vertice[5]; _borderVerts[9] = vertice[1]; _borderVerts[10] = vertice[2]; _borderVerts[11] = vertice[6]; _borderVerts[12] = vertice[2]; _borderVerts[13] = vertice[7]; _borderVerts[14] = vertice[6]; _borderVerts[15] = vertice[2]; _borderVerts[16] = vertice[3]; _borderVerts[17] = vertice[7]; _borderVerts[18] = vertice[3]; _borderVerts[19] = vertice[4]; _borderVerts[20] = vertice[7]; _borderVerts[21] = vertice[3]; _borderVerts[22] = vertice[0]; _borderVerts[23] = vertice[4]; }
private static Vertices MakeVertices(Vector2 sz) { Vertices v = new Vertices(); v.Add(new Vector2(0, 0)); v.Add(new Vector2(sz.X, 0)); v.Add(new Vector2(sz.X, sz.Y)); v.Add(new Vector2(0,sz.Y)); return v; }
/// <summary> /// Build vertices to represent an axis-aligned box. /// </summary> /// <param name="hx">the half-width.</param> /// <param name="hy">the half-height.</param> public static Vertices CreateRectangle(float hx, float hy) { Vertices vertices = new Vertices(4); vertices.Add(new Vector2(-hx, -hy)); vertices.Add(new Vector2(hx, -hy)); vertices.Add(new Vector2(hx, hy)); vertices.Add(new Vector2(-hx, hy)); return vertices; }
private RevoluteTest() { //Ground Body ground = BodyFactory.CreateEdge(World, new Vector2(-40.0f, 0.0f), new Vector2(40.0f, 0.0f)); { Body bodyB = BodyFactory.CreateCircle(World, 0.5f, 5f, new Vector2(-10.0f, 20.0f)); bodyB.BodyType = BodyType.Dynamic; const float w = 100.0f; bodyB.AngularVelocity = w; bodyB.LinearVelocity = new Vector2(-8.0f * w, 0.0f); _joint = new RevoluteJoint(ground, bodyB, new Vector2(-10.0f, 12.0f), true); _joint.MotorSpeed = 1.0f * Settings.Pi; _joint.MaxMotorTorque = 10000.0f; _joint.MotorEnabled = false; _joint.LowerLimit = -0.25f * Settings.Pi; _joint.UpperLimit = 0.5f * Settings.Pi; _joint.LimitEnabled = true; _joint.CollideConnected = true; World.AddJoint(_joint); } { Body ball = BodyFactory.CreateCircle(World, 3.0f, 5.0f, new Vector2(5.0f, 30.0f)); ball.BodyType = BodyType.Dynamic; ball.CollisionCategories = Category.Cat1; Vertices polygonVertices = PolygonTools.CreateRectangle(10.0f, 0.2f, new Vector2(-10.0f, 0.0f), 0.0f); Body polygonBody = BodyFactory.CreatePolygon(World, polygonVertices, 2, new Vector2(20, 10)); polygonBody.BodyType = BodyType.Dynamic; polygonBody.IsBullet = true; RevoluteJoint joint = new RevoluteJoint(ground, polygonBody, new Vector2(20, 10), true); joint.LowerLimit = -0.25f * Settings.Pi; joint.UpperLimit = 0.0f * Settings.Pi; joint.LimitEnabled = true; World.AddJoint(joint); } // Tests mass computation of a small object far from the origin { Vertices verts = new Vertices(3); verts.Add(new Vector2(17.63f, 36.31f)); verts.Add(new Vector2(17.52f, 36.69f)); verts.Add(new Vector2(17.19f, 36.36f)); Body polyShape = BodyFactory.CreatePolygon(World, verts, 1); polyShape.BodyType = BodyType.Dynamic; } }
private void CreateBorder(float width, float height, float borderWidth) { width = Math.Abs(width); height = Math.Abs(height); _anchor = BodyFactory.CreateBody(_world); left = BodyFactory.CreateBody(_world); right = BodyFactory.CreateBody(_world); up = BodyFactory.CreateBody(_world); down = BodyFactory.CreateBody(_world); UserData userData = new UserData(-1, 3, true); Vertices vert = new Vertices(); // top // counterclockwise Vertices vup = new Vertices(); vup.Add(new Vector2(0, 10)); vup.Add(new Vector2(0, 0)); vup.Add(new Vector2(1000, 0)); vup.Add(new Vector2(1000, 10)); up.CreateFixture(new PolygonShape(vup, 0.0f), userData); //Bottom down.CreateFixture(new PolygonShape(vup, 0.0f), userData); down.Position = new Vector2(0, 990); //Left Vertices vl = new Vertices(); vl.Add(new Vector2(0, 1000)); vl.Add(new Vector2(0, 0)); vl.Add(new Vector2(10, 0)); vl.Add(new Vector2(10, 1000)); left.CreateFixture(new PolygonShape(vl, 0.0f), userData); //Right right.CreateFixture(new PolygonShape(vl, 0.0f), userData); right.Position = new Vector2(990, 0); foreach (Fixture t in _anchor.FixtureList) { t.CollisionFilter.CollisionCategories = Category.All; t.CollisionFilter.CollidesWith = Category.All; t.Friction = _frictionValue; t.Restitution = _bouncyValue; } ContentManager content = Master.theMaster.game.Content; topBorder = content.Load<Texture2D>("images/BoarderHorizontal"); bottomBorder = content.Load<Texture2D>("images/BoarderHorizontal"); rightBorder = content.Load<Texture2D>("images/BoarderVertical"); leftBorder = content.Load<Texture2D>("images/BoarderVertical"); }
public void InitBorders() { Vertices borders = new Vertices(4); borders.Add(new Vector2(0, 0)); borders.Add(new Vector2(width, 0)); borders.Add(new Vector2(width, height)); borders.Add(new Vector2(0, height)); borderBody = BodyFactory.CreateLoopShape(_world, borders); borderBody.CollisionCategories = Category.All; borderBody.CollidesWith = Category.All; }
public void addQuad(World world, WallCompiled wall, int a, int b) { var verts = new Vertices(4); verts.Add(wall.Verts1[a]); verts.Add(wall.Verts4[a]); verts.Add(wall.Verts4[b]); verts.Add(wall.Verts1[b]); var wallBody = new Body(world); var wallShape = new PolygonShape(verts, 1f); Fixtures[a] = wallBody.CreateFixture(wallShape); Fixtures[a].Friction = 0f; }
private void CreateBodyFixture() { //Create the vertices that will create the collision shape Vertices verts = new Vertices(); verts.Add(new Vector2(-ConvertUnits.ToSimUnits(size / 2f), ConvertUnits.ToSimUnits(size / 2f))); verts.Add(new Vector2(-ConvertUnits.ToSimUnits(size / 2f), -ConvertUnits.ToSimUnits(size / 2f))); verts.Add(new Vector2(ConvertUnits.ToSimUnits(size / 2f), -ConvertUnits.ToSimUnits(size / 2f))); verts.Add(new Vector2(ConvertUnits.ToSimUnits(size / 2f), ConvertUnits.ToSimUnits(size / 2f))); //Create the shape and attach it to the body PolygonShape s = new PolygonShape(verts, 0); body.CreateFixture(s); body.FixtureList[0].IsSensor = true; }
public Entity BuildEntity(Entity e, params object[] args) { e.Tag = "Chassis"; #region Body Body Chassis = e.AddComponent<Body>(new Body(_World, e)); { Vertices vertices = new Vertices(8); vertices.Add(new Vector2(-2.5f, 0.08f)); vertices.Add(new Vector2(-2.375f, -0.46f)); vertices.Add(new Vector2(-0.58f, -0.92f)); vertices.Add(new Vector2(0.46f, -0.92f)); vertices.Add(new Vector2(2.5f, -0.17f)); vertices.Add(new Vector2(2.5f, 0.205f)); vertices.Add(new Vector2(2.3f, 0.33f)); vertices.Add(new Vector2(-2.25f, 0.35f)); PolygonShape chassisShape = new PolygonShape(vertices, 2f); Chassis.BodyType = BodyType.Dynamic; Chassis.Position = new Vector2(0.0f, -1.0f); Chassis.CreateFixture(chassisShape); } #endregion #region Sprite e.AddComponent<Sprite>(new Sprite(args[0] as Texture2D, (Rectangle)args[1], Chassis, 1, Color.White, 0f)); #endregion return e; }
public void CreateCollisionRectangle(Rectangle rectangle, Vector2 position) { Vertices vertices = new Vertices(); vertices.Add(Engine.Physics.PositionToPhysicsWorld(new Vector2(rectangle.Left, rectangle.Top))); vertices.Add(Engine.Physics.PositionToPhysicsWorld(new Vector2(rectangle.Right, rectangle.Top))); vertices.Add(Engine.Physics.PositionToPhysicsWorld(new Vector2(rectangle.Right, rectangle.Bottom))); vertices.Add(Engine.Physics.PositionToPhysicsWorld(new Vector2(rectangle.Left, rectangle.Bottom))); Fixture fixture = FixtureFactory.CreatePolygon(Engine.Physics.World, vertices, 1.0f); fixture.Body.Position = position; fixture.Body.BodyType = BodyType.Static; fixture.Restitution = 0.0f; fixture.CollisionFilter.CollisionCategories = (Category)Global.CollisionCategories.Structure; }
private RayCastTest() { { Vertices vertices = new Vertices(3); vertices.Add(new Vector2(-0.5f, 0.0f)); vertices.Add(new Vector2(0.5f, 0.0f)); vertices.Add(new Vector2(0.0f, 1.5f)); _polygons[0] = new PolygonShape(vertices, 1); } { Vertices vertices2 = new Vertices(3); vertices2.Add(new Vector2(-0.1f, 0.0f)); vertices2.Add(new Vector2(0.1f, 0.0f)); vertices2.Add(new Vector2(0.0f, 1.5f)); _polygons[1] = new PolygonShape(vertices2, 1); } { const float w = 1.0f; float b = w / (2.0f + (float)Math.Sqrt(2.0)); float s = (float)Math.Sqrt(2.0) * b; Vertices vertices3 = new Vertices(8); vertices3.Add(new Vector2(0.5f * s, 0.0f)); vertices3.Add(new Vector2(0.5f * w, b)); vertices3.Add(new Vector2(0.5f * w, b + s)); vertices3.Add(new Vector2(0.5f * s, w)); vertices3.Add(new Vector2(-0.5f * s, w)); vertices3.Add(new Vector2(-0.5f * w, b + s)); vertices3.Add(new Vector2(-0.5f * w, b)); vertices3.Add(new Vector2(-0.5f * s, 0.0f)); _polygons[2] = new PolygonShape(vertices3, 1); } { _polygons[3] = new PolygonShape(1); _polygons[3].Vertices = PolygonTools.CreateRectangle(0.5f, 0.5f); } { _circle = new CircleShape(0.5f, 1); } _bodyIndex = 0; _angle = 0.0f; _mode = RayCastMode.Closest; }
public void InitializePhysics(World world) { Body body = new Body(world); Vertices verts = new Vertices(); if (!IsStair) verts.Add(new Vector2(ConvertUnits.ToSimUnits(Bounds.X), ConvertUnits.ToSimUnits(Bounds.Y))); verts.Add(new Vector2(ConvertUnits.ToSimUnits(Bounds.X + Bounds.Width), ConvertUnits.ToSimUnits(Bounds.Y))); verts.Add(new Vector2(ConvertUnits.ToSimUnits(Bounds.X + Bounds.Width), ConvertUnits.ToSimUnits(Bounds.Y + Bounds.Height))); verts.Add(new Vector2(ConvertUnits.ToSimUnits(Bounds.X), ConvertUnits.ToSimUnits(Bounds.Y + Bounds.Height))); body.CreateFixture(new PolygonShape(verts, 0)); body.Friction = 0.40f; Bodies = new List<Body>(); Bodies.Add(body); }
public override void Placed() { placed = true; dragable = false; //reset color color = Color.White; //Compute Vertices top = new Vector2((float)position.X, (float)position.Y - (float)size.Y / 2f); bottomLeft = new Vector2((float)position.X - (float)size.X / 2f, (float)position.Y + (float)size.Y / 2f); bottomRight = new Vector2((float)position.X + (float)size.X / 2f, (float)position.Y + (float)size.Y / 2f); //initialize body physics parameters Vertices vertices = new Vertices(); vertices.Add(UnitConverter.toSimSpace(top)); vertices.Add(UnitConverter.toSimSpace(bottomLeft)); vertices.Add(UnitConverter.toSimSpace(bottomRight)); brickBody = BodyFactory.CreatePolygon(Game1.world, vertices, 1.0f, "TriangleBrick"); //brickBody = BodyFactory.CreateRectangle(Game1.world, UnitConverter.toSimSpace(brickWidth), UnitConverter.toSimSpace(brickHeight), 1.0f, UnitConverter.toSimSpace(position)); brickBody.BodyType = BodyType.Static; brickBody.OnCollision += BrickBody_OnCollision; brickBody.Restitution = 0.1f; brickBody.AngularDamping = 20; brickBody.Friction = 0.5f; }
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(); }
/// <summary> /// Create a new chainshape from the vertices. /// </summary> /// <param name="vertices">The vertices to use. Must contain 2 or more vertices.</param> /// <param name="createLoop">Set to true to create a closed loop. It connects the first vertice to the last, and automatically adjusts connectivity to create smooth collisions along the chain.</param> public ChainShape(Vertices vertices, bool createLoop = false) : base(0) { ShapeType = ShapeType.Chain; _radius = Settings.PolygonRadius; Debug.Assert(vertices != null && vertices.Count >= 3); Debug.Assert(vertices[0] != vertices[vertices.Count - 1]); // FPE. See http://www.box2d.org/forum/viewtopic.php?f=4&t=7973&p=35363 for (int i = 1; i < vertices.Count; ++i) { Vector2 v1 = vertices[i - 1]; Vector2 v2 = vertices[i]; // If the code crashes here, it means your vertices are too close together. Debug.Assert(Vector2.DistanceSquared(v1, v2) > Settings.LinearSlop * Settings.LinearSlop); } Vertices = new Vertices(vertices); if (createLoop) { Vertices.Add(vertices[0]); PrevVertex = Vertices[Vertices.Count - 2]; //FPE: We use the properties instead of the private fields here. NextVertex = Vertices[1]; //FPE: We use the properties instead of the private fields here. } }
/// <summary> /// Removes all collinear points on the polygon. /// </summary> /// <param name="vertices">The polygon that needs simplification.</param> /// <param name="collinearityTolerance">The collinearity tolerance.</param> /// <returns>A simplified polygon.</returns> public static Vertices CollinearSimplify(Vertices vertices, float collinearityTolerance) { //We can't simplify polygons under 3 vertices if (vertices.Count < 3) return vertices; Vertices simplified = new Vertices(); for (int i = 0; i < vertices.Count; i++) { int prevId = vertices.PreviousIndex(i); int nextId = vertices.NextIndex(i); Vector2 prev = vertices[prevId]; Vector2 current = vertices[i]; Vector2 next = vertices[nextId]; //If they collinear, continue if (MathUtils.Collinear(ref prev, ref current, ref next, collinearityTolerance)) continue; simplified.Add(current); } return simplified; }
private ConvexHullTest2() { _pointCloud1 = new Vertices(32); for (int i = 0; i < 32; i++) { float x = Rand.RandomFloat(-10, 10); float y = Rand.RandomFloat(-10, 10); _pointCloud1.Add(new Vector2(x, y)); } _pointCloud2 = new Vertices(_pointCloud1); _pointCloud3 = new Vertices(_pointCloud1); //Melkman DOES NOT work on point clouds. It only works on simple polygons. _pointCloud1.Translate(new Vector2(-20, 30)); _melkman = Melkman.GetConvexHull(_pointCloud1); //Giftwrap works on point clouds _pointCloud2.Translate(new Vector2(20, 30)); _giftWrap = GiftWrap.GetConvexHull(_pointCloud2); _pointCloud3.Translate(new Vector2(20, 10)); _chainHull = ChainHull.GetConvexHull(_pointCloud3); }
public PathTile(List<Vector2> localPoints, Vector2 position, World world, bool MakroCollision = false) { body = new Body(world); body.Position = ConvertUnits.ToSimUnits(position); body.UserData = "Wall"; body.IsStatic = true; Vertices terrain = new Vertices(); foreach (Vector2 point in localPoints) { terrain.Add(ConvertUnits.ToSimUnits(point)); } for (int i = 0; i < terrain.Count - 1; ++i) { FixtureFactory.AttachEdge(terrain[i], terrain[i + 1], body); body.FixtureList[i].UserData = "Wall"; } body.Restitution = 0f; body.Friction = float.MaxValue; if (!MakroCollision) body.CollisionCategories = Category.Cat15 & ~Category.Cat3; else body.CollidesWith = Category.Cat29; }
//Rounded rectangle contributed by Jonathan Smars - [email protected] /// <summary> /// Creates a rounded rectangle with the specified width and height. /// </summary> /// <param name="width">The width.</param> /// <param name="height">The height.</param> /// <param name="xRadius">The rounding X radius.</param> /// <param name="yRadius">The rounding Y radius.</param> /// <param name="segments">The number of segments to subdivide the edges.</param> /// <returns></returns> public static Vertices CreateRoundedRectangle(float width, float height, float xRadius, float yRadius, int segments) { if (yRadius > height / 2 || xRadius > width / 2) throw new Exception("Rounding amount can't be more than half the height and width respectively."); if (segments < 0) throw new Exception("Segments must be zero or more."); //We need at least 8 vertices to create a rounded rectangle Debug.Assert(Settings.MaxPolygonVertices >= 8); Vertices vertices = new Vertices(); if (segments == 0) { vertices.Add(new Vector2(width * .5f - xRadius, -height * .5f)); vertices.Add(new Vector2(width * .5f, -height * .5f + yRadius)); vertices.Add(new Vector2(width * .5f, height * .5f - yRadius)); vertices.Add(new Vector2(width * .5f - xRadius, height * .5f)); vertices.Add(new Vector2(-width * .5f + xRadius, height * .5f)); vertices.Add(new Vector2(-width * .5f, height * .5f - yRadius)); vertices.Add(new Vector2(-width * .5f, -height * .5f + yRadius)); vertices.Add(new Vector2(-width * .5f + xRadius, -height * .5f)); } else { int numberOfEdges = (segments * 4 + 8); float stepSize = MathHelper.TwoPi / (numberOfEdges - 4); int perPhase = numberOfEdges / 4; Vector2 posOffset = new Vector2(width / 2 - xRadius, height / 2 - yRadius); vertices.Add(posOffset + new Vector2(xRadius, -yRadius + yRadius)); short phase = 0; for (int i = 1; i < numberOfEdges; i++) { if (i - perPhase == 0 || i - perPhase * 3 == 0) { posOffset.X *= -1; phase--; } else if (i - perPhase * 2 == 0) { posOffset.Y *= -1; phase--; } vertices.Add(posOffset + new Vector2(xRadius * (float)Math.Cos(stepSize * -(i + phase)), -yRadius * (float)Math.Sin(stepSize * -(i + phase)))); } } return vertices; }
/// <summary> /// Adds the vertices. /// </summary> /// <param name="vertices">The vertices.</param> /// <param name="position">The position.</param> /// <returns>the combined vertices</returns> public static Vertices AddVectorToVertices( Vertices vertices, Vector2 position ) { Vertices verts = new Vertices( vertices.Count ); for ( int i = 0; i < vertices.Count; i++ ) { verts.Add( vertices[ i ] + ConvertUnits.ToSimUnits( position ) ); } return verts; }
public Border(World world, Vector2 worldSize) { float simWidth = ConvertUnits.ToSimUnits(worldSize.X); float simHeight = ConvertUnits.ToSimUnits(worldSize.Y); Corners = new Vertices(4); Corners.Add(new Vector2(0f, 0f)); Corners.Add(new Vector2(simWidth, 0f)); Corners.Add(new Vector2(simWidth, simHeight)); Corners.Add(new Vector2(0f, simHeight)); _anchor = BodyFactory.CreateLoopShape(world, Corners); _anchor.CollisionCategories = (Category)CharacterEntity.CollisionCategory.Environment; _anchor.CollidesWith = (Category)CharacterEntity.CollidesWith.Environment; }
/// <summary> /// Initialize the proxy using the given shape. The shape /// must remain in scope while the proxy is in use. /// </summary> /// <param name="shape">The shape.</param> /// <param name="index">The index.</param> public void Set(Shape shape, int index) { switch (shape.ShapeType) { case ShapeType.Circle: { CircleShape circle = (CircleShape) shape; Vertices = new Vertices(1); Vertices.Add(circle.Position); Radius = circle.Radius; } break; case ShapeType.Polygon: { PolygonShape polygon = (PolygonShape) shape; Vertices = polygon.Vertices; Radius = polygon.Radius; } break; case ShapeType.Loop: { LoopShape loop = (LoopShape) shape; Debug.Assert(0 <= index && index < loop.Vertices.Count); Buffer[0] = loop.Vertices[index]; if (index + 1 < loop.Vertices.Count) { Buffer[1] = loop.Vertices[index + 1]; } else { Buffer[1] = loop.Vertices[0]; } Vertices = new Vertices(2); Vertices.Add(Buffer[0]); Vertices.Add(Buffer[1]); Radius = loop.Radius; } break; case ShapeType.Edge: { EdgeShape edge = (EdgeShape) shape; Vertices = new Vertices(2); Vertices.Add(edge.Vertex1); Vertices.Add(edge.Vertex2); Radius = edge.Radius; } break; default: Debug.Assert(false); break; } }
//methods public void Add(Vertex element) { Vertices?.Add(element); element.Id = IdVertexesCounter; IdVertexesCounter++; AdjacencyMatrix.AddVertex(); }
/// Create a loop. This automatically adjusts connectivity. public void CreateLoop(Vertices vertices) { Debug.Assert(vertices.Count >= 3); Vertices = new Vertices(vertices); Vertices.Add(vertices[0]); _prevVertex = Vertices[Vertices.Count - 2]; _nextVertex = Vertices[1]; _hasPrevVertex = true; _hasNextVertex = true; }
public Border(World world, PhysicsGameScreen screen, Viewport viewport) { _world = world; _screen = screen; float halfWidth = ConvertUnits.ToSimUnits(viewport.Width) / 2f - 0.75f; float halfHeight = ConvertUnits.ToSimUnits(viewport.Height) / 2f - 0.75f; Vertices borders = new Vertices(4); borders.Add(new Vector2(-halfWidth, halfHeight)); borders.Add(new Vector2(halfWidth, halfHeight)); borders.Add(new Vector2(halfWidth, -halfHeight)); borders.Add(new Vector2(-halfWidth, -halfHeight)); _anchor = BodyFactory.CreateLoopShape(_world, borders); _anchor.CollisionCategories = Category.All; _anchor.CollidesWith = Category.All; _anchor.AngularDamping = 0; _anchor.Friction = 0; _anchor.Restitution = 1; _basicEffect = new BasicEffect(_screen.ScreenManager.GraphicsDevice) { VertexColorEnabled = true, TextureEnabled = true, Texture = this._screen.ScreenManager.Content.Load <Texture2D>("Materials/pavement") }; VertexPositionColorTexture[] vertice = new VertexPositionColorTexture[8]; vertice[0] = new VertexPositionColorTexture(new Vector3(-halfWidth, -halfHeight, 0f), Color.LightGray, new Vector2(-halfWidth, -halfHeight) / 5.25f); vertice[1] = new VertexPositionColorTexture(new Vector3(halfWidth, -halfHeight, 0f), Color.LightGray, new Vector2(halfWidth, -halfHeight) / 5.25f); vertice[2] = new VertexPositionColorTexture(new Vector3(halfWidth, halfHeight, 0f), Color.LightGray, new Vector2(halfWidth, halfHeight) / 5.25f); vertice[3] = new VertexPositionColorTexture(new Vector3(-halfWidth, halfHeight, 0f), Color.LightGray, new Vector2(-halfWidth, halfHeight) / 5.25f); vertice[4] = new VertexPositionColorTexture(new Vector3(-halfWidth - 2f, -halfHeight - 2f, 0f), Color.LightGray, new Vector2(-halfWidth - 2f, -halfHeight - 2f) / 5.25f); vertice[5] = new VertexPositionColorTexture(new Vector3(halfWidth + 2f, -halfHeight - 2f, 0f), Color.LightGray, new Vector2(halfWidth + 2f, -halfHeight - 2f) / 5.25f); vertice[6] = new VertexPositionColorTexture(new Vector3(halfWidth + 2f, halfHeight + 2f, 0f), Color.LightGray, new Vector2(halfWidth + 2f, halfHeight + 2f) / 5.25f); vertice[7] = new VertexPositionColorTexture(new Vector3(-halfWidth - 2f, halfHeight + 2f, 0f), Color.LightGray, new Vector2(-halfWidth - 2f, halfHeight + 2f) / 5.25f); _borderVerts = new VertexPositionColorTexture[24]; _borderVerts[0] = vertice[0]; _borderVerts[1] = vertice[5]; _borderVerts[2] = vertice[4]; _borderVerts[3] = vertice[0]; _borderVerts[4] = vertice[1]; _borderVerts[5] = vertice[5]; _borderVerts[6] = vertice[1]; _borderVerts[7] = vertice[6]; _borderVerts[8] = vertice[5]; _borderVerts[9] = vertice[1]; _borderVerts[10] = vertice[2]; _borderVerts[11] = vertice[6]; _borderVerts[12] = vertice[2]; _borderVerts[13] = vertice[7]; _borderVerts[14] = vertice[6]; _borderVerts[15] = vertice[2]; _borderVerts[16] = vertice[3]; _borderVerts[17] = vertice[7]; _borderVerts[18] = vertice[3]; _borderVerts[19] = vertice[4]; _borderVerts[20] = vertice[7]; _borderVerts[21] = vertice[3]; _borderVerts[22] = vertice[0]; _borderVerts[23] = vertice[4]; }
/// <summary> /// Combine a list of triangles into a list of convex polygons. /// /// Note: This only works on triangles. /// </summary> ///<param name="triangles">The triangles.</param> ///<param name="maxPolys">The maximun number of polygons to return.</param> ///<param name="tolerance">The tolerance</param> public static List <Vertices> PolygonizeTriangles(List <Vertices> triangles, int maxPolys = int.MaxValue, float tolerance = 0.001f) { if (triangles.Count <= 0) { return(triangles); } List <Vertices> polys = new List <Vertices>(); bool[] covered = new bool[triangles.Count]; for (int i = 0; i < triangles.Count; ++i) { covered[i] = false; //Check here for degenerate triangles Vertices triangle = triangles[i]; Vector2 a = triangle[0]; Vector2 b = triangle[1]; Vector2 c = triangle[2]; if ((a.X == b.X && a.Y == b.Y) || (b.X == c.X && b.Y == c.Y) || (a.X == c.X && a.Y == c.Y)) { covered[i] = true; } } int polyIndex = 0; bool notDone = true; while (notDone) { int currTri = -1; for (int i = 0; i < triangles.Count; ++i) { if (covered[i]) { continue; } currTri = i; break; } if (currTri == -1) { notDone = false; } else { Vertices poly = new Vertices(3); for (int i = 0; i < 3; i++) { poly.Add(triangles[currTri][i]); } covered[currTri] = true; int index = 0; for (int i = 0; i < 2 * triangles.Count; ++i, ++index) { while (index >= triangles.Count) { index -= triangles.Count; } if (covered[index]) { continue; } Vertices newP = AddTriangle(triangles[index], poly); if (newP == null) { continue; // is this right } if (newP.Count > Settings.MaxPolygonVertices) { continue; } if (newP.IsConvex()) { //Or should it be IsUsable? Maybe re-write IsConvex to apply the angle threshold from Box2d poly = new Vertices(newP); covered[index] = true; } } //We have a maximum of polygons that we need to keep under. if (polyIndex < maxPolys) { SimplifyTools.MergeParallelEdges(poly, tolerance); //If identical points are present, a triangle gets //borked by the MergeParallelEdges function, hence //the vertex number check if (poly.Count >= 3) { polys.Add(new Vertices(poly)); } else { Debug.WriteLine("Skipping corrupt poly."); } } if (poly.Count >= 3) { polyIndex++; //Must be outside (polyIndex < polysLength) test } } } //TODO: Add sanity check //Remove empty vertice collections for (int i = polys.Count - 1; i >= 0; i--) { if (polys[i].Count == 0) { polys.RemoveAt(i); } } return(polys); }
private static Vertices AddTriangle(Triangle t, Vertices vertices) { // float32 equalTol = .001f; // First, find vertices that connect int firstP = -1; int firstT = -1; int secondP = -1; int secondT = -1; for (int i = 0; i < vertices.Count; i++) { if (t.X[0] == vertices[i].X && t.Y[0] == vertices[i].Y) { if (firstP == -1) { firstP = i; firstT = 0; } else { secondP = i; secondT = 0; } } else if (t.X[1] == vertices[i].X && t.Y[1] == vertices[i].Y) { if (firstP == -1) { firstP = i; firstT = 1; } else { secondP = i; secondT = 1; } } else if (t.X[2] == vertices[i].X && t.Y[2] == vertices[i].Y) { if (firstP == -1) { firstP = i; firstT = 2; } else { secondP = i; secondT = 2; } } } // Fix ordering if first should be last vertex of poly if (firstP == 0 && secondP == vertices.Count - 1) { firstP = vertices.Count - 1; secondP = 0; } // Didn't find it if (secondP == -1) { return(null); } // Find tip index on triangle int tipT = 0; if (tipT == firstT || tipT == secondT) { tipT = 1; } if (tipT == firstT || tipT == secondT) { tipT = 2; } Vertices result = new Vertices(vertices.Count + 1); for (int i = 0; i < vertices.Count; i++) { result.Add(vertices[i]); if (i == firstP) { result.Add(new Vector2(t.X[tipT], t.Y[tipT])); } } return(result); }
private CharacterCollisionTest() { //Ground body Body ground = BodyFactory.CreateEdge(World, new Vector2(-20.0f, 0.0f), new Vector2(20.0f, 0.0f)); // Collinear edges with no adjacency information. // This shows the problematic case where a box shape can hit // an internal vertex. EdgeShape shape = new EdgeShape(new Vector2(-8.0f, 1.0f), new Vector2(-6.0f, 1.0f)); ground.CreateFixture(shape); shape = new EdgeShape(new Vector2(-6.0f, 1.0f), new Vector2(-4.0f, 1.0f)); ground.CreateFixture(shape); shape = new EdgeShape(new Vector2(-4.0f, 1.0f), new Vector2(-2.0f, 1.0f)); ground.CreateFixture(shape); // Chain shape { Vertices vs = new Vertices(4); vs.Add(new Vector2(5.0f, 7.0f)); vs.Add(new Vector2(6.0f, 8.0f)); vs.Add(new Vector2(7.0f, 8.0f)); vs.Add(new Vector2(8.0f, 7.0f)); Body body = BodyFactory.CreateChainShape(World, vs); body.Rotation = 0.25f * Settings.Pi; } // Square tiles. This shows that adjacency shapes may // have non-smooth collision. There is no solution // to this problem. PolygonShape tile = new PolygonShape(1); tile.Vertices = PolygonTools.CreateRectangle(1.0f, 1.0f, new Vector2(4.0f, 3.0f), 0.0f); ground.CreateFixture(tile); tile.Vertices = PolygonTools.CreateRectangle(1.0f, 1.0f, new Vector2(6.0f, 3.0f), 0.0f); ground.CreateFixture(tile); tile.Vertices = PolygonTools.CreateRectangle(1.0f, 1.0f, new Vector2(8.0f, 3.0f), 0.0f); ground.CreateFixture(tile); // Square made from an edge loop. Collision should be smooth. Vertices vertices = new Vertices(4); vertices.Add(new Vector2(-1.0f, 3.0f)); vertices.Add(new Vector2(1.0f, 3.0f)); vertices.Add(new Vector2(1.0f, 5.0f)); vertices.Add(new Vector2(-1.0f, 5.0f)); FixtureFactory.AttachLoopShape(vertices, ground); // Edge loop. Collision should be smooth. vertices = new Vertices(10); vertices.Add(new Vector2(0.0f, 0.0f)); vertices.Add(new Vector2(6.0f, 0.0f)); vertices.Add(new Vector2(6.0f, 2.0f)); vertices.Add(new Vector2(4.0f, 1.0f)); vertices.Add(new Vector2(2.0f, 2.0f)); vertices.Add(new Vector2(0.0f, 2.0f)); vertices.Add(new Vector2(-2.0f, 2.0f)); vertices.Add(new Vector2(-4.0f, 3.0f)); vertices.Add(new Vector2(-6.0f, 2.0f)); vertices.Add(new Vector2(-6.0f, 0.0f)); BodyFactory.CreateLoopShape(World, vertices, new Vector2(-10, 4)); // Square character 1 Body squareCharacter = BodyFactory.CreateRectangle(World, 1, 1, 20, new Vector2(-3.0f, 8.0f)); squareCharacter.BodyType = BodyType.Dynamic; squareCharacter.FixedRotation = true; squareCharacter.SleepingAllowed = false; squareCharacter.OnCollision += CharacterOnCollision; squareCharacter.OnSeparation += CharacterOnSeparation; // Square character 2 Body squareCharacter2 = BodyFactory.CreateRectangle(World, 0.5f, 0.5f, 20, new Vector2(-5.0f, 5.0f)); squareCharacter2.BodyType = BodyType.Dynamic; squareCharacter2.FixedRotation = true; squareCharacter2.SleepingAllowed = false; // Hexagon character float angle = 0.0f; const float delta = Settings.Pi / 3.0f; vertices = new Vertices(6); for (int i = 0; i < 6; ++i) { vertices.Add(new Vector2(0.5f * (float)Math.Cos(angle), 0.5f * (float)Math.Sin(angle))); angle += delta; } Body hexCharacter = BodyFactory.CreatePolygon(World, vertices, 20, new Vector2(-5.0f, 8.0f)); hexCharacter.BodyType = BodyType.Dynamic; hexCharacter.FixedRotation = true; hexCharacter.SleepingAllowed = false; // Circle character Body circleCharacter = BodyFactory.CreateCircle(World, 0.5f, 20, new Vector2(3.0f, 5.0f)); circleCharacter.BodyType = BodyType.Dynamic; circleCharacter.FixedRotation = true; circleCharacter.SleepingAllowed = false; // Circle character _character = BodyFactory.CreateCircle(World, 0.25f, 20, new Vector2(-7.0f, 6.0f)); _character.BodyType = BodyType.Dynamic; _character.Friction = 1.0f; _character.SleepingAllowed = false; }
private CollisionProcessingTest() { //Ground BodyFactory.CreateEdge(World, new Vector2(-40.0f, 0.0f), new Vector2(40.0f, 0.0f)); const float xLo = -5.0f; const float xHi = 5.0f; const float yLo = 2.0f; const float yHi = 35.0f; // Small triangle Vertices vertices = new Vertices(3); vertices.Add(new Vector2(-1.0f, 0.0f)); vertices.Add(new Vector2(1.0f, 0.0f)); vertices.Add(new Vector2(0.0f, 2.0f)); PolygonShape polygon = new PolygonShape(vertices, 1); Body body1 = BodyFactory.CreateBody(World); body1.BodyType = BodyType.Dynamic; body1.Position = new Vector2(Rand.RandomFloat(xLo, xHi), Rand.RandomFloat(yLo, yHi)); Fixture fixture = body1.CreateFixture(polygon); fixture.OnCollision += OnCollision; // Large triangle (recycle definitions) vertices[0] *= 2.0f; vertices[1] *= 2.0f; vertices[2] *= 2.0f; polygon.Vertices = vertices; Body body2 = BodyFactory.CreateBody(World); body2.BodyType = BodyType.Dynamic; body2.Position = new Vector2(Rand.RandomFloat(xLo, xHi), Rand.RandomFloat(yLo, yHi)); fixture = body2.CreateFixture(polygon); fixture.OnCollision += OnCollision; // Small box Vertices smallBox = PolygonUtils.CreateRectangle(1.0f, 0.5f); polygon.Vertices = smallBox; Body body3 = BodyFactory.CreateBody(World); body3.BodyType = BodyType.Dynamic; body3.Position = new Vector2(Rand.RandomFloat(xLo, xHi), Rand.RandomFloat(yLo, yHi)); fixture = body3.CreateFixture(polygon); fixture.OnCollision += OnCollision; // Large box (recycle definitions) Vertices largeBox = PolygonUtils.CreateRectangle(2.0f, 1.0f); polygon.Vertices = largeBox; Body body4 = BodyFactory.CreateBody(World); body4.BodyType = BodyType.Dynamic; body4.Position = new Vector2(Rand.RandomFloat(xLo, xHi), Rand.RandomFloat(yLo, yHi)); fixture = body4.CreateFixture(polygon); fixture.OnCollision += OnCollision; // Small circle CircleShape circle = new CircleShape(1.0f, 1); Body body5 = BodyFactory.CreateBody(World); body5.BodyType = BodyType.Dynamic; body5.Position = new Vector2(Rand.RandomFloat(xLo, xHi), Rand.RandomFloat(yLo, yHi)); fixture = body5.CreateFixture(circle); fixture.OnCollision += OnCollision; // Large circle circle.Radius *= 2.0f; Body body6 = BodyFactory.CreateBody(World); body6.BodyType = BodyType.Dynamic; body6.Position = new Vector2(Rand.RandomFloat(xLo, xHi), Rand.RandomFloat(yLo, yHi)); fixture = body6.CreateFixture(circle); fixture.OnCollision += OnCollision; }
/// <summary> /// Добавление новой вершины /// </summary> /// <param name="vertex"></param> public void AddVertex(Point vertex) { Vertices.Add(vertex); }
private PinballTest() { // Ground body Body ground; { ground = World.CreateBody(); Vertices vertices = new Vertices(5); vertices.Add(new Vector2(0.0f, -2.0f)); vertices.Add(new Vector2(8.0f, 6.0f)); vertices.Add(new Vector2(8.0f, 20.0f)); vertices.Add(new Vector2(-8.0f, 20.0f)); vertices.Add(new Vector2(-8.0f, 6.0f)); ChainShape chain = new ChainShape(vertices, true); ground.CreateFixture(chain); } // Flippers { Vector2 p1 = new Vector2(-2.0f, 0f); Vector2 p2 = new Vector2(2.0f, 0f); Body leftFlipper = World.CreateBody(p1); leftFlipper.BodyType = BodyType.Dynamic; Body rightFlipper = World.CreateBody(p2); rightFlipper.BodyType = BodyType.Dynamic; PolygonShape box = new PolygonShape(1); box.Vertices = PolygonTools.CreateRectangle(1.75f, 0.1f); leftFlipper.CreateFixture(box); rightFlipper.CreateFixture(box); _leftJoint = new RevoluteJoint(ground, leftFlipper, p1, Vector2.Zero); _leftJoint.MaxMotorTorque = 1000.0f; _leftJoint.LimitEnabled = true; _leftJoint.MotorEnabled = true; _leftJoint.MotorSpeed = 0.0f; _leftJoint.LowerLimit = -30.0f * MathHelper.Pi / 180.0f; _leftJoint.UpperLimit = 5.0f * MathHelper.Pi / 180.0f; World.Add(_leftJoint); _rightJoint = new RevoluteJoint(ground, rightFlipper, p2, Vector2.Zero); _rightJoint.MaxMotorTorque = 1000.0f; _rightJoint.LimitEnabled = true; _rightJoint.MotorEnabled = true; _rightJoint.MotorSpeed = 0.0f; _rightJoint.LowerLimit = -5.0f * MathHelper.Pi / 180.0f; _rightJoint.UpperLimit = 30.0f * MathHelper.Pi / 180.0f; World.Add(_rightJoint); } // Circle character { _ball = World.CreateBody(new Vector2(1.0f, 15.0f)); _ball.BodyType = BodyType.Dynamic; _ball.IsBullet = true; _ball.CreateFixture(new CircleShape(0.2f, 1.0f)); } }
//From Eric Jordan's convex decomposition library /// <summary> /// Merges all parallel edges in the list of vertices /// </summary> /// <param name="vertices">The vertices.</param> /// <param name="tolerance">The tolerance.</param> public static void MergeParallelEdges(Vertices vertices, float tolerance) { if (vertices.Count <= 3) { return; //Can't do anything useful here to a triangle } bool[] mergeMe = new bool[vertices.Count]; int newNVertices = vertices.Count; //Gather points to process for (int i = 0; i < vertices.Count; ++i) { int lower = (i == 0) ? (vertices.Count - 1) : (i - 1); int middle = i; int upper = (i == vertices.Count - 1) ? (0) : (i + 1); float dx0 = vertices[middle].X - vertices[lower].X; float dy0 = vertices[middle].Y - vertices[lower].Y; float dx1 = vertices[upper].Y - vertices[middle].X; float dy1 = vertices[upper].Y - vertices[middle].Y; float norm0 = (float)Math.Sqrt(dx0 * dx0 + dy0 * dy0); float norm1 = (float)Math.Sqrt(dx1 * dx1 + dy1 * dy1); if (!(norm0 > 0.0f && norm1 > 0.0f) && newNVertices > 3) { //Merge identical points mergeMe[i] = true; --newNVertices; } dx0 /= norm0; dy0 /= norm0; dx1 /= norm1; dy1 /= norm1; float cross = dx0 * dy1 - dx1 * dy0; float dot = dx0 * dx1 + dy0 * dy1; if (Math.Abs(cross) < tolerance && dot > 0 && newNVertices > 3) { mergeMe[i] = true; --newNVertices; } else { mergeMe[i] = false; } } if (newNVertices == vertices.Count || newNVertices == 0) { return; } int currIndex = 0; //Copy the vertices to a new list and clear the old Vertices oldVertices = new Vertices(vertices); vertices.Clear(); for (int i = 0; i < oldVertices.Count; ++i) { if (mergeMe[i] || newNVertices == 0 || currIndex == newNVertices) { continue; } Debug.Assert(currIndex < newNVertices); vertices.Add(oldVertices[i]); ++currIndex; } }
public List <Vertices> DetectVertices() { #region Check TextureConverter setup. if (_data == null) { throw new Exception("'_data' can't be null. You have to use SetTextureData(uint[] data, int width) before calling this method."); } if (_data.Length < 4) { throw new Exception("'_data' length can't be less then 4. Your texture must be at least 2 x 2 pixels in size. " + "You have to use SetTextureData(uint[] data, int width) before calling this method."); } if (_width < 2) { throw new Exception("'_width' can't be less then 2. Your texture must be at least 2 x 2 pixels in size. " + "You have to use SetTextureData(uint[] data, int width) before calling this method."); } if (_data.Length % _width != 0) { throw new Exception("'_width' has an invalid value. You have to use SetTextureData(uint[] data, int width) before calling this method."); } #endregion List <Vertices> detectedPolygons = new List <Vertices>(); Vector2?holeEntrance = null; Vector2?polygonEntrance = null; List <Vector2> blackList = new List <Vector2>(); bool searchOn; do { Vertices polygon; if (detectedPolygons.Count == 0) { // First pass / single polygon polygon = new Vertices(CreateSimplePolygon(Vector2.Zero, Vector2.Zero)); if (polygon.Count > 2) { polygonEntrance = GetTopMostVertex(polygon); } } else if (polygonEntrance.HasValue) { // Multi pass / multiple polygons polygon = new Vertices(CreateSimplePolygon(polygonEntrance.Value, new Vector2(polygonEntrance.Value.X - 1f, polygonEntrance.Value.Y))); } else { break; } searchOn = false; if (polygon.Count > 2) { if (_holeDetection) { do { holeEntrance = SearchHoleEntrance(polygon, holeEntrance); if (holeEntrance.HasValue) { if (!blackList.Contains(holeEntrance.Value)) { blackList.Add(holeEntrance.Value); Vertices holePolygon = CreateSimplePolygon(holeEntrance.Value, new Vector2(holeEntrance.Value.X + 1, holeEntrance.Value.Y)); if (holePolygon != null && holePolygon.Count > 2) { switch (_polygonDetectionType) { case VerticesDetectionType.Integrated: // Add first hole polygon vertex to close the hole polygon. holePolygon.Add(holePolygon[0]); int vertex1Index, vertex2Index; if (SplitPolygonEdge(polygon, holeEntrance.Value, out vertex1Index, out vertex2Index)) { polygon.InsertRange(vertex2Index, holePolygon); } break; case VerticesDetectionType.Separated: if (polygon.Holes == null) { polygon.Holes = new List <Vertices>(); } polygon.Holes.Add(holePolygon); break; } } } else { break; } } else { break; } }while (true); } detectedPolygons.Add(polygon); } if (_multipartDetection || polygon.Count <= 2) { if (SearchNextHullEntrance(detectedPolygons, polygonEntrance.Value, out polygonEntrance)) { searchOn = true; } } }while (searchOn); if (detectedPolygons == null || (detectedPolygons != null && detectedPolygons.Count == 0)) { throw new Exception("Couldn't detect any vertices."); } // Post processing. if (PolygonDetectionType == VerticesDetectionType.Separated) // Only when VerticesDetectionType.Separated? -> Recheck. { ApplyTriangulationCompatibleWinding(ref detectedPolygons); } if (_transform != Matrix.Identity) { ApplyTransform(ref detectedPolygons); } return(detectedPolygons); }
/// <summary> /// /// </summary> /// <param name="entrance"></param> /// <param name="last"></param> /// <returns></returns> private Vertices CreateSimplePolygon(Vector2 entrance, Vector2 last) { bool entranceFound = false; bool endOfHull = false; Vertices polygon = new Vertices(32); Vertices hullArea = new Vertices(32); Vertices endOfHullArea = new Vertices(32); Vector2 current = Vector2.Zero; #region Entrance check // Get the entrance point. //todo: alle möglichkeiten testen if (entrance == Vector2.Zero || !InBounds(ref entrance)) { entranceFound = SearchHullEntrance(out entrance); if (entranceFound) { current = new Vector2(entrance.X - 1f, entrance.Y); } } else { if (IsSolid(ref entrance)) { if (IsNearPixel(ref entrance, ref last)) { current = last; entranceFound = true; } else { Vector2 temp; if (SearchNearPixels(false, ref entrance, out temp)) { current = temp; entranceFound = true; } else { entranceFound = false; } } } } #endregion if (entranceFound) { polygon.Add(entrance); hullArea.Add(entrance); Vector2 next = entrance; do { // Search in the pre vision list for an outstanding point. Vector2 outstanding; if (SearchForOutstandingVertex(hullArea, out outstanding)) { if (endOfHull) { // We have found the next pixel, but is it on the last bit of the hull? if (endOfHullArea.Contains(outstanding)) { // Indeed. polygon.Add(outstanding); } // That's enough, quit. break; } // Add it and remove all vertices that don't matter anymore // (all the vertices before the outstanding). polygon.Add(outstanding); hullArea.RemoveRange(0, hullArea.IndexOf(outstanding)); } // Last point gets current and current gets next. Our little spider is moving forward on the hull ;). last = current; current = next; // Get the next point on hull. if (GetNextHullPoint(ref last, ref current, out next)) { // Add the vertex to a hull pre vision list. hullArea.Add(next); } else { // Quit break; } if (next == entrance && !endOfHull) { // It's the last bit of the hull, search on and exit at next found vertex. endOfHull = true; endOfHullArea.AddRange(hullArea); // We don't want the last vertex to be the same as the first one, because it causes the triangulation code to crash. if (endOfHullArea.Contains(entrance)) { endOfHullArea.Remove(entrance); } } } while (true); } return(polygon); }
//Melkman based convex hull algorithm contributed by Cowdozer /// <summary> /// Creates a convex hull. /// Note: /// 1. Vertices must be of a simple polygon, i.e. edges do not overlap. /// 2. Melkman does not work on point clouds /// </summary> /// <remarks> /// Implemented using Melkman's Convex Hull Algorithm - O(n) time complexity. /// Reference: http://www.ams.sunysb.edu/~jsbm/courses/345/melkman.pdf /// </remarks> /// <returns>A convex hull in counterclockwise winding order.</returns> public static Vertices GetConvexHull(Vertices vertices) { //With less than 3 vertices, this is about the best we can do for a convex hull if (vertices.Count < 3) { return(vertices); } //We'll never need a queue larger than the current number of Vertices +1 //Create double-ended queue Vector2[] deque = new Vector2[vertices.Count + 1]; int qf = 3, qb = 0; //Queue front index, queue back index int qfm1, qbm1; //qfm1 = second element, qbm1 = second last element //Start by placing first 3 vertices in convex CCW order int startIndex = 3; float k = MathUtils.Area(vertices[0], vertices[1], vertices[2]); if (k == 0) { //Vertices are collinear. deque[0] = vertices[0]; deque[1] = vertices[2]; //We can skip vertex 1 because it should be between 0 and 2 deque[2] = vertices[0]; qf = 2; //Go until the end of the collinear sequence of vertices for (startIndex = 3; startIndex < vertices.Count; startIndex++) { Vector2 tmp = vertices[startIndex]; if (MathUtils.Area(ref deque[0], ref deque[1], ref tmp) == 0) //This point is also collinear { deque[1] = vertices[startIndex]; } else { break; } } } else { deque[0] = deque[3] = vertices[2]; if (k > 0) { //Is Left. Set deque = {2, 0, 1, 2} deque[1] = vertices[0]; deque[2] = vertices[1]; } else { //Is Right. Set deque = {2, 1, 0, 2} deque[1] = vertices[1]; deque[2] = vertices[0]; } } qfm1 = qf == 0 ? deque.Length - 1 : qf - 1; //qfm1 = qf - 1; qbm1 = qb == deque.Length - 1 ? 0 : qb + 1; //qbm1 = qb + 1; //Add vertices one at a time and adjust convex hull as needed for (int i = startIndex; i < vertices.Count; i++) { Vector2 nextPt = vertices[i]; //Ignore if it is already within the convex hull we have constructed if (MathUtils.Area(ref deque[qfm1], ref deque[qf], ref nextPt) > 0 && MathUtils.Area(ref deque[qb], ref deque[qbm1], ref nextPt) > 0) { continue; } //Pop front until convex while (!(MathUtils.Area(ref deque[qfm1], ref deque[qf], ref nextPt) > 0)) { //Pop the front element from the queue qf = qfm1; //qf--; qfm1 = qf == 0 ? deque.Length - 1 : qf - 1; //qfm1 = qf - 1; } //Add vertex to the front of the queue qf = qf == deque.Length - 1 ? 0 : qf + 1; //qf++; qfm1 = qf == 0 ? deque.Length - 1 : qf - 1; //qfm1 = qf - 1; deque[qf] = nextPt; //Pop back until convex while (!(MathUtils.Area(ref deque[qb], ref deque[qbm1], ref nextPt) > 0)) { //Pop the back element from the queue qb = qbm1; //qb++; qbm1 = qb == deque.Length - 1 ? 0 : qb + 1; //qbm1 = qb + 1; } //Add vertex to the back of the queue qb = qb == 0 ? deque.Length - 1 : qb - 1; //qb--; qbm1 = qb == deque.Length - 1 ? 0 : qb + 1; //qbm1 = qb + 1; deque[qb] = nextPt; } //Create the convex hull from what is left in the deque Vertices convexHull = new Vertices(vertices.Count + 1); if (qb < qf) { for (int i = qb; i < qf; i++) { convexHull.Add(deque[i]); } } else { for (int i = 0; i < qf; i++) { convexHull.Add(deque[i]); } for (int i = qb; i < deque.Length; i++) { convexHull.Add(deque[i]); } } return(convexHull); }
//Andrew's monotone chain 2D convex hull algorithm. //Copyright 2001, softSurfer (www.softsurfer.com) /// <summary> /// Gets the convex hull. /// </summary> /// <remarks> /// http://www.softsurfer.com/Archive/algorithm_0109/algorithm_0109.htm /// </remarks> /// <returns></returns> public static Vertices GetConvexHull(Vertices P) { P.Sort(new PointComparer()); Vector2[] H = new Vector2[P.Count]; Vertices res = new Vertices(); int n = P.Count; int bot, top = -1; // indices for bottom and top of the stack int i; // array scan index // Get the indices of points with min x-coord and min|max y-coord int minmin = 0, minmax; float xmin = P[0].X; for (i = 1; i < n; i++) { if (P[i].X != xmin) { break; } } minmax = i - 1; if (minmax == n - 1) { // degenerate case: all x-coords == xmin H[++top] = P[minmin]; if (P[minmax].Y != P[minmin].Y) // a nontrivial segment { H[++top] = P[minmax]; } H[++top] = P[minmin]; // add polygon endpoint for (int j = 0; j < top + 1; j++) { res.Add(H[j]); } return(res); } top = res.Count - 1; // Get the indices of points with max x-coord and min|max y-coord int maxmin, maxmax = n - 1; float xmax = P[n - 1].X; for (i = n - 2; i >= 0; i--) { if (P[i].X != xmax) { break; } } maxmin = i + 1; // Compute the lower hull on the stack H H[++top] = P[minmin]; // push minmin point onto stack i = minmax; while (++i <= maxmin) { // the lower line joins P[minmin] with P[maxmin] if (MathUtils.Area(P[minmin], P[maxmin], P[i]) >= 0 && i < maxmin) { continue; // ignore P[i] above or on the lower line } while (top > 0) // there are at least 2 points on the stack { // test if P[i] is left of the line at the stack top if (MathUtils.Area(H[top - 1], H[top], P[i]) > 0) { break; // P[i] is a new hull vertex } else { top--; // pop top point off stack } } H[++top] = P[i]; // push P[i] onto stack } // Next, compute the upper hull on the stack H above the bottom hull if (maxmax != maxmin) // if distinct xmax points { H[++top] = P[maxmax]; // push maxmax point onto stack } bot = top; // the bottom point of the upper hull stack i = maxmin; while (--i >= minmax) { // the upper line joins P[maxmax] with P[minmax] if (MathUtils.Area(P[maxmax], P[minmax], P[i]) >= 0 && i > minmax) { continue; // ignore P[i] below or on the upper line } while (top > bot) // at least 2 points on the upper stack { // test if P[i] is left of the line at the stack top if (MathUtils.Area(H[top - 1], H[top], P[i]) > 0) { break; // P[i] is a new hull vertex } else { top--; // pop top point off stack } } H[++top] = P[i]; // push P[i] onto stack } if (minmax != minmin) { H[++top] = P[minmin]; // push joining endpoint onto stack } for (int j = 0; j < top + 1; j++) { res.Add(H[j]); } return(res); }
private SerializationTest() { Body ground = BodyFactory.CreateEdge(World, new Vector2(-20, 0), new Vector2(20, 0)); //Friction and distance joint { Body bodyA = BodyFactory.CreateCircle(World, 1, 1.5f, new Vector2(10, 25)); bodyA.BodyType = BodyType.Dynamic; Body bodyB = BodyFactory.CreateRectangle(World, 1, 1, 1, new Vector2(-1, 25)); bodyB.BodyType = BodyType.Dynamic; FrictionJoint frictionJoint = JointFactory.CreateFrictionJoint(World, bodyB, ground, Vector2.Zero); frictionJoint.CollideConnected = true; frictionJoint.MaxForce = 100; JointFactory.CreateDistanceJoint(World, bodyA, bodyB); } //Wheel joint { Vertices vertices = new Vertices(6); vertices.Add(new Vector2(-1.5f, -0.5f)); vertices.Add(new Vector2(1.5f, -0.5f)); vertices.Add(new Vector2(1.5f, 0.0f)); vertices.Add(new Vector2(0.0f, 0.9f)); vertices.Add(new Vector2(-1.15f, 0.9f)); vertices.Add(new Vector2(-1.5f, 0.2f)); Body carBody = BodyFactory.CreatePolygon(World, vertices, 1, new Vector2(0, 1)); carBody.BodyType = BodyType.Dynamic; Body wheel1 = BodyFactory.CreateCircle(World, 0.4f, 1, new Vector2(-1.0f, 0.35f)); wheel1.BodyType = BodyType.Dynamic; wheel1.Friction = 0.9f; Body wheel2 = BodyFactory.CreateCircle(World, 0.4f, 1, new Vector2(1.0f, 0.4f)); wheel2.BodyType = BodyType.Dynamic; wheel2.Friction = 0.9f; Vector2 axis = new Vector2(0.0f, 1.0f); WheelJoint spring1 = JointFactory.CreateWheelJoint(World, carBody, wheel1, axis); spring1.MotorSpeed = 0.0f; spring1.MaxMotorTorque = 20.0f; spring1.MotorEnabled = true; spring1.Frequency = 4; spring1.DampingRatio = 0.7f; WheelJoint spring2 = JointFactory.CreateWheelJoint(World, carBody, wheel2, axis); spring2.MotorSpeed = 0.0f; spring2.MaxMotorTorque = 10.0f; spring2.MotorEnabled = false; spring2.Frequency = 4; spring2.DampingRatio = 0.7f; } //Prismatic joint { Body body = BodyFactory.CreateRectangle(World, 2, 2, 5, new Vector2(-10.0f, 10.0f)); body.BodyType = BodyType.Dynamic; body.Rotation = 0.5f * Settings.Pi; Vector2 axis = new Vector2(2.0f, 1.0f); axis.Normalize(); PrismaticJoint joint = JointFactory.CreatePrismaticJoint(World, ground, body, Vector2.Zero, axis); joint.MotorSpeed = 5.0f; joint.MaxMotorForce = 1000.0f; joint.MotorEnabled = true; joint.LowerLimit = -10.0f; joint.UpperLimit = 20.0f; joint.LimitEnabled = true; } // Pulley joint { Body body1 = BodyFactory.CreateRectangle(World, 2, 4, 5, new Vector2(-10.0f, 16.0f)); body1.BodyType = BodyType.Dynamic; Body body2 = BodyFactory.CreateRectangle(World, 2, 4, 5, new Vector2(10.0f, 16.0f)); body2.BodyType = BodyType.Dynamic; Vector2 anchor1 = new Vector2(-10.0f, 16.0f + 2.0f); Vector2 anchor2 = new Vector2(10.0f, 16.0f + 2.0f); Vector2 worldAnchor1 = new Vector2(-10.0f, 16.0f + 2.0f + 12.0f); Vector2 worldAnchor2 = new Vector2(10.0f, 16.0f + 2.0f + 12.0f); JointFactory.CreatePulleyJoint(World, body1, body2, anchor1, anchor2, worldAnchor1, worldAnchor2, 1.5f, true); } //Revolute joint { Body ball = BodyFactory.CreateCircle(World, 3.0f, 5.0f, new Vector2(5.0f, 30.0f)); ball.BodyType = BodyType.Dynamic; Body polygonBody = BodyFactory.CreateRectangle(World, 20, 0.4f, 2, new Vector2(10, 10)); polygonBody.BodyType = BodyType.Dynamic; polygonBody.IsBullet = true; RevoluteJoint joint = JointFactory.CreateRevoluteJoint(World, ground, polygonBody, new Vector2(10, 0)); joint.LowerLimit = -0.25f * Settings.Pi; joint.UpperLimit = 0.0f * Settings.Pi; joint.LimitEnabled = true; } //Weld joint { PolygonShape shape = new PolygonShape(PolygonUtils.CreateRectangle(0.5f, 0.125f), 20); Body prevBody = ground; for (int i = 0; i < 10; ++i) { Body body = BodyFactory.CreateBody(World); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(-14.5f + 1.0f * i, 5.0f); body.CreateFixture(shape); Vector2 anchor = new Vector2(0.5f, 0); if (i == 0) { anchor = new Vector2(-15f, 5); } JointFactory.CreateWeldJoint(World, prevBody, body, anchor, new Vector2(-0.5f, 0)); prevBody = body; } } //Rope joint { LinkFactory.CreateChain(World, new Vector2(-10, 10), new Vector2(-20, 10), 0.1f, 0.5f, 10, 0.1f, true); } //Angle joint { Body fA = BodyFactory.CreateRectangle(World, 4, 4, 1, new Vector2(-5, 4)); fA.BodyType = BodyType.Dynamic; fA.Rotation = (float)(Math.PI / 3); Body fB = BodyFactory.CreateRectangle(World, 4, 4, 1, new Vector2(5, 4)); fB.BodyType = BodyType.Dynamic; AngleJoint joint = new AngleJoint(fA, fB); joint.TargetAngle = (float)Math.PI / 2; World.AddJoint(joint); } //Motor joint { Body body = BodyFactory.CreateRectangle(World, 4, 1, 2, new Vector2(0, 35)); body.BodyType = BodyType.Dynamic; body.Friction = 0.6f; MotorJoint motorJoint = JointFactory.CreateMotorJoint(World, ground, body); motorJoint.MaxForce = 1000.0f; motorJoint.MaxTorque = 1000.0f; motorJoint.LinearOffset = new Vector2(0, 35); motorJoint.AngularOffset = (float)(Math.PI / 3f); } }
private void ReadBody(List <string> section, PlyElement element) { foreach (string line in section) { string[] tokens = line.Split(splitter, StringSplitOptions.RemoveEmptyEntries); if (element.Type == PlyElementType.vertex) { float[] floatTokens = new float[tokens.Length]; PlyVertex Vertex = new PlyVertex(); for (int i = 0; i < tokens.Length; i++) { string typeName = element.Properties[i].TypeName; string name = element.Properties[i].Name; PlyPropertyType propType = element.Properties[i].Type; byte r = 0; byte g = 0; byte b = 0; if (propType == PlyPropertyType.x) { Vertex.X = float.Parse(tokens[i]); } if (propType == PlyPropertyType.y) { Vertex.Y = float.Parse(tokens[i]); } if (propType == PlyPropertyType.z) { Vertex.Z = float.Parse(tokens[i]); } if (propType == PlyPropertyType.nx) { Vertex.Normal.X = double.Parse(tokens[i]); } if (propType == PlyPropertyType.ny) { Vertex.Normal.Y = double.Parse(tokens[i]); } if (propType == PlyPropertyType.nz) { Vertex.Normal.Z = double.Parse(tokens[i]); } if (propType == PlyPropertyType.red) { r = byte.Parse(tokens[i]); } if (propType == PlyPropertyType.green) { g = byte.Parse(tokens[i]); } if (propType == PlyPropertyType.blue) { b = byte.Parse(tokens[i]); } Vertex.Col = System.Drawing.Color.FromArgb(r, g, b); } Vertices.Add(Vertex); } if (element.Type == PlyElementType.face) { var indexList = new List <int>(); for (int i = 1; i < tokens.Length; i++) { int temp = int.Parse(tokens[i]); indexList.Add(temp); } Faces.Add(new PlyFace(indexList)); } if (element.Type == PlyElementType.edge) { PlyEdge edge = new PlyEdge(element.containsColor); for (int i = 0; i < tokens.Length; i++) { string typeName = element.Properties[i].TypeName; string name = element.Properties[i].Name; PlyPropertyType propType = element.Properties[i].Type; byte r = 0; byte b = 0; byte g = 0; if (propType == PlyPropertyType.red) { r = byte.Parse(tokens[i]); } if (propType == PlyPropertyType.green) { g = byte.Parse(tokens[i]); } if (propType == PlyPropertyType.blue) { b = byte.Parse(tokens[i]); } if (propType == PlyPropertyType.vertex1) { edge.Vertex1 = int.Parse(tokens[i]); } if (propType == PlyPropertyType.vertex2) { edge.Vertex2 = int.Parse(tokens[i]); } edge.Color = System.Drawing.Color.FromArgb(r, g, b); } Edges.Add(edge); } if (element.Type == PlyElementType.material) { for (int i = 0; i < tokens.Length; i++) { } } if (element.Type == PlyElementType.other) { for (int i = 0; i < tokens.Length; i++) { } } } }
private CantileverTest() { Body ground = World.CreateEdge(new Vector2(-40, 0), new Vector2(40, 0)); { PolygonShape shape = new PolygonShape(20); shape.Vertices = PolygonTools.CreateRectangle(0.5f, 0.125f); Body prevBody = ground; for (int i = 0; i < Count; ++i) { Body body = World.CreateBody(); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(-14.5f + 1.0f * i, 5.0f); body.CreateFixture(shape); Vector2 anchor = new Vector2(-15.0f + 1.0f * i, 5.0f); WeldJoint jd = new WeldJoint(prevBody, body, anchor, anchor, true); World.Add(jd); prevBody = body; } } { PolygonShape shape = new PolygonShape(20f); shape.Vertices = PolygonTools.CreateRectangle(1f, 0.125f); Body prevBody = ground; for (int i = 0; i < 3; ++i) { Body body = World.CreateBody(); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(-14.0f + 2.0f * i, 15.0f); body.CreateFixture(shape); Vector2 anchor = new Vector2(-15.0f + 2.0f * i, 15.0f); WeldJoint jd = new WeldJoint(prevBody, body, anchor, anchor, true); jd.FrequencyHz = 5.0f; jd.DampingRatio = 0.7f; World.Add(jd); prevBody = body; } } { PolygonShape shape = new PolygonShape(20f); shape.Vertices = PolygonTools.CreateRectangle(0.5f, 0.125f); Body prevBody = ground; for (int i = 0; i < Count; ++i) { Body body = World.CreateBody(); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(-4.5f + 1.0f * i, 5.0f); body.CreateFixture(shape); if (i > 0) { Vector2 anchor = new Vector2(-5.0f + 1.0f * i, 5.0f); WeldJoint jd = new WeldJoint(prevBody, body, anchor, anchor, true); World.Add(jd); } prevBody = body; } } { PolygonShape shape = new PolygonShape(20f); shape.Vertices = PolygonTools.CreateRectangle(0.5f, 0.125f); Body prevBody = ground; for (int i = 0; i < Count; ++i) { Body body = World.CreateBody(); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(5.5f + 1.0f * i, 10.0f); body.CreateFixture(shape); if (i > 0) { Vector2 anchor = new Vector2(5.0f + 1.0f * i, 10.0f); WeldJoint jd = new WeldJoint(prevBody, body, anchor, anchor, true); jd.FrequencyHz = 8.0f; jd.DampingRatio = 0.7f; World.Add(jd); } prevBody = body; } } //Triangels Vertices vertices = new Vertices(3); vertices.Add(new Vector2(-0.5f, 0.0f)); vertices.Add(new Vector2(0.5f, 0.0f)); vertices.Add(new Vector2(0.0f, 1.5f)); for (int i = 0; i < 2; ++i) { PolygonShape shape = new PolygonShape(vertices, 1); Body body = World.CreateBody(); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(-8.0f + 8.0f * i, 12.0f); body.CreateFixture(shape); } //Circles for (int i = 0; i < 2; ++i) { CircleShape shape = new CircleShape(0.5f, 1); Body body = World.CreateBody(); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(-6.0f + 6.0f * i, 10.0f); body.CreateFixture(shape); } }
/// <summary> /// Calculates the polygon(s) from the result simplical chain. /// </summary> /// <remarks>Used by method <c>Execute()</c>.</remarks> private static PolyClipError BuildPolygonsFromChain(List <Edge> simplicies, out List <Vertices> result) { result = new List <Vertices>(); PolyClipError errVal = PolyClipError.None; while (simplicies.Count > 0) { Vertices output = new Vertices(); output.Add(simplicies[0].EdgeStart); output.Add(simplicies[0].EdgeEnd); simplicies.RemoveAt(0); bool closed = false; int index = 0; int count = simplicies.Count; // Needed to catch infinite loops while (!closed && simplicies.Count > 0) { if (VectorEqual(output[output.Count - 1], simplicies[index].EdgeStart)) { if (VectorEqual(simplicies[index].EdgeEnd, output[0])) { closed = true; } else { output.Add(simplicies[index].EdgeEnd); } simplicies.RemoveAt(index); --index; } else if (VectorEqual(output[output.Count - 1], simplicies[index].EdgeEnd)) { if (VectorEqual(simplicies[index].EdgeStart, output[0])) { closed = true; } else { output.Add(simplicies[index].EdgeStart); } simplicies.RemoveAt(index); --index; } if (!closed) { if (++index == simplicies.Count) { if (count == simplicies.Count) { result = new List <Vertices>(); Debug.WriteLine("Undefined error while building result polygon(s)."); return(PolyClipError.BrokenResult); } index = 0; count = simplicies.Count; } } } if (output.Count < 3) { errVal = PolyClipError.DegeneratedOutput; Debug.WriteLine("Degenerated output polygon produced (vertices < 3)."); } result.Add(output); } return(errVal); }
//Extracted from Box2D /// <summary>Returns the convex hull from the given vertices.</summary> /// <param name="vertices">The vertices.</param> public static Vertices GetConvexHull(Vertices vertices) { if (vertices.Count <= 3) { return(vertices); } // Find the right most point on the hull int i0 = 0; float x0 = vertices[0].X; for (int i = 1; i < vertices.Count; ++i) { float x = vertices[i].X; if (x > x0 || x == x0 && vertices[i].Y < vertices[i0].Y) { i0 = i; x0 = x; } } int[] hull = new int[vertices.Count]; int m = 0; int ih = i0; for (;;) { hull[m] = ih; int ie = 0; for (int j = 1; j < vertices.Count; ++j) { if (ie == ih) { ie = j; continue; } Vector2 r = vertices[ie] - vertices[hull[m]]; Vector2 v = vertices[j] - vertices[hull[m]]; float c = MathUtils.Cross(ref r, ref v); if (c < 0.0f) { ie = j; } // Collinearity check if (c == 0.0f && v.LengthSquared() > r.LengthSquared()) { ie = j; } } ++m; ih = ie; if (ie == i0) { break; } } Vertices result = new Vertices(m); // Copy vertices. for (int i = 0; i < m; ++i) { result.Add(vertices[hull[i]]); } return(result); }
/// <summary> /// Turns a list of triangles into a list of convex polygons. Very simple /// method - start with a seed triangle, keep adding triangles to it until /// you can't add any more without making the polygon non-convex. /// /// Returns an integer telling how many polygons were created. Will fill /// polys array up to polysLength entries, which may be smaller or larger /// than the return value. /// /// Takes O(N/// P) where P is the number of resultant polygons, N is triangle /// count. /// /// The final polygon list will not necessarily be minimal, though in /// practice it works fairly well. /// </summary> /// <param name="triangulated">The triangulated.</param> /// <param name="maxPolys"></param> /// <returns></returns> public static List <Vertices> PolygonizeTriangles(List <Triangle> triangulated, int maxPolys, float tolerance) { List <Vertices> polys = new List <Vertices>(50); int polyIndex = 0; if (triangulated.Count <= 0) { // return empty polygon list return(polys); } bool[] covered = new bool[triangulated.Count]; for (int i = 0; i < triangulated.Count; ++i) { covered[i] = false; // Check here for degenerate triangles if (((triangulated[i].X[0] == triangulated[i].X[1]) && (triangulated[i].Y[0] == triangulated[i].Y[1])) || ((triangulated[i].X[1] == triangulated[i].X[2]) && (triangulated[i].Y[1] == triangulated[i].Y[2])) || ((triangulated[i].X[0] == triangulated[i].X[2]) && (triangulated[i].Y[0] == triangulated[i].Y[2]))) { covered[i] = true; } } bool notDone = true; while (notDone) { int currTri = -1; for (int i = 0; i < triangulated.Count; ++i) { if (covered[i]) { continue; } currTri = i; break; } if (currTri == -1) { notDone = false; } else { Vertices poly = new Vertices(3); for (int i = 0; i < 3; i++) { poly.Add(new Vector2(triangulated[currTri].X[i], triangulated[currTri].Y[i])); } covered[currTri] = true; int index = 0; for (int i = 0; i < 2 * triangulated.Count; ++i, ++index) { while (index >= triangulated.Count) { index -= triangulated.Count; } if (covered[index]) { continue; } Vertices newP = AddTriangle(triangulated[index], poly); if (newP == null) { continue; // is this right } if (newP.Count > Settings.MaxPolygonVertices) { continue; } if (newP.IsConvex()) { // Or should it be IsUsable? Maybe re-write IsConvex to apply the angle threshold from Box2d poly = new Vertices(newP); covered[index] = true; } } // We have a maximum of polygons that we need to keep under. if (polyIndex < maxPolys) { SimplifyTools.MergeParallelEdges(poly, tolerance); // If identical points are present, a triangle gets // borked by the MergeParallelEdges function, hence // the vertex number check if (poly.Count >= 3) { polys.Add(new Vertices(poly)); } // else // printf("Skipping corrupt poly\n"); } if (poly.Count >= 3) { polyIndex++; // Must be outside (polyIndex < polysLength) test } } } return(polys); }
/// <summary> /// This function makes a simple cube shape. /// </summary> private void CreateCubeGeometry() { UVs.Add(new UV(0, 0)); UVs.Add(new UV(0, 1)); UVs.Add(new UV(1, 1)); UVs.Add(new UV(1, 0)); // Add the vertices. Vertices.Add(new Vertex(-1, -1, -1)); Vertices.Add(new Vertex(1, -1, -1)); Vertices.Add(new Vertex(1, -1, 1)); Vertices.Add(new Vertex(-1, -1, 1)); Vertices.Add(new Vertex(-1, 1, -1)); Vertices.Add(new Vertex(1, 1, -1)); Vertices.Add(new Vertex(1, 1, 1)); Vertices.Add(new Vertex(-1, 1, 1)); // Add the faces. Face face = new Face(); // bottom face.Indices.Add(new Index(1, 0)); face.Indices.Add(new Index(2, 1)); face.Indices.Add(new Index(3, 2)); face.Indices.Add(new Index(0, 3)); Faces.Add(face); face = new Face(); // top face.Indices.Add(new Index(7, 0)); face.Indices.Add(new Index(6, 1)); face.Indices.Add(new Index(5, 2)); face.Indices.Add(new Index(4, 3)); Faces.Add(face); face = new Face(); // right face.Indices.Add(new Index(5, 0)); face.Indices.Add(new Index(6, 1)); face.Indices.Add(new Index(2, 2)); face.Indices.Add(new Index(1, 3)); Faces.Add(face); face = new Face(); // left face.Indices.Add(new Index(7, 0)); face.Indices.Add(new Index(4, 1)); face.Indices.Add(new Index(0, 2)); face.Indices.Add(new Index(3, 3)); Faces.Add(face); face = new Face(); // front face.Indices.Add(new Index(4, 0)); face.Indices.Add(new Index(5, 1)); face.Indices.Add(new Index(1, 2)); face.Indices.Add(new Index(0, 3)); Faces.Add(face); face = new Face(); // back face.Indices.Add(new Index(6, 0)); face.Indices.Add(new Index(7, 1)); face.Indices.Add(new Index(3, 2)); face.Indices.Add(new Index(2, 3)); Faces.Add(face); }
private ApplyForceTest() { World.Gravity = Vector2.Zero; const float restitution = 0.4f; Body ground; { ground = BodyFactory.CreateBody(World); ground.Position = new Vector2(0.0f, 20.0f); EdgeShape shape = new EdgeShape(new Vector2(-20.0f, -20.0f), new Vector2(-20.0f, 20.0f)); // Left vertical Fixture fixture = ground.CreateFixture(shape); fixture.Restitution = restitution; // Right vertical shape = new EdgeShape(new Vector2(20.0f, -20.0f), new Vector2(20.0f, 20.0f)); ground.CreateFixture(shape); // Top horizontal shape = new EdgeShape(new Vector2(-20.0f, 20.0f), new Vector2(20.0f, 20.0f)); ground.CreateFixture(shape); // Bottom horizontal shape = new EdgeShape(new Vector2(-20.0f, -20.0f), new Vector2(20.0f, -20.0f)); ground.CreateFixture(shape); } { Transform xf1 = new Transform(); xf1.q.Set(0.3524f * Settings.Pi); xf1.p = MathUtils.Mul(ref xf1.q, new Vector2(1.0f, 0.0f)); Vertices vertices = new Vertices(3); vertices.Add(MathUtils.Mul(ref xf1, new Vector2(-1.0f, 0.0f))); vertices.Add(MathUtils.Mul(ref xf1, new Vector2(1.0f, 0.0f))); vertices.Add(MathUtils.Mul(ref xf1, new Vector2(0.0f, 0.5f))); PolygonShape poly1 = new PolygonShape(vertices, 4); Transform xf2 = new Transform(); xf2.q.Set(-0.3524f * Settings.Pi); xf2.p = MathUtils.Mul(ref xf2.q, new Vector2(-1.0f, 0.0f)); vertices[0] = MathUtils.Mul(ref xf2, new Vector2(-1.0f, 0.0f)); vertices[1] = MathUtils.Mul(ref xf2, new Vector2(1.0f, 0.0f)); vertices[2] = MathUtils.Mul(ref xf2, new Vector2(0.0f, 0.5f)); PolygonShape poly2 = new PolygonShape(vertices, 2); _body = BodyFactory.CreateBody(World); _body.BodyType = BodyType.Dynamic; _body.Position = new Vector2(0.0f, 2.0f); _body.Rotation = Settings.Pi; _body.AngularDamping = 5.0f; _body.LinearDamping = 0.8f; _body.SleepingAllowed = true; _body.CreateFixture(poly1); _body.CreateFixture(poly2); } { Vertices box = PolygonTools.CreateRectangle(0.5f, 0.5f); PolygonShape shape = new PolygonShape(box, 1); for (int i = 0; i < 10; ++i) { Body body = BodyFactory.CreateBody(World); body.Position = new Vector2(0.0f, 5.0f + 1.54f * i); body.BodyType = BodyType.Dynamic; Fixture fixture = body.CreateFixture(shape); fixture.Friction = 0.3f; const float gravity = 10.0f; float I = body.Inertia; float mass = body.Mass; // For a circle: I = 0.5 * m * r * r ==> r = sqrt(2 * I / m) float radius = (float)Math.Sqrt(2.0 * (I / mass)); FrictionJoint jd = new FrictionJoint(ground, body, Vector2.Zero); jd.CollideConnected = true; jd.MaxForce = mass * gravity; jd.MaxTorque = mass * radius * gravity; World.AddJoint(jd); } } }
BridgeTest() { Body ground; { ground = new Body(World); EdgeShape shape = new EdgeShape(new Vector2(-40.0f, 0.0f), new Vector2(40.0f, 0.0f)); ground.CreateFixture(shape); } { Vertices box = PolygonTools.CreateRectangle(0.5f, 0.125f); PolygonShape shape = new PolygonShape(box, 20); Body prevBody = ground; for (int i = 0; i < Count; ++i) { Body body = BodyFactory.CreateBody(World); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(-14.5f + 1.0f * i, 5.0f); Fixture fixture = body.CreateFixture(shape); fixture.Friction = 0.2f; Vector2 anchor = new Vector2(-15f + 1.0f * i, 5.0f); RevoluteJoint jd = new RevoluteJoint(prevBody, body, anchor, true); World.AddJoint(jd); prevBody = body; } Vector2 anchor2 = new Vector2(-15.0f + 1.0f * Count, 5.0f); RevoluteJoint jd2 = new RevoluteJoint(ground, prevBody, anchor2, true); World.AddJoint(jd2); } Vertices vertices = new Vertices(3); vertices.Add(new Vector2(-0.5f, 0.0f)); vertices.Add(new Vector2(0.5f, 0.0f)); vertices.Add(new Vector2(0.0f, 1.5f)); for (int i = 0; i < 2; ++i) { PolygonShape shape = new PolygonShape(vertices, 1); Body body = BodyFactory.CreateBody(World); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(-8.0f + 8.0f * i, 12.0f); body.CreateFixture(shape); } for (int i = 0; i < 3; ++i) { CircleShape shape = new CircleShape(0.5f, 1); Body body = BodyFactory.CreateBody(World); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(-6.0f + 6.0f * i, 10.0f); body.CreateFixture(shape); } }
/// <summary>Returns the convex hull from the given vertices..</summary> public static Vertices GetConvexHull(Vertices vertices) { if (vertices.Count <= 3) { return(vertices); } Vertices pointSet = new Vertices(vertices); //Sort by X-axis pointSet.Sort(PointComparerPrivate); Vector2[] h = new Vector2[pointSet.Count]; Vertices res; int top = -1; // indices for bottom and top of the stack int i; // array scan index // Get the indices of points with min x-coord and min|max y-coord const int minmin = 0; float xmin = pointSet[0].X; for (i = 1; i < pointSet.Count; i++) { if (pointSet[i].X != xmin) { break; } } // degenerate case: all x-coords == xmin int minmax = i - 1; if (minmax == pointSet.Count - 1) { h[++top] = pointSet[minmin]; if (pointSet[minmax].Y != pointSet[minmin].Y) // a nontrivial segment { h[++top] = pointSet[minmax]; } h[++top] = pointSet[minmin]; // add polygon endpoint res = new Vertices(top + 1); for (int j = 0; j < top + 1; j++) { res.Add(h[j]); } return(res); } top = -1; // Get the indices of points with max x-coord and min|max y-coord int maxmax = pointSet.Count - 1; float xmax = pointSet[pointSet.Count - 1].X; for (i = pointSet.Count - 2; i >= 0; i--) { if (pointSet[i].X != xmax) { break; } } int maxmin = i + 1; // Compute the lower hull on the stack H h[++top] = pointSet[minmin]; // push minmin point onto stack i = minmax; while (++i <= maxmin) { // the lower line joins P[minmin] with P[maxmin] if (MathUtils.Area(pointSet[minmin], pointSet[maxmin], pointSet[i]) >= 0 && i < maxmin) { continue; // ignore P[i] above or on the lower line } while (top > 0) // there are at least 2 points on the stack { // test if P[i] is left of the line at the stack top if (MathUtils.Area(h[top - 1], h[top], pointSet[i]) > 0) { break; // P[i] is a new hull vertex } top--; // pop top point off stack } h[++top] = pointSet[i]; // push P[i] onto stack } // GetNext, compute the upper hull on the stack H above the bottom hull if (maxmax != maxmin) // if distinct xmax points { h[++top] = pointSet[maxmax]; // push maxmax point onto stack } int bot = top; i = maxmin; while (--i >= minmax) { // the upper line joins P[maxmax] with P[minmax] if (MathUtils.Area(pointSet[maxmax], pointSet[minmax], pointSet[i]) >= 0 && i > minmax) { continue; // ignore P[i] below or on the upper line } while (top > bot) // at least 2 points on the upper stack { // test if P[i] is left of the line at the stack top if (MathUtils.Area(h[top - 1], h[top], pointSet[i]) > 0) { break; // P[i] is a new hull vertex } top--; // pop top point off stack } h[++top] = pointSet[i]; // push P[i] onto stack } if (minmax != minmin) { h[++top] = pointSet[minmin]; // push joining endpoint onto stack } res = new Vertices(top + 1); for (int j = 0; j < top + 1; j++) { res.Add(h[j]); } return(res); }
public Border(World world, PhysicsGameScreen screen, Viewport viewport) { _world = world; _screen = screen; float halfWidth = ConvertUnits.ToSimUnits(viewport.Width) / 2f; float halfHeight = ConvertUnits.ToSimUnits(viewport.Height) / 2f; Vertices borders = new Vertices(4); borders.Add(new Vector2(-halfWidth, halfHeight)); borders.Add(new Vector2(halfWidth, halfHeight)); #if IPAD //Room on top borders.Add(new Vector2(halfWidth + 28, -halfHeight - 5)); //Room on top borders.Add(new Vector2(-halfWidth - 28, -halfHeight - 5)); #else //Room on top borders.Add(new Vector2(halfWidth + 16, -halfHeight - 5)); //Room on top borders.Add(new Vector2(-halfWidth - 16, -halfHeight - 5)); #endif _anchor = BodyFactory.CreateLoopShape(_world, borders); _anchor.CollisionCategories = Category.All; _anchor.CollidesWith = Category.All; _basicEffect = new BasicEffect(_screen.ScreenManager.GraphicsDevice); _basicEffect.VertexColorEnabled = true; _basicEffect.TextureEnabled = true; _basicEffect.Texture = _screen.ScreenManager.Content.Load <Texture2D>("Materials/blank"); VertexPositionColorTexture[] vertice = new VertexPositionColorTexture[8]; //UpperLeft vertice[0] = new VertexPositionColorTexture(new Vector3(-halfWidth, -halfHeight - 2, 0f), Color.Red, new Vector2(-halfWidth, -halfHeight)); //UpperRight vertice[1] = new VertexPositionColorTexture(new Vector3(halfWidth, -halfHeight - 2, 0f), Color.Red, new Vector2(halfWidth, -halfHeight)); vertice[2] = new VertexPositionColorTexture(new Vector3(halfWidth, halfHeight, 0f), Color.Red, new Vector2(halfWidth, halfHeight)); vertice[3] = new VertexPositionColorTexture(new Vector3(-halfWidth, halfHeight, 0f), Color.Red, new Vector2(-halfWidth, halfHeight)); vertice[4] = new VertexPositionColorTexture(new Vector3(-halfWidth - 2f, -halfHeight - 2f, 0f), Color.Red, new Vector2(-halfWidth - 2f, -halfHeight - 2f)); vertice[5] = new VertexPositionColorTexture(new Vector3(halfWidth + 2f, -halfHeight - 2f, 0f), Color.Red, new Vector2(halfWidth + 2f, -halfHeight - 2f)); vertice[6] = new VertexPositionColorTexture(new Vector3(halfWidth + 2f, halfHeight + 2f, 0f), Color.Red, new Vector2(halfWidth + 2f, halfHeight + 2f)); vertice[7] = new VertexPositionColorTexture(new Vector3(-halfWidth - 2f, halfHeight + 2f, 0f), Color.Red, new Vector2(-halfWidth - 2f, halfHeight + 2f)); _borderVerts = new VertexPositionColorTexture[24]; _borderVerts[0] = vertice[0]; _borderVerts[1] = vertice[5]; _borderVerts[2] = vertice[4]; _borderVerts[3] = vertice[0]; _borderVerts[4] = vertice[1]; _borderVerts[5] = vertice[5]; _borderVerts[6] = vertice[1]; _borderVerts[7] = vertice[6]; _borderVerts[8] = vertice[5]; _borderVerts[9] = vertice[1]; _borderVerts[10] = vertice[2]; _borderVerts[11] = vertice[6]; _borderVerts[12] = vertice[2]; _borderVerts[13] = vertice[7]; _borderVerts[14] = vertice[6]; _borderVerts[15] = vertice[2]; _borderVerts[16] = vertice[3]; _borderVerts[17] = vertice[7]; _borderVerts[18] = vertice[3]; _borderVerts[19] = vertice[4]; _borderVerts[20] = vertice[7]; _borderVerts[21] = vertice[3]; _borderVerts[22] = vertice[0]; _borderVerts[23] = vertice[4]; }
private CarTest() { _hz = 4.0f; _zeta = 0.7f; _speed = 50.0f; Body ground = BodyFactory.CreateEdge(World, new Vector2(-20.0f, 0.0f), new Vector2(20.0f, 0.0f)); { float[] hs = { 0.25f, 1.0f, 4.0f, 0.0f, 0.0f, -1.0f, -2.0f, -2.0f, -1.25f, 0.0f }; float x = 20.0f, y1 = 0.0f; const float dx = 5.0f; for (int i = 0; i < 10; ++i) { float y2 = hs[i]; FixtureFactory.AttachEdge(new Vector2(x, y1), new Vector2(x + dx, y2), ground); y1 = y2; x += dx; } for (int i = 0; i < 10; ++i) { float y2 = hs[i]; FixtureFactory.AttachEdge(new Vector2(x, y1), new Vector2(x + dx, y2), ground); y1 = y2; x += dx; } FixtureFactory.AttachEdge(new Vector2(x, 0.0f), new Vector2(x + 40.0f, 0.0f), ground); x += 80.0f; FixtureFactory.AttachEdge(new Vector2(x, 0.0f), new Vector2(x + 40.0f, 0.0f), ground); x += 40.0f; FixtureFactory.AttachEdge(new Vector2(x, 0.0f), new Vector2(x + 10.0f, 5.0f), ground); x += 20.0f; FixtureFactory.AttachEdge(new Vector2(x, 0.0f), new Vector2(x + 40.0f, 0.0f), ground); x += 40.0f; FixtureFactory.AttachEdge(new Vector2(x, 0.0f), new Vector2(x, 20.0f), ground); ground.Friction = 0.6f; } // Teeter { Body body = new Body(World); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(140.0f, 1.0f); PolygonShape box = new PolygonShape(1); box.Vertices = PolygonUtils.CreateRectangle(10.0f, 0.25f); body.CreateFixture(box); RevoluteJoint jd = JointFactory.CreateRevoluteJoint(World, ground, body, Vector2.Zero); jd.LowerLimit = -8.0f * Settings.Pi / 180.0f; jd.UpperLimit = 8.0f * Settings.Pi / 180.0f; jd.LimitEnabled = true; body.ApplyAngularImpulse(100.0f); } //Bridge { const int N = 20; PolygonShape shape = new PolygonShape(1); shape.Vertices = PolygonUtils.CreateRectangle(1.0f, 0.125f); Body prevBody = ground; for (int i = 0; i < N; ++i) { Body body = new Body(World); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(161.0f + 2.0f * i, -0.125f); Fixture fix = body.CreateFixture(shape); fix.Friction = 0.6f; Vector2 anchor = new Vector2(-1, 0); JointFactory.CreateRevoluteJoint(World, prevBody, body, anchor); prevBody = body; } Vector2 anchor2 = new Vector2(1.0f, 0); JointFactory.CreateRevoluteJoint(World, ground, prevBody, anchor2); } // Boxes { PolygonShape box = new PolygonShape(0.5f); box.Vertices = PolygonUtils.CreateRectangle(0.5f, 0.5f); Body body = new Body(World); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(230.0f, 0.5f); body.CreateFixture(box); body = new Body(World); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(230.0f, 1.5f); body.CreateFixture(box); body = new Body(World); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(230.0f, 2.5f); body.CreateFixture(box); body = new Body(World); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(230.0f, 3.5f); body.CreateFixture(box); body = new Body(World); body.BodyType = BodyType.Dynamic; body.Position = new Vector2(230.0f, 4.5f); body.CreateFixture(box); } // Car { Vertices vertices = new Vertices(8); vertices.Add(new Vector2(-1.5f, -0.5f)); vertices.Add(new Vector2(1.5f, -0.5f)); vertices.Add(new Vector2(1.5f, 0.0f)); vertices.Add(new Vector2(0.0f, 0.9f)); vertices.Add(new Vector2(-1.15f, 0.9f)); vertices.Add(new Vector2(-1.5f, 0.2f)); PolygonShape chassis = new PolygonShape(vertices, 1); CircleShape circle = new CircleShape(0.4f, 1); _car = new Body(World); _car.BodyType = BodyType.Dynamic; _car.Position = new Vector2(0.0f, 1.0f); _car.CreateFixture(chassis); _wheel1 = new Body(World); _wheel1.BodyType = BodyType.Dynamic; _wheel1.Position = new Vector2(-1.0f, 0.35f); _wheel1.CreateFixture(circle); _wheel1.Friction = 0.9f; _wheel2 = new Body(World); _wheel2.BodyType = BodyType.Dynamic; _wheel2.Position = new Vector2(1.0f, 0.4f); _wheel2.CreateFixture(circle); _wheel2.Friction = 0.9f; Vector2 axis = new Vector2(0.0f, 1.0f); _spring1 = new WheelJoint(_car, _wheel1, _wheel1.Position, axis, true); _spring1.MotorSpeed = 0.0f; _spring1.MaxMotorTorque = 20.0f; _spring1.MotorEnabled = true; _spring1.Frequency = _hz; _spring1.DampingRatio = _zeta; World.AddJoint(_spring1); _spring2 = new WheelJoint(_car, _wheel2, _wheel2.Position, axis, true); _spring2.MotorSpeed = 0.0f; _spring2.MaxMotorTorque = 10.0f; _spring2.MotorEnabled = false; _spring2.Frequency = _hz; _spring2.DampingRatio = _zeta; World.AddJoint(_spring2); } }
/// <summary> /// Activate the explosion at the specified position. /// </summary> /// <param name="pos">The position where the explosion happens </param> /// <param name="radius">The explosion radius </param> /// <param name="maxForce">The explosion force at the explosion point (then is inversely proportional to the square of the distance)</param> /// <returns>A list of bodies and the amount of force that was applied to them.</returns> public Dictionary <Fixture, Vector2> Activate(Vector2 pos, float radius, float maxForce) { AABB aabb; aabb.LowerBound = pos + new Vector2(-radius, -radius); aabb.UpperBound = pos + new Vector2(radius, radius); var shapes = new Fixture[MaxShapes]; // More than 5 shapes in an explosion could be possible, but still strange. var containedShapes = new Fixture[5]; bool exit = false; int shapeCount = 0; int containedShapeCount = 0; // Query the world for overlapping shapes. World.QueryAABB( fixture => { if (fixture.TestPoint(ref pos)) { if (IgnoreWhenInsideShape) { exit = true; return(false); } containedShapes[containedShapeCount++] = fixture; } else { shapes[shapeCount++] = fixture; } // Continue the query. return(true); }, ref aabb); if (exit) { return(new Dictionary <Fixture, Vector2>()); } var exploded = new Dictionary <Fixture, Vector2>(shapeCount + containedShapeCount); // Per shape max/min angles for now. var vals = new float[shapeCount * 2]; int valIndex = 0; for (int i = 0; i < shapeCount; ++i) { PolygonShape ps; var cs = shapes[i].Shape as CircleShape; if (cs != null) { // We create a "diamond" approximation of the circle var v = new Vertices(); var vec = Vector2.Zero + new Vector2(cs.Radius, 0); v.Add(vec); vec = Vector2.Zero + new Vector2(0, cs.Radius); v.Add(vec); vec = Vector2.Zero + new Vector2(-cs.Radius, cs.Radius); v.Add(vec); vec = Vector2.Zero + new Vector2(0, -cs.Radius); v.Add(vec); ps = new PolygonShape(v, 0); } else { ps = shapes[i].Shape as PolygonShape; } if ((shapes[i].Body.BodyType == BodyType.Dynamic) && ps != null) { var toCentroid = shapes[i].Body.GetWorldPoint(ps.MassData.Centroid) - pos; var angleToCentroid = (float)Math.Atan2(toCentroid.Y, toCentroid.X); var min = float.MaxValue; var max = float.MinValue; var minAbsolute = 0.0f; var maxAbsolute = 0.0f; for (var j = 0; j < ps.Vertices.Count; ++j) { var toVertex = (shapes[i].Body.GetWorldPoint(ps.Vertices[j]) - pos); var newAngle = (float)Math.Atan2(toVertex.Y, toVertex.X); var diff = (newAngle - angleToCentroid); diff = (diff - MathHelper.Pi) % (2 * MathHelper.Pi); // the minus pi is important. It means cutoff for going other direction is at 180 deg where it needs to be if (diff < 0.0f) { diff += 2 * MathHelper.Pi; // correction for not handling negs } diff -= MathHelper.Pi; if (Math.Abs(diff) > MathHelper.Pi) { continue; // Something's wrong, point not in shape but exists angle diff > 180 } if (diff > max) { max = diff; maxAbsolute = newAngle; } if (diff < min) { min = diff; minAbsolute = newAngle; } } vals[valIndex] = minAbsolute; ++valIndex; vals[valIndex] = maxAbsolute; ++valIndex; } } Array.Sort(vals, 0, valIndex, _rdc); _data.Clear(); var rayMissed = true; for (var i = 0; i < valIndex; ++i) { Fixture fixture = null; float midpt; var iplus = (i == valIndex - 1 ? 0 : i + 1); if (vals[i] == vals[iplus]) { continue; } if (i == valIndex - 1) { // the single edgecase midpt = (vals[0] + MathHelper.Pi * 2 + vals[i]); } else { midpt = (vals[i + 1] + vals[i]); } midpt = midpt / 2; var p1 = pos; var p2 = radius * new Vector2((float)Math.Cos(midpt), (float)Math.Sin(midpt)) + pos; // RaycastOne bool hitClosest = false; World.RayCast((f, p, n, fr) => { var body = f.Body; if (!IsActiveOn(body)) { return(0); } hitClosest = true; fixture = f; return(fr); }, p1, p2); // draws radius points if ((hitClosest) && (fixture.Body.BodyType == BodyType.Dynamic)) { if ((_data.Any()) && (_data.Last().Body == fixture.Body) && (!rayMissed)) { var laPos = _data.Count - 1; var la = _data[laPos]; la.Max = vals[iplus]; _data[laPos] = la; } else { // make new ShapeData d; d.Body = fixture.Body; d.Min = vals[i]; d.Max = vals[iplus]; _data.Add(d); } if ((_data.Count > 1) && (i == valIndex - 1) && (_data.Last().Body == _data.First().Body) && (_data.Last().Max == _data.First().Min)) { var fi = _data[0]; fi.Min = _data.Last().Min; _data.RemoveAt(_data.Count - 1); _data[0] = fi; while (_data.First().Min >= _data.First().Max) { fi.Min -= MathHelper.Pi * 2; _data[0] = fi; } } var lastPos = _data.Count - 1; var last = _data[lastPos]; while ((_data.Count > 0) && (_data.Last().Min >= _data.Last().Max)) // just making sure min<max { last.Min = _data.Last().Min - 2 * MathHelper.Pi; _data[lastPos] = last; } rayMissed = false; } else { rayMissed = true; // raycast did not find a shape } } for (int i = 0; i < _data.Count; ++i) { if (!IsActiveOn(_data[i].Body)) { continue; } var arclen = _data[i].Max - _data[i].Min; var first = MathHelper.Min(maxEdgeOffset, EdgeRatio * arclen); var insertedRays = (int)Math.Ceiling(((arclen - 2.0f * first) - (MinRays - 1) * MaxAngle) / MaxAngle); if (insertedRays < 0) { insertedRays = 0; } float offset = (arclen - first * 2.0f) / ((float)MinRays + insertedRays - 1); //Note: This loop can go into infinite as it operates on floats. //Added FloatEquals with a large epsilon. for (float j = _data[i].Min + first; j < _data[i].Max || MathUtils.FloatEquals(j, _data[i].Max, 0.0001f); j += offset) { var p1 = pos; var p2 = pos + radius * new Vector2((float)Math.Cos(j), (float)Math.Sin(j)); var hitpoint = Vector2.Zero; var minlambda = float.MaxValue; var fl = _data[i].Body.FixtureList; for (int x = 0; x < fl.Count; x++) { Fixture f = fl[x]; RayCastInput ri; ri.Point1 = p1; ri.Point2 = p2; ri.MaxFraction = 50f; RayCastOutput ro; if (f.RayCast(out ro, ref ri, 0)) { if (minlambda > ro.Fraction) { minlambda = ro.Fraction; hitpoint = ro.Fraction * p2 + (1 - ro.Fraction) * p1; } } // the force that is to be applied for this particular ray. // offset is angular coverage. lambda*length of segment is distance. var impulse = (arclen / (MinRays + insertedRays)) * maxForce * 180.0f / MathHelper.Pi * (1.0f - Math.Min(1.0f, minlambda)); // We Apply the impulse!!! var vectImp = Vector2.Dot(impulse * new Vector2((float)Math.Cos(j), (float)Math.Sin(j)), -ro.Normal) * new Vector2((float)Math.Cos(j), (float)Math.Sin(j)); _data[i].Body.ApplyLinearImpulse(ref vectImp, ref hitpoint); // We gather the fixtures for returning them if (exploded.ContainsKey(f)) { exploded[f] += vectImp; } else { exploded.Add(f, vectImp); } if (minlambda > 1.0f) { hitpoint = p2; } } } } // We check contained shapes for (var i = 0; i < containedShapeCount; ++i) { var fix = containedShapes[i]; if (!IsActiveOn(fix.Body)) { continue; } var impulse = MinRays * maxForce * 180.0f / MathHelper.Pi; Vector2 hitPoint; var circShape = fix.Shape as CircleShape; if (circShape != null) { hitPoint = fix.Body.GetWorldPoint(circShape.Position); } else { var shape = fix.Shape as PolygonShape; hitPoint = fix.Body.GetWorldPoint(shape.MassData.Centroid); } var vectImp = impulse * (hitPoint - pos); fix.Body.ApplyLinearImpulse(ref vectImp, ref hitPoint); if (!exploded.ContainsKey(fix)) { exploded.Add(fix, vectImp); } } return(exploded); }
protected override void LoadContent(PloobsEngine.Engine.GraphicInfo GraphicInfo, PloobsEngine.Engine.GraphicFactory factory, PloobsEngine.SceneControl.IContentManager contentManager) { tile = factory.GetTexture2D("Textures/tile"); FarseerWorld fworld = this.World.PhysicWorld as FarseerWorld; //ground { Vertices Vertices = new Vertices(3); Vertices.Add(new Vector2(-200, 0)); Vertices.Add(new Vector2(0, 200)); Vertices.Add(new Vector2(200, 0)); SpriteFarseer SpriteFarseer = new SpriteFarseer(factory, Vertices, Color.Red); Basic2DTextureMaterial mat = new Basic2DTextureMaterial(); FarseerObject fs = new FarseerObject(fworld, SpriteFarseer, 1, BodyType.Static); I2DObject o = new I2DObject(fs, mat, SpriteFarseer); this.World.AddObject(o); } ///from texture { Texture2D tex = factory.GetTexture2D("Textures//goo"); IModelo2D model = new SpriteFarseer(tex); Basic2DTextureMaterial mat = new Basic2DTextureMaterial(); FarseerObject fs = new FarseerObject(fworld, tex); I2DObject o = new I2DObject(fs, mat, model); this.World.AddObject(o); } ///rectangle Vertices verts = PolygonTools.CreateRectangle(50, 50); { IModelo2D model = new SpriteFarseer(factory, verts, Color.Red); model.LayerDepth = 0; Basic2DTextureMaterial mat = new Basic2DTextureMaterial(); FarseerObject fs = new FarseerObject(fworld, model, 1, BodyType.Static); I2DObject o = new I2DObject(fs, mat, model); this.World.AddObject(o); } //rectangle //cria em Display verts = PolygonTools.CreateRectangle(50, 50); { IModelo2D model = new SpriteFarseer(factory, verts, Color.Green); model.LayerDepth = 1; Basic2DTextureMaterial mat = new Basic2DTextureMaterial(); FarseerObject fs = new FarseerObject(fworld, model, 1, BodyType.Static); I2DObject o = new I2DObject(fs, mat, model); o.PhysicObject.Position = new Vector2(50, 50); this.World.AddObject(o); } ///rectangle verts = PolygonTools.CreateRectangle(50, 50); { IModelo2D model = new SpriteFarseer(factory, verts, Color.Orange); model.LayerDepth = 0; Basic2DTextureMaterial mat = new Basic2DTextureMaterial(); FarseerObject fs = new FarseerObject(fworld, model, 1, BodyType.Static); I2DObject o = new I2DObject(fs, mat, model); o.PhysicObject.Position = new Vector2(-GraphicInfo.BackBufferWidth / 2, 0); this.World.AddObject(o); } ///circle CircleShape circle = new CircleShape(50, 1); { IModelo2D model = new SpriteFarseer(factory, circle, Color.Yellow); Basic2DTextureMaterial mat = new Basic2DTextureMaterial(); FarseerObject fs = new FarseerObject(fworld, model); I2DObject o = new I2DObject(fs, mat, model); o.PhysicObject.Position = new Vector2(0, -GraphicInfo.BackBufferHeight / 2); this.World.AddObject(o); } ///animated sprite { Texture2D tex = factory.GetTexture2D("Textures//DudeSheet"); SpriteAnimated sa = new SpriteAnimated(tex, 8, 2); sa.AddAnimation("ANIM1", 1, 8, 0); sa.AddAnimation("ANIM2", 2, 4, MathHelper.PiOver2); Basic2DTextureMaterial mat = new Basic2DTextureMaterial(); Texture2D frame = factory.GetTexturePart(tex, sa.GetFrameRectangle("ANIM1", 0)); FarseerObject fs = new FarseerObject(fworld, frame); I2DObject sheet = new I2DObject(fs, mat, sa); sheet.PhysicObject.Position = new Vector2(100, 100); this.World.AddObject(sheet); } ///camera this.World.Camera2D = new Camera2D(GraphicInfo); base.LoadContent(GraphicInfo, factory, contentManager); }
private void CreateLeg(float s, Vector2 wheelAnchor) { Vector2 p1 = new Vector2(5.4f * s, -6.1f); Vector2 p2 = new Vector2(7.2f * s, -1.2f); Vector2 p3 = new Vector2(4.3f * s, -1.9f); Vector2 p4 = new Vector2(3.1f * s, 0.8f); Vector2 p5 = new Vector2(6.0f * s, 1.5f); Vector2 p6 = new Vector2(2.5f * s, 3.7f); PolygonShape poly1 = new PolygonShape(1); PolygonShape poly2 = new PolygonShape(1); Vertices vertices = new Vertices(3); if (s > 0.0f) { vertices.Add(p1); vertices.Add(p2); vertices.Add(p3); poly1.Vertices = vertices; vertices[0] = Vector2.Zero; vertices[1] = p5 - p4; vertices[2] = p6 - p4; poly2.Vertices = vertices; } else { vertices.Add(p1); vertices.Add(p3); vertices.Add(p2); poly1.Vertices = vertices; vertices[0] = Vector2.Zero; vertices[1] = p6 - p4; vertices[2] = p5 - p4; poly2.Vertices = vertices; } Body body1 = BodyFactory.CreateBody(World); body1.BodyType = BodyType.Dynamic; body1.Position = _offset; body1.AngularDamping = 10.0f; Body body2 = BodyFactory.CreateBody(World); body2.BodyType = BodyType.Dynamic; body2.Position = p4 + _offset; body2.AngularDamping = 10.0f; Fixture f1 = body1.CreateFixture(poly1); f1.CollisionGroup = -1; Fixture f2 = body2.CreateFixture(poly2); f2.CollisionGroup = -1; // Using a soft distanceraint can reduce some jitter. // It also makes the structure seem a bit more fluid by // acting like a suspension system. DistanceJoint djd = new DistanceJoint(body1, body2, p2 + _offset, p5 + _offset, true); djd.DampingRatio = 0.5f; djd.Frequency = 10.0f; World.AddJoint(djd); DistanceJoint djd2 = new DistanceJoint(body1, body2, p3 + _offset, p4 + _offset, true); djd2.DampingRatio = 0.5f; djd2.Frequency = 10.0f; World.AddJoint(djd2); DistanceJoint djd3 = new DistanceJoint(body1, _wheel, p3 + _offset, wheelAnchor + _offset, true); djd3.DampingRatio = 0.5f; djd3.Frequency = 10.0f; World.AddJoint(djd3); DistanceJoint djd4 = new DistanceJoint(body2, _wheel, p6 + _offset, wheelAnchor + _offset, true); djd4.DampingRatio = 0.5f; djd4.Frequency = 10.0f; World.AddJoint(djd4); Vector2 anchor = p4 - new Vector2(0.0f, 0.8f) /*+ _offset*/; RevoluteJoint rjd = new RevoluteJoint(body2, _chassis, p4 + _offset, true); World.AddJoint(rjd); }
/// <summary> /// Decompose the polygon into triangles /// </summary> /// <param name="contour">The list of points describing the polygon</param> /// <returns></returns> public static List <Vertices> ConvexPartition(Vertices contour) { int n = contour.Count; if (n < 3) { return(new List <Vertices>()); } int[] V = new int[n]; // We want a counter-clockwise polygon in V if (contour.IsCounterClockWise()) { for (int v = 0; v < n; v++) { V[v] = v; } } else { for (int v = 0; v < n; v++) { V[v] = (n - 1) - v; } } int nv = n; // Remove nv-2 Vertices, creating 1 triangle every time int count = 2 * nv; /* error detection */ List <Vertices> result = new List <Vertices>(); for (int v = nv - 1; nv > 2;) { // If we loop, it is probably a non-simple polygon if (0 >= (count--)) { // Triangulate: ERROR - probable bad polygon! return(new List <Vertices>()); } // Three consecutive vertices in current polygon, <u,v,w> int u = v; if (nv <= u) { u = 0; // Previous } v = u + 1; if (nv <= v) { v = 0; // New v } int w = v + 1; if (nv <= w) { w = 0; // Next } _tmpA = contour[V[u]]; _tmpB = contour[V[v]]; _tmpC = contour[V[w]]; if (Snip(contour, u, v, w, nv, V)) { int s, t; // Output Triangle Vertices triangle = new Vertices(3); triangle.Add(_tmpA); triangle.Add(_tmpB); triangle.Add(_tmpC); result.Add(triangle); // Remove v from remaining polygon for (s = v, t = v + 1; t < nv; s++, t++) { V[s] = V[t]; } nv--; // Reset error detection counter count = 2 * nv; } } return(result); }
private EdgeShapesTest() { // Ground body { Body ground = BodyFactory.CreateBody(World); float x1 = -20.0f; float y1 = 2.0f * (float)Math.Cos(x1 / 10.0f * (float)Math.PI); for (int i = 0; i < 80; ++i) { float x2 = x1 + 0.5f; float y2 = 2.0f * (float)Math.Cos(x2 / 10.0f * (float)Math.PI); EdgeShape shape = new EdgeShape(new Vector2(x1, y1), new Vector2(x2, y2)); ground.CreateFixture(shape); x1 = x2; y1 = y2; } } { Vertices vertices = new Vertices(3); vertices.Add(new Vector2(-0.5f, 0.0f)); vertices.Add(new Vector2(0.5f, 0.0f)); vertices.Add(new Vector2(0.0f, 1.5f)); _polygons[0] = new PolygonShape(vertices, 20); } { Vertices vertices = new Vertices(3); vertices.Add(new Vector2(-0.1f, 0.0f)); vertices.Add(new Vector2(0.1f, 0.0f)); vertices.Add(new Vector2(0.0f, 1.5f)); _polygons[1] = new PolygonShape(vertices, 20); } { const float w = 1.0f; float b = w / (2.0f + (float)Math.Sqrt(2.0f)); float s = (float)Math.Sqrt(2.0f) * b; Vertices vertices = new Vertices(8); vertices.Add(new Vector2(0.5f * s, 0.0f)); vertices.Add(new Vector2(0.5f * w, b)); vertices.Add(new Vector2(0.5f * w, b + s)); vertices.Add(new Vector2(0.5f * s, w)); vertices.Add(new Vector2(-0.5f * s, w)); vertices.Add(new Vector2(-0.5f * w, b + s)); vertices.Add(new Vector2(-0.5f * w, b)); vertices.Add(new Vector2(-0.5f * s, 0.0f)); _polygons[2] = new PolygonShape(vertices, 20); } { _polygons[3] = new PolygonShape(20); _polygons[3].Vertices = PolygonUtils.CreateRectangle(0.5f, 0.5f); } { _circle = new CircleShape(0.5f, 1); } _bodyIndex = 0; _angle = 0.0f; }
public static List<Vertices> ConvexPartition(Vertices vertices) { Polygon poly = new Polygon(); foreach (FVector2 vertex in vertices) { poly.Points.Add(new TriangulationPoint(vertex.X, vertex.Y)); } DTSweepContext tcx = new DTSweepContext(); tcx.PrepareTriangulation(poly); DTSweep.Triangulate(tcx); List<Vertices> results = new List<Vertices>(); foreach (DelaunayTriangle triangle in poly.Triangles) { Vertices v = new Vertices(); foreach (TriangulationPoint p in triangle.Points) { v.Add(new FVector2((float)p.X, (float)p.Y)); } results.Add(v); } return results; }