FluidInfo ILineFluidAffectable.GetFluidInfo(GetTangentCallback callback, Line line) { if (polygons.Length == 1) { return(ShapeHelper.GetFluidInfo(Vertexes, callback, line)); } List <Vector2D[]> submerged = new List <Vector2D[]>(polygons.Length); for (int index = 0; index < polygons.Length; ++index) { Vector2D[] vertexes = VertexHelper.GetIntersection(polygons[index], line); if (vertexes.Length >= 3) { submerged.Add(vertexes); } } if (submerged.Count == 0) { return(null); } Vector2D[][] newPolygons = submerged.ToArray(); Vector2D centroid = VertexHelper.GetCentroidOfRange(newPolygons); Scalar area = VertexHelper.GetAreaOfRange(newPolygons); Vector2D tangent = callback(centroid); Vector2D dragCenter; Scalar dragArea; ShapeHelper.GetFluidInfo(newPolygons, tangent, out dragCenter, out dragArea); return(new FluidInfo(dragCenter, dragArea, centroid, area)); }
public static FluidInfo GetFluidInfo(Vector2D[] vertexes2, GetTangentCallback callback, Line line) { Vector2D centroid; Scalar area; Vector2D dragCenter; Scalar dragArea; Vector2D[] vertexes = ShapeHelper.GetIntersection(vertexes2, line); if (vertexes.Length < 3) { return(null); } centroid = PolygonShape.GetCentroid(vertexes); area = PolygonShape.GetArea(vertexes); Vector2D tangent = callback(centroid); Scalar min, max; ShapeHelper.GetProjectedBounds(vertexes, tangent, out min, out max); Scalar avg = (max + min) / 2; dragCenter = tangent * avg; dragArea = max - min; return(new FluidInfo(dragCenter, dragArea, centroid, area)); }
protected internal override void RunLogic(TimeStep step) { for (int index = 0; index < items.Count; ++index) { Wrapper wrapper = items[index]; Body body = wrapper.body; if (wrapper.affectable == null || body.IgnoresPhysicsLogics || Scalar.IsPositiveInfinity(body.Mass.Mass)) { continue; } IShape shape = body.Shape; int isInsideCount = 0; foreach (Vector2D corner in body.Rectangle.Corners()) { Scalar distance = line.GetDistance(corner); if (distance <= 0) { isInsideCount++; } } if (isInsideCount == 0) { continue; } if (isInsideCount != 4) { Vector2D relativeVelocity = Vector2D.Zero; Vector2D velocityDirection = Vector2D.Zero; Vector2D dragDirection = Vector2D.Zero; Vector2D centroid = Vector2D.Zero; Line bodyLine; Line.Transform(ref body.Matrices.ToBody, ref line, out bodyLine); GetTangentCallback callback = delegate(Vector2D centTemp) { centroid = body.Matrices.ToWorldNormal * centTemp; PhysicsHelper.GetRelativeVelocity(ref body.State.Velocity, ref centroid, out relativeVelocity); relativeVelocity = FluidVelocity - relativeVelocity; velocityDirection = relativeVelocity.Normalized; dragDirection = body.Matrices.ToBodyNormal * velocityDirection.LeftHandNormal; return(dragDirection); }; FluidInfo lineInfo = wrapper.affectable.GetFluidInfo(callback, bodyLine); if (lineInfo == null) { continue; } // Vector2D centTemp = lineInfo.Centroid; Scalar areaTemp = lineInfo.Area; // Vector2D centroid = body.Matrices.ToWorldNormal * centTemp; Vector2D buoyancyForce = body.State.Acceleration.Linear * areaTemp * -Density; body.ApplyForce(buoyancyForce, centroid); /* * PhysicsHelper.GetRelativeVelocity(ref body.State.Velocity, ref centroid, out relativeVelocity); * relativeVelocity = FluidVelocity-relativeVelocity; * velocityDirection = relativeVelocity.Normalized; * dragDirection = body.Matrices.ToBodyNormal * velocityDirection.LeftHandNormal; * * lineInfo = wrapper.affectable.GetFluidInfo(dragDirection, bodyLine); * if (lineInfo == null) { continue; }*/ Scalar speedSq = relativeVelocity.MagnitudeSq; Scalar dragForceMag = -.5f * Density * speedSq * lineInfo.DragArea * DragCoefficient; Scalar maxDrag = -MathHelper.Sqrt(speedSq) * body.Mass.Mass * step.DtInv; if (dragForceMag < maxDrag) { dragForceMag = maxDrag; } Vector2D dragForce = dragForceMag * velocityDirection; body.ApplyForce(dragForce, body.Matrices.ToWorldNormal * lineInfo.DragCenter); body.ApplyTorque( -body.Mass.MomentOfInertia * (body.Coefficients.DynamicFriction + Density + DragCoefficient) * body.State.Velocity.Angular); } else { Vector2D relativeVelocity = body.State.Velocity.Linear - FluidVelocity; Vector2D velocityDirection = relativeVelocity.Normalized; Vector2D dragDirection = body.Matrices.ToBodyNormal * velocityDirection.LeftHandNormal; Vector2D centroid = wrapper.body.Matrices.ToWorldNormal * wrapper.affectable.Centroid; Vector2D buoyancyForce = body.State.Acceleration.Linear * wrapper.affectable.Area * -Density; wrapper.body.ApplyForce(buoyancyForce, centroid); if (velocityDirection == Vector2D.Zero) { continue; } DragInfo dragInfo = wrapper.affectable.GetFluidInfo(dragDirection); if (dragInfo.DragArea < .01f) { continue; } Scalar speedSq = relativeVelocity.MagnitudeSq; Scalar dragForceMag = -.5f * Density * speedSq * dragInfo.DragArea * DragCoefficient; Scalar maxDrag = -MathHelper.Sqrt(speedSq) * body.Mass.Mass * step.DtInv; if (dragForceMag < maxDrag) { dragForceMag = maxDrag; } Vector2D dragForce = dragForceMag * velocityDirection; wrapper.body.ApplyForce(dragForce, body.Matrices.ToWorldNormal * dragInfo.DragCenter); wrapper.body.ApplyTorque( -body.Mass.MomentOfInertia * (body.Coefficients.DynamicFriction + Density + DragCoefficient) * body.State.Velocity.Angular); } } }
protected internal override void RunLogic(TimeStep step) { Scalar area = MathHelper.Pi * radius * radius; Scalar density = explosionBody.Mass.Mass / area; BoundingCircle circle = new BoundingCircle(explosionBody.State.Position.Linear, radius); Matrix2x3 temp; ALVector2D.ToMatrix2x3(ref explosionBody.State.Position, out temp); Matrices matrices = new Matrices(); matrices.SetToWorld(ref temp); Vector2D relativeVelocity = Vector2D.Zero; Vector2D velocityDirection = Vector2D.Zero; Vector2D dragDirection = Vector2D.Zero; for (int index = 0; index < items.Count; ++index) { Wrapper wrapper = items[index]; Body body = wrapper.body; Matrix2x3 matrix; Matrix2x3.Multiply(ref matrices.ToBody, ref body.Matrices.ToWorld, out matrix); ContainmentType containmentType; BoundingRectangle rect = body.Rectangle; circle.Contains(ref rect, out containmentType); if (containmentType == ContainmentType.Intersects) { return; GetTangentCallback callback = delegate(Vector2D centroid) { centroid = body.Matrices.ToWorld * centroid; Vector2D p1 = centroid - explosionBody.State.Position.Linear; Vector2D p2 = centroid - body.State.Position.Linear; PhysicsHelper.GetRelativeVelocity( ref explosionBody.State.Velocity, ref body.State.Velocity, ref p1, ref p2, out relativeVelocity); relativeVelocity = p1.Normalized * this.pressurePulseSpeed; relativeVelocity = -relativeVelocity; velocityDirection = relativeVelocity.Normalized; dragDirection = matrices.ToBodyNormal * velocityDirection.LeftHandNormal; return(dragDirection); }; DragInfo dragInfo = wrapper.affectable.GetExplosionInfo(matrix, radius, callback); if (dragInfo == null) { continue; } if (velocityDirection == Vector2D.Zero) { continue; } if (dragInfo.DragArea < .01f) { continue; } Scalar speedSq = relativeVelocity.MagnitudeSq; Scalar dragForceMag = -.5f * density * speedSq * dragInfo.DragArea * dragCoefficient; Scalar maxDrag = -MathHelper.Sqrt(speedSq) * body.Mass.Mass * step.DtInv; if (dragForceMag < maxDrag) { dragForceMag = maxDrag; } Vector2D dragForce = dragForceMag * velocityDirection; wrapper.body.ApplyForce(dragForce, (body.Matrices.ToBody * matrices.ToWorld) * dragInfo.DragCenter); } else if (containmentType == ContainmentType.Contains) { Vector2D centroid = body.Matrices.ToWorld * wrapper.affectable.Centroid; Vector2D p1 = centroid - explosionBody.State.Position.Linear; Vector2D p2 = centroid - body.State.Position.Linear; PhysicsHelper.GetRelativeVelocity( ref explosionBody.State.Velocity, ref body.State.Velocity, ref p1, ref p2, out relativeVelocity); relativeVelocity = p1.Normalized * this.pressurePulseSpeed; relativeVelocity = -relativeVelocity; velocityDirection = relativeVelocity.Normalized; dragDirection = matrices.ToBodyNormal * velocityDirection.LeftHandNormal; DragInfo dragInfo = wrapper.affectable.GetFluidInfo(dragDirection); if (dragInfo.DragArea < .01f) { continue; } Scalar speedSq = relativeVelocity.MagnitudeSq; Scalar dragForceMag = -.5f * density * speedSq * dragInfo.DragArea * dragCoefficient; Scalar maxDrag = -MathHelper.Sqrt(speedSq) * body.Mass.Mass * step.DtInv; if (dragForceMag < maxDrag) { dragForceMag = maxDrag; } Vector2D dragForce = dragForceMag * velocityDirection; wrapper.body.ApplyForce(dragForce, body.Matrices.ToWorldNormal * dragInfo.DragCenter); wrapper.body.ApplyTorque( -body.Mass.MomentOfInertia * (body.Coefficients.DynamicFriction + density + dragCoefficient) * body.State.Velocity.Angular); } } }
DragInfo IExplosionAffectable.GetExplosionInfo(Matrix2x3 matrix, Scalar radius, GetTangentCallback callback) { //TODO: do this right! //TODO: do this right! Vector2D[] vertexes2 = new Vector2D[Vertexes.Length]; for (int index = 0; index < vertexes2.Length; ++index) { vertexes2[index] = matrix * Vertexes[index]; } Vector2D[] inter = VertexHelper.GetIntersection(vertexes2, radius); if (inter.Length < 3) { return(null); } Vector2D centroid = VertexHelper.GetCentroid(inter); Vector2D tangent = callback(centroid); Scalar min, max; ShapeHelper.GetProjectedBounds(inter, tangent, out min, out max); Scalar avg = (max + min) / 2; return(new DragInfo(tangent * avg, max - min)); }
FluidInfo ILineFluidAffectable.GetFluidInfo(GetTangentCallback callback, Line line) { return(ShapeHelper.GetFluidInfo(Vertexes, callback, line)); }
DragInfo IExplosionAffectable.GetExplosionInfo(Matrix2x3 matrix, Scalar radius, GetTangentCallback callback) { //TODO: do this right! Vector2D[] vertexes2 = new Vector2D[Vertexes.Length]; for (int index = 0; index < vertexes2.Length; ++index) { vertexes2[index] = matrix * Vertexes[index]; } Vector2D[] inter = VertexHelper.GetIntersection(vertexes2, radius); if (inter.Length < 3) { return null; } Vector2D centroid = VertexHelper.GetCentroid(inter); Vector2D tangent = callback(centroid); Scalar min, max; ShapeHelper.GetProjectedBounds(inter, tangent, out min, out max); Scalar avg = (max + min) / 2; return new DragInfo(tangent * avg, max - min); }
FluidInfo ILineFluidAffectable.GetFluidInfo(GetTangentCallback callback, Line line) { return ShapeHelper.GetFluidInfo(Vertexes, callback, line); }
FluidInfo ILineFluidAffectable.GetFluidInfo(GetTangentCallback callback, Line line) { if (polygons.Length == 1) { return ShapeHelper.GetFluidInfo(Vertexes, callback, line); } List<Vector2D[]> submerged = new List<Vector2D[]>(polygons.Length); for (int index = 0; index < polygons.Length; ++index) { Vector2D[] vertexes = VertexHelper.GetIntersection(polygons[index], line); if (vertexes.Length >= 3) { submerged.Add(vertexes); } } if (submerged.Count == 0) { return null; } Vector2D[][] newPolygons = submerged.ToArray(); Vector2D centroid = VertexHelper.GetCentroidOfRange(newPolygons); Scalar area = VertexHelper.GetAreaOfRange(newPolygons); Vector2D tangent = callback(centroid); Vector2D dragCenter; Scalar dragArea; ShapeHelper.GetFluidInfo(newPolygons, tangent, out dragCenter, out dragArea); return new FluidInfo(dragCenter, dragArea, centroid, area); }