private Body LevelFromTexture(Texture2D Texture, ref Vector2 origin) { // Get the world World World = GamePlayManager.WorldManager.World; World.Gravity = Vector2.Zero; _scale = 1.15f; // Create an array to hold the data from the texture uint[] data = new uint[Texture.Width * Texture.Height]; // Transfer the texture data to the array Texture.GetData(data); // Find the vertices that makes up the outline of the shape in the texture Vertices textureVertices = PolygonTools.CreatePolygon(data, Texture.Width, false); // The tool return vertices as they were found in the texture. // We need to find the real center (centroid) of the vertices for 2 reasons: // 1. To translate the vertices so the polygon is centered around the centroid. // 2. To draw the texture and lighting the correct place. Vector2 centroid = -textureVertices.GetCentroid(); textureVertices.Translate(ref centroid); Vector2 textureCenter = new Rectangle(0, 0, Texture.Width, Texture.Height).Center.ToVector2(); origin = -centroid; Vector2 offset = -(textureCenter - origin) * _scale; // We simplify the vertices found in the texture. textureVertices = SimplifyTools.ReduceByDistance(textureVertices, 4f); // Since it is a concave polygon, we need to partition it into several smaller convex polygons // -- EarclipDecomposer - 303 polygons - 60fps on XBOX - 7835 Milliseconds on XBOX // -- BayazitDecomposer - 108 polygons - 60fps on XBOX - 222 Milliseconds on XBOX List <Vertices> list = BayazitDecomposer.ConvexPartition(textureVertices); // Scale the vertices from graphics space to sim space Vector2 vertScale = new Vector2(ConvertUnits.ToSimUnits(1)) * _scale; foreach (Vertices vertices in list) { vertices.Scale(ref vertScale); } // Create a single body with multiple fixtures Body compound = BodyFactory.CreateCompoundPolygon(World, list, 1f, BodyType.Static); compound.BodyType = BodyType.Static; compound.Position = ConvertUnits.ToSimUnits(MazeOffset + offset); // Add to krypton foreach (Vertices vertices in list) { Vector2[] points = new Vector2[vertices.Count]; int i = vertices.Count; foreach (Vector2 vector in vertices) { i--; points[i] = ConvertUnits.ToDisplayUnits(vector) + offset + MazeOffset; } ShadowHull hull = ShadowHull.CreateConvex(ref points); KryptonEngine.Hulls.Add(hull); } new Mob(GamePlayManager.MobManager, new FarseerPhysicalBody(compound)) { AnimatedSprite = new AnimatedSprite(@"Blank") }; return(compound); }
public static List <Vertices> ConvexPartition(Vertices vertices, TriangulationAlgorithm algorithm, bool discardAndFixInvalid = true, float tolerance = 0.001f) { if (vertices.Count <= 3) { return new List <Vertices> { vertices } } ; List <Vertices> results = null; switch (algorithm) { case TriangulationAlgorithm.Earclip: #pragma warning disable 162 // ReSharper disable three ConditionIsAlwaysTrueOrFalse if (Settings.SkipSanityChecks) { Debug.Assert(!vertices.IsCounterClockWise(), "The Ear-clip algorithm expects the polygon to be clockwise."); } else { if (vertices.IsCounterClockWise()) { Vertices temp = new Vertices(vertices); temp.Reverse(); results = EarclipDecomposer.ConvexPartition(temp, tolerance); } else { results = EarclipDecomposer.ConvexPartition(vertices, tolerance); } } break; case TriangulationAlgorithm.Bayazit: if (Settings.SkipSanityChecks) { Debug.Assert(vertices.IsCounterClockWise(), "The polygon is not counter clockwise. This is needed for Bayazit to work correctly."); } else { if (!vertices.IsCounterClockWise()) { Vertices temp = new Vertices(vertices); temp.Reverse(); results = BayazitDecomposer.ConvexPartition(temp); } else { results = BayazitDecomposer.ConvexPartition(vertices); } } break; case TriangulationAlgorithm.Flipcode: if (Settings.SkipSanityChecks) { Debug.Assert(vertices.IsCounterClockWise(), "The polygon is not counter clockwise. This is needed for Bayazit to work correctly."); } #pragma warning restore 162 else { if (!vertices.IsCounterClockWise()) { Vertices temp = new Vertices(vertices); temp.Reverse(); results = FlipcodeDecomposer.ConvexPartition(temp); } else { results = FlipcodeDecomposer.ConvexPartition(vertices); } } break; case TriangulationAlgorithm.Seidel: results = SeidelDecomposer.ConvexPartition(vertices, tolerance); break; case TriangulationAlgorithm.SeidelTrapezoids: results = SeidelDecomposer.ConvexPartitionTrapezoid(vertices, tolerance); break; case TriangulationAlgorithm.Delauny: results = CDTDecomposer.ConvexPartition(vertices); break; default: throw new ArgumentOutOfRangeException(nameof(algorithm)); } if (discardAndFixInvalid) { for (int i = results.Count - 1; i >= 0; i--) { Vertices polygon = results[i]; if (!ValidatePolygon(polygon)) { results.RemoveAt(i); } } } return(results); }
public override void LoadContent() { base.LoadContent(); World.Gravity = Vector2.Zero; _border = new Border(World, this, ScreenManager.GraphicsDevice.Viewport); _breakableObject = new List <List <Vertices> >(); Texture2D alphabet = ScreenManager.Content.Load <Texture2D>("Samples/alphabet"); uint[] data = new uint[alphabet.Width * alphabet.Height]; alphabet.GetData(data); List <Vertices> list = PolygonTools.CreatePolygon(data, alphabet.Width, 3.5f, 20, true, true); float yOffset = -5f; float xOffset = -14f; for (int i = 0; i < list.Count; i++) { if (i == 9) { yOffset = 0f; xOffset = -14f; } if (i == 18) { yOffset = 5f; xOffset = -12.25f; } Vertices polygon = list[i]; Vector2 centroid = -polygon.GetCentroid(); polygon.Translate(ref centroid); //polygon = SimplifyTools.CollinearSimplify(polygon); // this breaks the split hole function polygon = SimplifyTools.ReduceByDistance(polygon, 4); List <Vertices> triangulated = BayazitDecomposer.ConvexPartition(polygon); #if WINDOWS_PHONE const float scale = 0.6f; #else const float scale = 1f; #endif Vector2 vertScale = new Vector2(ConvertUnits.ToSimUnits(1)) * scale; foreach (Vertices vertices in triangulated) { vertices.Scale(ref vertScale); } BreakableBody breakableBody = new BreakableBody(triangulated, World, 1); breakableBody.MainBody.Position = new Vector2(xOffset, yOffset); breakableBody.Strength = 100; breakableBody.MainBody.UserData = i; World.AddBreakableBody(breakableBody); polygon.Scale(ref vertScale); _breakableObject.Add(polygon.SplitAtHoles()); xOffset += 3.5f; } }
public void InitFromTexture() { uint[] data = null; Rectangle materialAreaRect; if (this.SceneItem is AnimatedSprite) { AnimatedSprite s = SceneItem as AnimatedSprite; string areaName = s.Animations[0].AnimationFrames[0].Area; materialAreaRect = s.Material.Areas[areaName]; } else if (this.SceneItem is Sprite) { Sprite s = SceneItem as Sprite; string areaName = s.MaterialArea; if (areaName == string.Empty) { materialAreaRect = s.Material.Texture.Bounds; } else { materialAreaRect = s.Material.Areas[areaName]; } } else { return;//not even a sprite? Get outta town } if (materialAreaRect.Width < 2 || materialAreaRect.Height < 2 || materialAreaRect.Width > 512 || materialAreaRect.Height > 512) { return; } Texture2D wholeTexture = ((Sprite)this.SceneItem).Material.Texture; data = new uint[materialAreaRect.Width * materialAreaRect.Height]; wholeTexture.GetData(0, materialAreaRect, data, 0, data.Length); //Find the vertices that makes up the outline of the shape in the texture Vertices textureVertices = PolygonTools.CreatePolygon(data, materialAreaRect.Width, false); //The tool return vertices as they were found in the texture. //We need to find the real center (centroid) of the vertices for 2 reasons: //1. To translate the vertices so the polygon is centered around the centroid. Vector2 centroid = -textureVertices.GetCentroid(); textureVertices.Translate(ref centroid); //2. To draw the texture the correct place. SceneItem.Pivot = -centroid; //Offset = -centroid; //We simplify the vertices found in the texture. textureVertices = SimplifyTools.ReduceByDistance(textureVertices, 1f); //Since it is a concave polygon, we need to partition it into several smaller convex polygons List <Vertices> list = BayazitDecomposer.ConvexPartition(textureVertices); //scale the vertices from graphics space to sim space //float scale = ((Sprite)SceneItem).Scale; //float scale = 100.0f;//100 is 1-to-1 for pixels //Vector2 vertScale = new Vector2(ConvertUnits.ToSimUnits(1)) * scale; //foreach (Vertices vertices in list) { // vertices.Scale(ref vertScale); //} //Create a single body with multiple fixtures Body = BodyFactory.CreateCompoundPolygon(IceFarseerManager.StaticWorld, list, 1f, SceneItem.Position); _isBodyRemoved = false; //Body = BodyFactory.CreateCompoundPolygon(IceFarseerManager.StaticWorld, list, 1f, BodyType.Dynamic); //Body = BodyFactory.CreateCircle(IceFarseerManager.StaticWorld, wholeTexture.Width * 0.5f, 1.0f, SceneItem.Position, SceneItem); Body.BodyType = BodyType.Dynamic; Body.UserData = SceneItem; Body.IsSensor = true; Body.IgnoreGravity = true; Body.Enabled = true; Body.Awake = true; Body.CollidesWith = Category.All; Body.CollisionCategories = Category.All; Body.OnCollision += new OnCollisionEventHandler(IceFarseerManager.Instance.Body_OnCollision); }
private void CreatePreview() { if (materialBox.SelectedItem != null && colorBox.SelectedItem != null && shapeBox.SelectedItem != null) { Dictionary <string, object> shapeParameters = new Dictionary <string, object>(); shapeParameters.Add(ShapeParametersKeys.Material, materialBox.SelectedItem.ToString()); shapeParameters.Add(ShapeParametersKeys.MaterialScale, float.Parse(materialScale.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.Color, _colorDictionary[colorBox.SelectedItem.ToString()]); ObjectType objectType = (ObjectType)Enum.Parse(typeof(ObjectType), shapeBox.SelectedItem.ToString()); shapeParameters.Add(ShapeParametersKeys.ObjectType, objectType); switch (objectType) { case ObjectType.Arc: shapeParameters.Add(ShapeParametersKeys.ArcDegrees, float.Parse(arcDegrees.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.ArcRadius, float.Parse(arcRadius.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.ArcSides, int.Parse(arcSides.Value.ToString())); break; case ObjectType.Capsule: shapeParameters.Add(ShapeParametersKeys.CapsuleHeight, float.Parse(capsuleHeight.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.CapsuleBottomRadius, float.Parse(capsuleBottomRadius.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.CapsuleBottomEdges, int.Parse(capsuleBottomEdges.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.CapsuleTopRadius, float.Parse(capsuleTopRadius.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.CapsuleTopEdges, int.Parse(capsuleTopEdges.Value.ToString())); break; case ObjectType.Gear: shapeParameters.Add(ShapeParametersKeys.GearRadius, float.Parse(gearRadius.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.GearNumberOfTeeth, int.Parse(gearNumberOfTeeth.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.GearTipPercentage, float.Parse(gearTipPercentage.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.GearToothHeigt, float.Parse(gearToothHeight.Value.ToString())); break; case ObjectType.Rectangle: shapeParameters.Add(ShapeParametersKeys.RectangleWidth, float.Parse(rectangleWidth.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.RectangleHeight, float.Parse(rectangleHeight.Value.ToString())); break; case ObjectType.RoundedRectangle: shapeParameters.Add(ShapeParametersKeys.RoundedRectangleHeight, float.Parse(roundedRectangleWidth.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.RoundedRectangleWidth, float.Parse(roundedRectangleHeight.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.RoundedRectangleXRadius, float.Parse(roundedRectangleXRadius.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.RoundedRectangleYRadius, float.Parse(roundedRectangleYRadius.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.RoundedRectangleSegments, int.Parse(roundedRectangleSegments.Value.ToString())); break; case ObjectType.Ellipse: shapeParameters.Add(ShapeParametersKeys.EllipseXRadius, float.Parse(ellipseXRadius.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.EllipseYRadius, float.Parse(ellipseYRadius.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.EllipseNumberOfEdges, int.Parse(ellipseNumberOfEdges.Value.ToString())); break; case ObjectType.Circle: shapeParameters.Add(ShapeParametersKeys.CircleRadius, float.Parse(circleRadius.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.CircleSegments, AssetCreator.CircleSegments); break; case ObjectType.CustomShape: if (shapeFromTextureBox.SelectedItem == null) { return; } shapeParameters.Add(ShapeParametersKeys.CustomObjectScale, float.Parse(customShapeScale.Value.ToString())); shapeParameters.Add(ShapeParametersKeys.CustomObjectShape, shapeFromTextureBox.SelectedItem.ToString()); shapeParameters.Add(ShapeParametersKeys.CustomObjectUseOriginalTexture, useOriginalTextureCheck.Checked); break; default: throw new Exception("Unknown Shape"); } //Сохраняем исходную текстуру в словарь метаданных switch (objectType) { case ObjectType.CustomShape: shapeParameters.Add(ShapeParametersKeys.Texture, _assetCreator.GetShape((string)shapeParameters[ShapeParametersKeys.CustomObjectShape])); break; default: shapeParameters.Add(ShapeParametersKeys.Texture, _assetCreator.GetMaterial((string)shapeParameters[ShapeParametersKeys.Material])); break; } Vertices shapeVertices; Texture2D previewTexture; TextureFromDictionary(shapeParameters, out previewTexture, out shapeVertices); if (shapeVertices != null && previewTexture != null) { float?previousDensity = _objectLevelManager.PreviewObject[0].Body.Density; _objectLevelManager.PreviewObject[0].Body.FixtureList.Clear(); switch ((ObjectType)Enum.Parse(typeof(ObjectType), shapeBox.SelectedItem.ToString())) { case ObjectType.Circle: FixtureFactory.AttachCircle(float.Parse(circleRadius.Value.ToString()), previousDensity == null ? 1f : (float)previousDensity, _objectLevelManager.PreviewObject[0].Body); break; default: FixtureFactory.AttachCompoundPolygon(BayazitDecomposer.ConvexPartition(shapeVertices), previousDensity == null ? 1f : (float)previousDensity, _objectLevelManager.PreviewObject[0].Body); break; } _objectLevelManager.PreviewObject[0].Sprites[0] = new Sprite(previewTexture); _objectLevelManager.PreviewVertices = shapeVertices; previewScreen.PreviewGameObject = _objectLevelManager.PreviewObject[0]; editCurrentObjectAction.Checked = true; SetMouseToolButtonsState(editCurrentObjectAction); } previewTexture.SetMetadataDictionary(shapeParameters); } }
} // Vehicle() #endregion #region SetupPhysics /// <summary> SetupPhysics </summary> private void SetupPhysics() { // define car countour and damage state textures _vehicleTexture = ScreenManager.Content.Load <Texture2D>("Samples/car"); _destruct1 = ScreenManager.Content.Load <Texture2D>("Samples/car_destruct1"); _destruct2 = ScreenManager.Content.Load <Texture2D>("Samples/car_destruct2"); _destruct3 = ScreenManager.Content.Load <Texture2D>("Samples/car_destruct3"); uint[] data = new uint[_vehicleTexture.Width * _vehicleTexture.Height]; _vehicleTexture.GetData(data); Vertices textureVertices = PolygonTools.CreatePolygon(data, _vehicleTexture.Width, false); Vector2 centroid = -textureVertices.GetCentroid(); textureVertices.Translate(ref centroid); _origin = -centroid; textureVertices = SimplifyTools.ReduceByDistance(textureVertices, 4); List <Vertices> list = BayazitDecomposer.ConvexPartition(textureVertices); // _scale = 0.2f; Vector2 vertScale = new Vector2(ConvertUnits.ToSimUnits(1)) * _scale; foreach (Vertices vertixes in list) { vertixes.Scale(ref vertScale); } _vehicleBody = BodyFactory.CreateCompoundPolygon(PhysicsGameScreen.World, list, 1f, BodyType.Dynamic); _vehicleBody.BodyType = BodyType.Dynamic; _vehicleBody.Position = new Vector2(0.0f, -2.0f); _vehicleBody.Mass = 5f; _wheelBack = new Body(PhysicsGameScreen.World); _wheelBack.BodyType = BodyType.Dynamic; _wheelBack.Position = new Vector2(-2.0f, -0.8f);//new Vector2(-1.709f, -0.78f); wheelBackfix = _wheelBack.CreateFixture(new CircleShape(1.1f, 1f)); wheelBackfix.Friction = 120.0f; //_wheelBack.Mass = 2f; wheelBackfix.Body.Mass = 4f; //wheelBackfix.Restitution = 0f; _wheelBack.UserData = "wheel"; _wheelBack.OnCollision += new OnCollisionEventHandler(Body_OnCollision); _wheelFront = new Body(PhysicsGameScreen.World); _wheelFront.BodyType = BodyType.Dynamic; _wheelFront.Position = new Vector2(2.0f, -0.8f); wheelFrontfix = _wheelFront.CreateFixture(new CircleShape(1.1f, 1f)); wheelFrontfix.Friction = 120.0f; //_wheelFront.Mass = 2f; wheelFrontfix.Body.Mass = 4f; //wheelFrontfix.Restitution = 0f; wheelFrontfix.Body.UserData = "wheel"; wheelFrontfix.Body.OnCollision += new OnCollisionEventHandler(Body_OnCollision); Vector2 axis = new Vector2(0.0f, 1.0f);//0.8f); _springBack = new LineJoint(_vehicleBody, _wheelBack, _wheelBack.Position, axis); _springBack.MotorSpeed = 0.0f; _springBack.MaxMotorTorque = 90;// 80.0f;//100;//20.0f; _springBack.MotorEnabled = true; _springBack.Frequency = _hzBack; _springBack.DampingRatio = _zeta; PhysicsGameScreen.World.AddJoint(_springBack); _springFront = new LineJoint(_vehicleBody, _wheelFront, _wheelFront.Position, axis); _springFront.MotorSpeed = 0.0f; _springFront.MaxMotorTorque = 90;// 80.0f;//100;//10.0f; _springFront.MotorEnabled = true; _springFront.Frequency = _hzFront; _springFront.DampingRatio = _zeta; PhysicsGameScreen.World.AddJoint(_springFront); _wscale = 0.05f; // _vehicleBody = new Sprite(ScreenManager.Content.Load<Texture2D>("Samples/car"), // AssetCreator.CalculateOrigin(_vehicleBody) / _scale); _wheel = new Sprite(ScreenManager.Content.Load <Texture2D>("Samples/tankwheel2")); } // SetupPhysics()
/// <summary> /// Builds convex polygons out of the currently loaded 2D Shape Editor project. /// </summary> /// <returns>A list of convex polygons.</returns> private List <Polygon> BuildConvexPolygons() { List <Polygon> polygons = new List <Polygon>(); // for each shape in the project: foreach (Shape shape in project.shapes) { List <Vector2> vertices = new List <Vector2>(); // iterate through all segments of the shape: foreach (Segment segment in shape.segments) { // linear segment: if (segment.type == SegmentType.Linear) { vertices.Add(new Vector2(segment.position.x * project.extrudeScale.x, segment.position.y * -1.0f * project.extrudeScale.y) / 8.0f); } // bezier segment: else { foreach (Edge edge in GetBezierEdges(segment, GetNextSegment(shape, segment))) { vertices.Add(new Vector2(edge.Vertex1.Position.x * project.extrudeScale.x, edge.Vertex1.Position.y * -1.0f * project.extrudeScale.y) / 8.0f); } } } // in project v1 we use the horizontal and vertical flags to keep track of the correct winding order. Vector2[] inputVertices = vertices.ToArray(); if (project.flipHorizontally && !project.flipVertically) { inputVertices = ReverseWindingOrder(inputVertices); } if (!project.flipHorizontally && project.flipVertically) { inputVertices = ReverseWindingOrder(inputVertices); } // create convex polygons: inputVertices = ReverseWindingOrder(inputVertices); List <Vector2[]> convexPolygonsVertices = BayazitDecomposer.ConvexPartition(inputVertices); foreach (Vector2[] polyVertices in convexPolygonsVertices) { List <Vertex> vertexList = new List <Vertex>(); foreach (Vector2 vert in polyVertices) { vertexList.Add(new Vertex(vert, Vector3.zero, Vector2.zero)); } polygons.Add(new Polygon(vertexList.ToArray(), null, false, false)); } switch (extrudeMode) { case ExtrudeMode.CreatePolygon: // we make a brush for every polgon. desiredBrushCount = polygons.Count; break; case ExtrudeMode.RevolveShape: // we need another brush for every revolve step. desiredBrushCount = polygons.Count * project.revolveSteps; break; case ExtrudeMode.ExtrudeShape: // we make a brush for every polgon. desiredBrushCount = polygons.Count; break; case ExtrudeMode.ExtrudePoint: // we make a brush for every polgon. desiredBrushCount = polygons.Count; break; case ExtrudeMode.ExtrudeBevel: // we make a brush for every polgon. desiredBrushCount = polygons.Count; break; } } return(polygons); }