bool IRaySegmentsCollidable.TryGetRayCollision(Body thisBody, Body raysBody, RaySegmentsShape raySegments, out RaySegmentIntersectionInfo info) { bool intersects = false; RaySegment[] segments = raySegments.Segments; Scalar[] result = new Scalar[segments.Length]; Scalar temp; Vector2D[][] polygons = this.Polygons; for (int index = 0; index < segments.Length; ++index) { result[index] = -1; } Matrix2x3 matrix = raysBody.Matrices.ToBody * thisBody.Matrices.ToWorld; for (int polyIndex = 0; polyIndex < polygons.Length; ++polyIndex) { Vector2D[] unTrans = polygons[polyIndex]; Vector2D[] polygon = new Vector2D[unTrans.Length]; for (int index = 0; index < unTrans.Length; ++index) { Vector2D.Transform(ref matrix, ref unTrans[index], out polygon[index]); } BoundingRectangle rect; BoundingRectangle.FromVectors(polygon, out rect); BoundingPolygon poly = new BoundingPolygon(polygon); for (int index = 0; index < segments.Length; ++index) { RaySegment segment = segments[index]; rect.Intersects(ref segment.RayInstance, out temp); if (temp >= 0 && temp <= segment.Length) { poly.Intersects(ref segment.RayInstance, out temp); if (temp >= 0 && temp <= segment.Length) { if (result[index] == -1 || temp < result[index]) { result[index] = temp; } intersects = true; } } } } if (intersects) { info = new RaySegmentIntersectionInfo(result); } else { info = null; } return(intersects); }
bool IRaySegmentsCollidable.TryGetRayCollision(Body thisBody, Body raysBody, RaySegmentsShape raySegments, out RaySegmentIntersectionInfo info) { bool intersects = false; RaySegment[] segments = raySegments.Segments; Scalar[] result = new Scalar[segments.Length]; BoundingCircle bounding = new BoundingCircle(Vector2D.Zero, this.radius); Matrix2x3 vertexM = thisBody.Matrices.ToBody * raysBody.Matrices.ToWorld; for (int index = 0; index < segments.Length; ++index) { RaySegment segment = segments[index]; Ray ray2; Vector2D.Transform(ref vertexM, ref segment.RayInstance.Origin, out ray2.Origin); Vector2D.TransformNormal(ref vertexM, ref segment.RayInstance.Direction, out ray2.Direction); Scalar temp; bounding.Intersects(ref ray2, out temp); if (temp >= 0 && temp <= segment.Length) { intersects = true; result[index] = temp; continue; } else { result[index] = -1; } } if (intersects) { info = new RaySegmentIntersectionInfo(result); } else { info = null; } return(intersects); }
public static RaySegmentsShape CreateRays(RaySegment[] raySegments) { RaySegmentsShape rayShape = new RaySegmentsShape(raySegments); rayShape.Tag = new RaysSegmentsDrawable(rayShape); return rayShape; }
public static DisposeCallback BasicDemoSetup(DemoOpenInfo info) { DisposeCallback dispose = null; IShape bombShape = ShapeFactory.CreateSprite(Cache<SurfacePolygons>.GetItem("rocket.png"), 2, 16, 3); dispose += DemoHelper.RegisterBombLaunching(info, bombShape, 120); dispose += DemoHelper.RegisterMousePicking(info); dispose += DemoHelper.RegisterBodyStreamSpawning(info, new Body(new PhysicsState(), ParticleShape.Default, 1, Coefficients.Duplicate(), new Lifespan(.5f)), 2, 120, 1000, Key.B); dispose += DemoHelper.RegisterMaintainSpawning(info, SdlDotNet.Input.Key.N, delegate(Vector2D position) { ExplosionLogic result = new ExplosionLogic(position, Vector2D.Zero, 9000, .1f, 600, new Lifespan(.25f)); info.Scene.Engine.AddLogic(result); return result; }); List<RaySegment> segments = new List<RaySegment>(); for (Scalar angle = 0; angle < MathHelper.PiOver2; angle += .05f) { RaySegment seg = new RaySegment(); seg.Length = 500; seg.RayInstance = new Ray(Vector2D.Zero, Vector2D.FromLengthAndAngle(1, angle)); segments.Add(seg); } IShape rayShape = ShapeFactory.CreateRays(segments.ToArray()); dispose += DemoHelper.RegisterMaintainSpawning(info, SdlDotNet.Input.Key.M, delegate(Vector2D position) { Body lazer = new Body(new PhysicsState(), rayShape, 1, new Coefficients(1, 1), new Lifespan()); lazer.State.Position.Linear = position; lazer.State.Velocity.Angular = .91f; lazer.IgnoresGravity = true; lazer.ApplyPosition(); info.Scene.AddGraphic(CreateGraphic(lazer)); return lazer; }); return dispose; }
public void CalcBoundingRectangle(ref Matrix2x3 matrix, out BoundingRectangle rectangle) { Vector2D v1, v2; RaySegment segment = segments[0]; v1 = segment.RayInstance.Origin; v2.X = segment.RayInstance.Direction.X * segment.Length + v1.X; v2.Y = segment.RayInstance.Direction.Y * segment.Length + v1.Y; Vector2D.Transform(ref matrix, ref v1, out v1); Vector2D.Transform(ref matrix, ref v2, out v2); if (v1.X > v2.X) { rectangle.Min.X = v2.X; rectangle.Max.X = v1.X; } else { rectangle.Min.X = v1.X; rectangle.Max.X = v2.X; } if (v1.Y > v2.Y) { rectangle.Min.Y = v2.Y; rectangle.Max.Y = v1.Y; } else { rectangle.Min.Y = v1.Y; rectangle.Max.Y = v2.Y; } for (int index = 1; index < segments.Length; ++index) { segment = segments[index]; v1 = segment.RayInstance.Origin; v2.X = segment.RayInstance.Direction.X * segment.Length + v1.X; v2.Y = segment.RayInstance.Direction.Y * segment.Length + v1.Y; Vector2D.Transform(ref matrix, ref v1, out v1); Vector2D.Transform(ref matrix, ref v2, out v2); if (v1.X > rectangle.Max.X) { rectangle.Max.X = v1.X; } else if (v1.X < rectangle.Min.X) { rectangle.Min.X = v1.X; } if (v1.Y > rectangle.Max.Y) { rectangle.Max.Y = v1.Y; } else if (v1.Y < rectangle.Min.Y) { rectangle.Min.Y = v1.Y; } if (v2.X > rectangle.Max.X) { rectangle.Max.X = v2.X; } else if (v2.X < rectangle.Min.X) { rectangle.Min.X = v2.X; } if (v2.Y > rectangle.Max.Y) { rectangle.Max.Y = v2.Y; } else if (v2.Y < rectangle.Min.Y) { rectangle.Min.Y = v2.Y; } } }
void AddRays() { List<RaySegment> segments = new List<RaySegment>(); for (Scalar angle = 0; angle < MathHelper.PiOver2; angle += .05f) { RaySegment seg = new RaySegment(); seg.Length = 500; seg.RayInstance = new Ray(Vector2D.Zero, Vector2D.FromLengthAndAngle(1, angle)); segments.Add(seg); } lazer = new Body(new PhysicsState(), new RaySegmentsShape(segments.ToArray()), 1, new Coefficients(1, 1), new Lifespan()); lazer.State.Position.Linear = sparkPoint; lazer.State.Velocity.Angular = .91f; lazer.IgnoresGravity = true; lazer.ApplyPosition(); engine.AddBody(lazer); lazerLogic = new RaySegmentsCollisionLogic(lazer); engine.AddLogic(lazerLogic); lock (objects) { OpenGlObject o = new OpenGlObject(lazer, lazerLogic); lazer.Tag = o; objects.Add(o); } }
/// <summary> /// Creates a shape to be used in the Physics Body. A physics shape is scaled to the /// size of the object. In addition, it has more vertices and some additional info /// that is used in collision detection. /// </summary> internal static IShape CreatePhysicsShape(Shape shape, Vector size, CollisionShapeParameters parameters) { if (shape is RaySegment) { RaySegment raySegment = (RaySegment)shape; Physics2DDotNet.Shapes.RaySegment singleSegment = new Physics2DDotNet.Shapes.RaySegment( new Vector2D(raySegment.Origin.X, raySegment.Origin.Y), new Vector2D(raySegment.Direction.X, raySegment.Direction.Y), raySegment.Length); return(new RaySegmentsShape(singleSegment)); } else if (shape is Ellipse) { Debug.Assert(shape.IsUnitSize); double smaller = Math.Min(size.X, size.Y); double bigger = Math.Max(size.X, size.Y); // Average between width and height. double r = smaller / 2 + (bigger - smaller) / 2; int vertexCount = (int)Math.Ceiling((2 * Math.PI * r) / parameters.MaxVertexDistance); if (Math.Abs(size.X - size.Y) <= double.Epsilon) { // We get more accurate results by using the circleshape. // in addition, the circleshape does not need a DistanceGrid // object (which is slow to initialize) because calculations // for a circleshape are much simpler. return(new CircleShape(r, vertexCount)); } else { Vector2D[] vertexes = new Vector2D[vertexCount]; double a = 0.5 * size.X; double b = 0.5 * size.Y; for (int i = 0; i < vertexCount; i++) { double t = (i * 2 * Math.PI) / vertexCount; double x = a * Math.Cos(t); double y = b * Math.Sin(t); vertexes[i] = new Vector2D(x, y); } return(new PolygonShape(vertexes, parameters.DistanceGridSpacing)); } } else { Vector2D[] originalVertexes = new Vector2D[shape.Cache.OutlineVertices.Length]; for (int i = 0; i < shape.Cache.OutlineVertices.Length; i++) { Vector v = shape.Cache.OutlineVertices[i]; if (shape.IsUnitSize) { v.X *= size.X; v.Y *= size.Y; } originalVertexes[i] = new Vector2D(v.X, v.Y); } Vector2D[] polyVertexes = VertexHelper.Subdivide(originalVertexes, parameters.MaxVertexDistance); return(new PolygonShape(polyVertexes, parameters.DistanceGridSpacing)); } }