(61d00a474) v0.9.7.1
This commit is contained in:
@@ -1,4 +1,11 @@
|
||||
/*
|
||||
// Copyright (c) 2017 Kastellanos Nikolaos
|
||||
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
*
|
||||
@@ -26,6 +33,7 @@ using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using FarseerPhysics.Collision.Shapes;
|
||||
using FarseerPhysics.Common;
|
||||
using FarseerPhysics.Common.Maths;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Collision
|
||||
@@ -382,8 +390,8 @@ namespace FarseerPhysics.Collision
|
||||
/// <param name="aabb">The aabb.</param>
|
||||
public void Combine(ref AABB aabb)
|
||||
{
|
||||
LowerBound = Vector2.Min(LowerBound, aabb.LowerBound);
|
||||
UpperBound = Vector2.Max(UpperBound, aabb.UpperBound);
|
||||
Vector2.Min(ref LowerBound, ref aabb.LowerBound, out LowerBound);
|
||||
Vector2.Max(ref UpperBound, ref aabb.UpperBound, out UpperBound);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -393,8 +401,8 @@ namespace FarseerPhysics.Collision
|
||||
/// <param name="aabb2">The aabb2.</param>
|
||||
public void Combine(ref AABB aabb1, ref AABB aabb2)
|
||||
{
|
||||
LowerBound = Vector2.Min(aabb1.LowerBound, aabb2.LowerBound);
|
||||
UpperBound = Vector2.Max(aabb1.UpperBound, aabb2.UpperBound);
|
||||
Vector2.Min(ref aabb1.LowerBound, ref aabb2.LowerBound, out LowerBound);
|
||||
Vector2.Max(ref aabb1.UpperBound, ref aabb2.UpperBound, out UpperBound);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -434,15 +442,13 @@ namespace FarseerPhysics.Collision
|
||||
/// <param name="a">The first AABB.</param>
|
||||
/// <param name="b">The second AABB.</param>
|
||||
/// <returns>True if they are overlapping.</returns>
|
||||
|
||||
public static bool TestOverlap(ref AABB a, ref AABB b)
|
||||
{
|
||||
if (b.LowerBound.X - a.UpperBound.X > 0.0f ||
|
||||
b.LowerBound.Y - a.UpperBound.Y > 0.0f ||
|
||||
a.LowerBound.X - b.UpperBound.X > 0.0f ||
|
||||
a.LowerBound.Y - b.UpperBound.Y > 0.0f) return false;
|
||||
|
||||
return true;
|
||||
return
|
||||
b.LowerBound.X - a.UpperBound.X <= 0.0f &&
|
||||
b.LowerBound.Y - a.UpperBound.Y <= 0.0f &&
|
||||
a.LowerBound.X - b.UpperBound.X <= 0.0f &&
|
||||
a.LowerBound.Y - b.UpperBound.Y <= 0.0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -537,16 +543,6 @@ namespace FarseerPhysics.Collision
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This holds polygon B expressed in frame A.
|
||||
/// </summary>
|
||||
public class TempPolygon
|
||||
{
|
||||
public Vector2[] Vertices = new Vector2[Settings.MaxPolygonVertices];
|
||||
public Vector2[] Normals = new Vector2[Settings.MaxPolygonVertices];
|
||||
public int Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This structure is used to keep track of the best separating axis.
|
||||
/// </summary>
|
||||
@@ -587,9 +583,6 @@ namespace FarseerPhysics.Collision
|
||||
/// </summary>
|
||||
public static class Collision
|
||||
{
|
||||
[ThreadStatic]
|
||||
private static DistanceInput _input;
|
||||
|
||||
/// <summary>
|
||||
/// Test overlap between the two shapes.
|
||||
/// </summary>
|
||||
@@ -602,9 +595,9 @@ namespace FarseerPhysics.Collision
|
||||
/// <returns></returns>
|
||||
public static bool TestOverlap(Shape shapeA, int indexA, Shape shapeB, int indexB, ref Transform xfA, ref Transform xfB)
|
||||
{
|
||||
_input = _input ?? new DistanceInput();
|
||||
_input.ProxyA.Set(shapeA, indexA);
|
||||
_input.ProxyB.Set(shapeB, indexB);
|
||||
DistanceInput _input = new DistanceInput();
|
||||
_input.ProxyA = new DistanceProxy(shapeA, indexA);
|
||||
_input.ProxyB = new DistanceProxy(shapeB, indexB);
|
||||
_input.TransformA = xfA;
|
||||
_input.TransformB = xfB;
|
||||
_input.UseRadii = true;
|
||||
@@ -663,8 +656,8 @@ namespace FarseerPhysics.Collision
|
||||
{
|
||||
manifold.PointCount = 0;
|
||||
|
||||
Vector2 pA = MathUtils.Mul(ref xfA, circleA.Position);
|
||||
Vector2 pB = MathUtils.Mul(ref xfB, circleB.Position);
|
||||
Vector2 pA = Transform.Multiply(ref circleA._position, ref xfA);
|
||||
Vector2 pB = Transform.Multiply(ref circleB._position, ref xfB);
|
||||
|
||||
Vector2 d = pB - pA;
|
||||
float distSqr = Vector2.Dot(d, d);
|
||||
@@ -700,8 +693,8 @@ namespace FarseerPhysics.Collision
|
||||
manifold.PointCount = 0;
|
||||
|
||||
// Compute circle position in the frame of the polygon.
|
||||
Vector2 c = MathUtils.Mul(ref xfB, circleB.Position);
|
||||
Vector2 cLocal = MathUtils.MulT(ref xfA, c);
|
||||
Vector2 c = Transform.Multiply(ref circleB._position, ref xfB);
|
||||
Vector2 cLocal = Transform.Divide(ref c, ref xfA);
|
||||
|
||||
// Find the min separating edge.
|
||||
int normalIndex = 0;
|
||||
@@ -902,13 +895,13 @@ namespace FarseerPhysics.Collision
|
||||
Vector2 localNormal = new Vector2(localTangent.Y, -localTangent.X);
|
||||
Vector2 planePoint = 0.5f * (v11 + v12);
|
||||
|
||||
Vector2 tangent = MathUtils.Mul(xf1.q, localTangent);
|
||||
Vector2 tangent = Complex.Multiply(ref localTangent, ref xf1.q);
|
||||
|
||||
float normalx = tangent.Y;
|
||||
float normaly = -tangent.X;
|
||||
|
||||
v11 = MathUtils.Mul(ref xf1, v11);
|
||||
v12 = MathUtils.Mul(ref xf1, v12);
|
||||
v11 = Transform.Multiply(ref v11, ref xf1);
|
||||
v12 = Transform.Multiply(ref v12, ref xf1);
|
||||
|
||||
// Face offset.
|
||||
float frontOffset = normalx * v11.X + normaly * v11.Y;
|
||||
@@ -948,7 +941,7 @@ namespace FarseerPhysics.Collision
|
||||
if (separation <= totalRadius)
|
||||
{
|
||||
ManifoldPoint cp = manifold.Points[pointCount];
|
||||
cp.LocalPoint = MathUtils.MulT(ref xf2, clipPoints2[i].V);
|
||||
Transform.Divide(clipPoints2[i].V, ref xf2, out cp.LocalPoint);
|
||||
cp.Id = clipPoints2[i].ID;
|
||||
|
||||
if (flip)
|
||||
@@ -984,7 +977,7 @@ namespace FarseerPhysics.Collision
|
||||
manifold.PointCount = 0;
|
||||
|
||||
// Compute circle in frame of edge
|
||||
Vector2 Q = MathUtils.MulT(ref transformA, MathUtils.Mul(ref transformB, ref circleB._position));
|
||||
Vector2 Q = Transform.Divide(Transform.Multiply(ref circleB._position, ref transformB), ref transformA);
|
||||
|
||||
Vector2 A = edgeA.Vertex1, B = edgeA.Vertex2;
|
||||
Vector2 e = B - A;
|
||||
@@ -1126,24 +1119,29 @@ namespace FarseerPhysics.Collision
|
||||
/// <param name="xfB">The xf B.</param>
|
||||
public static void CollideEdgeAndPolygon(ref Manifold manifold, EdgeShape edgeA, ref Transform xfA, PolygonShape polygonB, ref Transform xfB)
|
||||
{
|
||||
EPCollider collider = new EPCollider();
|
||||
collider.Collide(ref manifold, edgeA, ref xfA, polygonB, ref xfB);
|
||||
EPCollider.Collide(ref manifold, edgeA, ref xfA, polygonB, ref xfB);
|
||||
}
|
||||
|
||||
private class EPCollider
|
||||
private static class EPCollider
|
||||
{
|
||||
private TempPolygon _polygonB = new TempPolygon();
|
||||
/// <summary>
|
||||
/// This holds polygon B expressed in frame A.
|
||||
/// </summary>
|
||||
internal struct TempPolygon
|
||||
{
|
||||
public Vector2[] Vertices;
|
||||
public Vector2[] Normals;
|
||||
public int Count;
|
||||
|
||||
Transform _xf;
|
||||
Vector2 _centroidB;
|
||||
Vector2 _v0, _v1, _v2, _v3;
|
||||
Vector2 _normal0, _normal1, _normal2;
|
||||
Vector2 _normal;
|
||||
Vector2 _lowerLimit, _upperLimit;
|
||||
float _radius;
|
||||
bool _front;
|
||||
internal TempPolygon(int maxPolygonVertices)
|
||||
{
|
||||
Vertices = new Vector2[maxPolygonVertices];
|
||||
Normals = new Vector2[maxPolygonVertices];
|
||||
Count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void Collide(ref Manifold manifold, EdgeShape edgeA, ref Transform xfA, PolygonShape polygonB, ref Transform xfB)
|
||||
public static void Collide(ref Manifold manifold, EdgeShape edgeA, ref Transform xfA, PolygonShape polygonB, ref Transform xfB)
|
||||
{
|
||||
// Algorithm:
|
||||
// 1. Classify v1 and v2
|
||||
@@ -1155,43 +1153,54 @@ namespace FarseerPhysics.Collision
|
||||
// 7. Return if _any_ axis indicates separation
|
||||
// 8. Clip
|
||||
|
||||
_xf = MathUtils.MulT(xfA, xfB);
|
||||
TempPolygon tempPolygonB = new TempPolygon(Settings.MaxPolygonVertices);
|
||||
Transform xf;
|
||||
Vector2 centroidB;
|
||||
Vector2 normal0 = new Vector2();
|
||||
Vector2 normal1;
|
||||
Vector2 normal2 = new Vector2();
|
||||
Vector2 normal;
|
||||
Vector2 lowerLimit, upperLimit;
|
||||
float radius;
|
||||
bool front;
|
||||
|
||||
_centroidB = MathUtils.Mul(ref _xf, polygonB.MassData.Centroid);
|
||||
Transform.Divide(ref xfB, ref xfA, out xf);
|
||||
|
||||
_v0 = edgeA.Vertex0;
|
||||
_v1 = edgeA._vertex1;
|
||||
_v2 = edgeA._vertex2;
|
||||
_v3 = edgeA.Vertex3;
|
||||
centroidB = Transform.Multiply(polygonB.MassData.Centroid, ref xf);
|
||||
|
||||
Vector2 v0 = edgeA.Vertex0;
|
||||
Vector2 v1 = edgeA._vertex1;
|
||||
Vector2 v2 = edgeA._vertex2;
|
||||
Vector2 v3 = edgeA.Vertex3;
|
||||
|
||||
bool hasVertex0 = edgeA.HasVertex0;
|
||||
bool hasVertex3 = edgeA.HasVertex3;
|
||||
|
||||
Vector2 edge1 = _v2 - _v1;
|
||||
Vector2 edge1 = v2 - v1;
|
||||
edge1.Normalize();
|
||||
_normal1 = new Vector2(edge1.Y, -edge1.X);
|
||||
float offset1 = Vector2.Dot(_normal1, _centroidB - _v1);
|
||||
normal1 = new Vector2(edge1.Y, -edge1.X);
|
||||
float offset1 = Vector2.Dot(normal1, centroidB - v1);
|
||||
float offset0 = 0.0f, offset2 = 0.0f;
|
||||
bool convex1 = false, convex2 = false;
|
||||
|
||||
// Is there a preceding edge?
|
||||
if (hasVertex0)
|
||||
{
|
||||
Vector2 edge0 = _v1 - _v0;
|
||||
Vector2 edge0 = v1 - v0;
|
||||
edge0.Normalize();
|
||||
_normal0 = new Vector2(edge0.Y, -edge0.X);
|
||||
convex1 = MathUtils.Cross(edge0, edge1) >= 0.0f;
|
||||
offset0 = Vector2.Dot(_normal0, _centroidB - _v0);
|
||||
normal0 = new Vector2(edge0.Y, -edge0.X);
|
||||
convex1 = MathUtils.Cross(ref edge0, ref edge1) >= 0.0f;
|
||||
offset0 = Vector2.Dot(normal0, centroidB - v0);
|
||||
}
|
||||
|
||||
// Is there a following edge?
|
||||
if (hasVertex3)
|
||||
{
|
||||
Vector2 edge2 = _v3 - _v2;
|
||||
Vector2 edge2 = v3 - v2;
|
||||
edge2.Normalize();
|
||||
_normal2 = new Vector2(edge2.Y, -edge2.X);
|
||||
convex2 = MathUtils.Cross(edge1, edge2) > 0.0f;
|
||||
offset2 = Vector2.Dot(_normal2, _centroidB - _v2);
|
||||
normal2 = new Vector2(edge2.Y, -edge2.X);
|
||||
convex2 = MathUtils.Cross(ref edge1, ref edge2) > 0.0f;
|
||||
offset2 = Vector2.Dot(normal2, centroidB - v2);
|
||||
}
|
||||
|
||||
// Determine front or back collision. Determine collision normal limits.
|
||||
@@ -1199,66 +1208,66 @@ namespace FarseerPhysics.Collision
|
||||
{
|
||||
if (convex1 && convex2)
|
||||
{
|
||||
_front = offset0 >= 0.0f || offset1 >= 0.0f || offset2 >= 0.0f;
|
||||
if (_front)
|
||||
front = offset0 >= 0.0f || offset1 >= 0.0f || offset2 >= 0.0f;
|
||||
if (front)
|
||||
{
|
||||
_normal = _normal1;
|
||||
_lowerLimit = _normal0;
|
||||
_upperLimit = _normal2;
|
||||
normal = normal1;
|
||||
lowerLimit = normal0;
|
||||
upperLimit = normal2;
|
||||
}
|
||||
else
|
||||
{
|
||||
_normal = -_normal1;
|
||||
_lowerLimit = -_normal1;
|
||||
_upperLimit = -_normal1;
|
||||
normal = -normal1;
|
||||
lowerLimit = -normal1;
|
||||
upperLimit = -normal1;
|
||||
}
|
||||
}
|
||||
else if (convex1)
|
||||
{
|
||||
_front = offset0 >= 0.0f || (offset1 >= 0.0f && offset2 >= 0.0f);
|
||||
if (_front)
|
||||
front = offset0 >= 0.0f || (offset1 >= 0.0f && offset2 >= 0.0f);
|
||||
if (front)
|
||||
{
|
||||
_normal = _normal1;
|
||||
_lowerLimit = _normal0;
|
||||
_upperLimit = _normal1;
|
||||
normal = normal1;
|
||||
lowerLimit = normal0;
|
||||
upperLimit = normal1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_normal = -_normal1;
|
||||
_lowerLimit = -_normal2;
|
||||
_upperLimit = -_normal1;
|
||||
normal = -normal1;
|
||||
lowerLimit = -normal2;
|
||||
upperLimit = -normal1;
|
||||
}
|
||||
}
|
||||
else if (convex2)
|
||||
{
|
||||
_front = offset2 >= 0.0f || (offset0 >= 0.0f && offset1 >= 0.0f);
|
||||
if (_front)
|
||||
front = offset2 >= 0.0f || (offset0 >= 0.0f && offset1 >= 0.0f);
|
||||
if (front)
|
||||
{
|
||||
_normal = _normal1;
|
||||
_lowerLimit = _normal1;
|
||||
_upperLimit = _normal2;
|
||||
normal = normal1;
|
||||
lowerLimit = normal1;
|
||||
upperLimit = normal2;
|
||||
}
|
||||
else
|
||||
{
|
||||
_normal = -_normal1;
|
||||
_lowerLimit = -_normal1;
|
||||
_upperLimit = -_normal0;
|
||||
normal = -normal1;
|
||||
lowerLimit = -normal1;
|
||||
upperLimit = -normal0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_front = offset0 >= 0.0f && offset1 >= 0.0f && offset2 >= 0.0f;
|
||||
if (_front)
|
||||
front = offset0 >= 0.0f && offset1 >= 0.0f && offset2 >= 0.0f;
|
||||
if (front)
|
||||
{
|
||||
_normal = _normal1;
|
||||
_lowerLimit = _normal1;
|
||||
_upperLimit = _normal1;
|
||||
normal = normal1;
|
||||
lowerLimit = normal1;
|
||||
upperLimit = normal1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_normal = -_normal1;
|
||||
_lowerLimit = -_normal2;
|
||||
_upperLimit = -_normal0;
|
||||
normal = -normal1;
|
||||
lowerLimit = -normal2;
|
||||
upperLimit = -normal0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1266,34 +1275,34 @@ namespace FarseerPhysics.Collision
|
||||
{
|
||||
if (convex1)
|
||||
{
|
||||
_front = offset0 >= 0.0f || offset1 >= 0.0f;
|
||||
if (_front)
|
||||
front = offset0 >= 0.0f || offset1 >= 0.0f;
|
||||
if (front)
|
||||
{
|
||||
_normal = _normal1;
|
||||
_lowerLimit = _normal0;
|
||||
_upperLimit = -_normal1;
|
||||
normal = normal1;
|
||||
lowerLimit = normal0;
|
||||
upperLimit = -normal1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_normal = -_normal1;
|
||||
_lowerLimit = _normal1;
|
||||
_upperLimit = -_normal1;
|
||||
normal = -normal1;
|
||||
lowerLimit = normal1;
|
||||
upperLimit = -normal1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_front = offset0 >= 0.0f && offset1 >= 0.0f;
|
||||
if (_front)
|
||||
front = offset0 >= 0.0f && offset1 >= 0.0f;
|
||||
if (front)
|
||||
{
|
||||
_normal = _normal1;
|
||||
_lowerLimit = _normal1;
|
||||
_upperLimit = -_normal1;
|
||||
normal = normal1;
|
||||
lowerLimit = normal1;
|
||||
upperLimit = -normal1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_normal = -_normal1;
|
||||
_lowerLimit = _normal1;
|
||||
_upperLimit = -_normal0;
|
||||
normal = -normal1;
|
||||
lowerLimit = normal1;
|
||||
upperLimit = -normal0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1301,67 +1310,67 @@ namespace FarseerPhysics.Collision
|
||||
{
|
||||
if (convex2)
|
||||
{
|
||||
_front = offset1 >= 0.0f || offset2 >= 0.0f;
|
||||
if (_front)
|
||||
front = offset1 >= 0.0f || offset2 >= 0.0f;
|
||||
if (front)
|
||||
{
|
||||
_normal = _normal1;
|
||||
_lowerLimit = -_normal1;
|
||||
_upperLimit = _normal2;
|
||||
normal = normal1;
|
||||
lowerLimit = -normal1;
|
||||
upperLimit = normal2;
|
||||
}
|
||||
else
|
||||
{
|
||||
_normal = -_normal1;
|
||||
_lowerLimit = -_normal1;
|
||||
_upperLimit = _normal1;
|
||||
normal = -normal1;
|
||||
lowerLimit = -normal1;
|
||||
upperLimit = normal1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_front = offset1 >= 0.0f && offset2 >= 0.0f;
|
||||
if (_front)
|
||||
front = offset1 >= 0.0f && offset2 >= 0.0f;
|
||||
if (front)
|
||||
{
|
||||
_normal = _normal1;
|
||||
_lowerLimit = -_normal1;
|
||||
_upperLimit = _normal1;
|
||||
normal = normal1;
|
||||
lowerLimit = -normal1;
|
||||
upperLimit = normal1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_normal = -_normal1;
|
||||
_lowerLimit = -_normal2;
|
||||
_upperLimit = _normal1;
|
||||
normal = -normal1;
|
||||
lowerLimit = -normal2;
|
||||
upperLimit = normal1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_front = offset1 >= 0.0f;
|
||||
if (_front)
|
||||
front = offset1 >= 0.0f;
|
||||
if (front)
|
||||
{
|
||||
_normal = _normal1;
|
||||
_lowerLimit = -_normal1;
|
||||
_upperLimit = -_normal1;
|
||||
normal = normal1;
|
||||
lowerLimit = -normal1;
|
||||
upperLimit = -normal1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_normal = -_normal1;
|
||||
_lowerLimit = _normal1;
|
||||
_upperLimit = _normal1;
|
||||
normal = -normal1;
|
||||
lowerLimit = normal1;
|
||||
upperLimit = normal1;
|
||||
}
|
||||
}
|
||||
|
||||
// Get polygonB in frameA
|
||||
_polygonB.Count = polygonB.Vertices.Count;
|
||||
tempPolygonB.Count = polygonB.Vertices.Count;
|
||||
for (int i = 0; i < polygonB.Vertices.Count; ++i)
|
||||
{
|
||||
_polygonB.Vertices[i] = MathUtils.Mul(ref _xf, polygonB.Vertices[i]);
|
||||
_polygonB.Normals[i] = MathUtils.Mul(_xf.q, polygonB.Normals[i]);
|
||||
tempPolygonB.Vertices[i] = Transform.Multiply(polygonB.Vertices[i], ref xf);
|
||||
tempPolygonB.Normals[i] = Complex.Multiply(polygonB.Normals[i], ref xf.q);
|
||||
}
|
||||
|
||||
_radius = 2.0f * Settings.PolygonRadius;
|
||||
radius = 2.0f * Settings.PolygonRadius;
|
||||
|
||||
manifold.PointCount = 0;
|
||||
|
||||
EPAxis edgeAxis = ComputeEdgeSeparation();
|
||||
EPAxis edgeAxis = ComputeEdgeSeparation(ref tempPolygonB, ref normal, ref v1, front);
|
||||
|
||||
// If no valid normal can be found than this edge should not collide.
|
||||
if (edgeAxis.Type == EPAxisType.Unknown)
|
||||
@@ -1369,13 +1378,13 @@ namespace FarseerPhysics.Collision
|
||||
return;
|
||||
}
|
||||
|
||||
if (edgeAxis.Separation > _radius)
|
||||
if (edgeAxis.Separation > radius)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EPAxis polygonAxis = ComputePolygonSeparation();
|
||||
if (polygonAxis.Type != EPAxisType.Unknown && polygonAxis.Separation > _radius)
|
||||
EPAxis polygonAxis = ComputePolygonSeparation(ref tempPolygonB, ref normal, ref v1, ref v2, ref lowerLimit, ref upperLimit, radius);
|
||||
if (polygonAxis.Type != EPAxisType.Unknown && polygonAxis.Separation > radius)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1406,10 +1415,10 @@ namespace FarseerPhysics.Collision
|
||||
|
||||
// Search for the polygon normal that is most anti-parallel to the edge normal.
|
||||
int bestIndex = 0;
|
||||
float bestValue = Vector2.Dot(_normal, _polygonB.Normals[0]);
|
||||
for (int i = 1; i < _polygonB.Count; ++i)
|
||||
float bestValue = Vector2.Dot(normal, tempPolygonB.Normals[0]);
|
||||
for (int i = 1; i < tempPolygonB.Count; ++i)
|
||||
{
|
||||
float value = Vector2.Dot(_normal, _polygonB.Normals[i]);
|
||||
float value = Vector2.Dot(normal, tempPolygonB.Normals[i]);
|
||||
if (value < bestValue)
|
||||
{
|
||||
bestValue = value;
|
||||
@@ -1418,10 +1427,10 @@ namespace FarseerPhysics.Collision
|
||||
}
|
||||
|
||||
int i1 = bestIndex;
|
||||
int i2 = i1 + 1 < _polygonB.Count ? i1 + 1 : 0;
|
||||
int i2 = i1 + 1 < tempPolygonB.Count ? i1 + 1 : 0;
|
||||
|
||||
ClipVertex c0 = ie[0];
|
||||
c0.V = _polygonB.Vertices[i1];
|
||||
c0.V = tempPolygonB.Vertices[i1];
|
||||
c0.ID.Features.IndexA = 0;
|
||||
c0.ID.Features.IndexB = (byte)i1;
|
||||
c0.ID.Features.TypeA = (byte)ContactFeatureType.Face;
|
||||
@@ -1429,35 +1438,35 @@ namespace FarseerPhysics.Collision
|
||||
ie[0] = c0;
|
||||
|
||||
ClipVertex c1 = ie[1];
|
||||
c1.V = _polygonB.Vertices[i2];
|
||||
c1.V = tempPolygonB.Vertices[i2];
|
||||
c1.ID.Features.IndexA = 0;
|
||||
c1.ID.Features.IndexB = (byte)i2;
|
||||
c1.ID.Features.TypeA = (byte)ContactFeatureType.Face;
|
||||
c1.ID.Features.TypeB = (byte)ContactFeatureType.Vertex;
|
||||
ie[1] = c1;
|
||||
|
||||
if (_front)
|
||||
if (front)
|
||||
{
|
||||
rf.i1 = 0;
|
||||
rf.i2 = 1;
|
||||
rf.v1 = _v1;
|
||||
rf.v2 = _v2;
|
||||
rf.normal = _normal1;
|
||||
rf.v1 = v1;
|
||||
rf.v2 = v2;
|
||||
rf.normal = normal1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rf.i1 = 1;
|
||||
rf.i2 = 0;
|
||||
rf.v1 = _v2;
|
||||
rf.v2 = _v1;
|
||||
rf.normal = -_normal1;
|
||||
rf.v1 = v2;
|
||||
rf.v2 = v1;
|
||||
rf.normal = -normal1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
manifold.Type = ManifoldType.FaceB;
|
||||
ClipVertex c0 = ie[0];
|
||||
c0.V = _v1;
|
||||
c0.V = v1;
|
||||
c0.ID.Features.IndexA = 0;
|
||||
c0.ID.Features.IndexB = (byte)primaryAxis.Index;
|
||||
c0.ID.Features.TypeA = (byte)ContactFeatureType.Vertex;
|
||||
@@ -1465,7 +1474,7 @@ namespace FarseerPhysics.Collision
|
||||
ie[0] = c0;
|
||||
|
||||
ClipVertex c1 = ie[1];
|
||||
c1.V = _v2;
|
||||
c1.V = v2;
|
||||
c1.ID.Features.IndexA = 0;
|
||||
c1.ID.Features.IndexB = (byte)primaryAxis.Index;
|
||||
c1.ID.Features.TypeA = (byte)ContactFeatureType.Vertex;
|
||||
@@ -1473,10 +1482,10 @@ namespace FarseerPhysics.Collision
|
||||
ie[1] = c1;
|
||||
|
||||
rf.i1 = primaryAxis.Index;
|
||||
rf.i2 = rf.i1 + 1 < _polygonB.Count ? rf.i1 + 1 : 0;
|
||||
rf.v1 = _polygonB.Vertices[rf.i1];
|
||||
rf.v2 = _polygonB.Vertices[rf.i2];
|
||||
rf.normal = _polygonB.Normals[rf.i1];
|
||||
rf.i2 = rf.i1 + 1 < tempPolygonB.Count ? rf.i1 + 1 : 0;
|
||||
rf.v1 = tempPolygonB.Vertices[rf.i1];
|
||||
rf.v2 = tempPolygonB.Vertices[rf.i2];
|
||||
rf.normal = tempPolygonB.Normals[rf.i1];
|
||||
}
|
||||
|
||||
rf.sideNormal1 = new Vector2(rf.normal.Y, -rf.normal.X);
|
||||
@@ -1522,13 +1531,13 @@ namespace FarseerPhysics.Collision
|
||||
{
|
||||
float separation = Vector2.Dot(rf.normal, clipPoints2[i].V - rf.v1);
|
||||
|
||||
if (separation <= _radius)
|
||||
if (separation <= radius)
|
||||
{
|
||||
ManifoldPoint cp = manifold.Points[pointCount];
|
||||
|
||||
if (primaryAxis.Type == EPAxisType.EdgeA)
|
||||
{
|
||||
cp.LocalPoint = MathUtils.MulT(ref _xf, clipPoints2[i].V);
|
||||
Transform.Divide(clipPoints2[i].V, ref xf, out cp.LocalPoint);
|
||||
cp.Id = clipPoints2[i].ID;
|
||||
}
|
||||
else
|
||||
@@ -1548,16 +1557,16 @@ namespace FarseerPhysics.Collision
|
||||
manifold.PointCount = pointCount;
|
||||
}
|
||||
|
||||
private EPAxis ComputeEdgeSeparation()
|
||||
private static EPAxis ComputeEdgeSeparation(ref TempPolygon polygonB, ref Vector2 normal, ref Vector2 v1, bool front)
|
||||
{
|
||||
EPAxis axis;
|
||||
axis.Type = EPAxisType.EdgeA;
|
||||
axis.Index = _front ? 0 : 1;
|
||||
axis.Index = front ? 0 : 1;
|
||||
axis.Separation = Settings.MaxFloat;
|
||||
|
||||
for (int i = 0; i < _polygonB.Count; ++i)
|
||||
for (int i = 0; i < polygonB.Count; ++i)
|
||||
{
|
||||
float s = Vector2.Dot(_normal, _polygonB.Vertices[i] - _v1);
|
||||
float s = Vector2.Dot(normal, polygonB.Vertices[i] - v1);
|
||||
if (s < axis.Separation)
|
||||
{
|
||||
axis.Separation = s;
|
||||
@@ -1567,24 +1576,24 @@ namespace FarseerPhysics.Collision
|
||||
return axis;
|
||||
}
|
||||
|
||||
private EPAxis ComputePolygonSeparation()
|
||||
private static EPAxis ComputePolygonSeparation(ref TempPolygon polygonB, ref Vector2 normal, ref Vector2 v1, ref Vector2 v2, ref Vector2 lowerLimit, ref Vector2 upperLimit, float radius)
|
||||
{
|
||||
EPAxis axis;
|
||||
axis.Type = EPAxisType.Unknown;
|
||||
axis.Index = -1;
|
||||
axis.Separation = -Settings.MaxFloat;
|
||||
|
||||
Vector2 perp = new Vector2(-_normal.Y, _normal.X);
|
||||
Vector2 perp = new Vector2(-normal.Y, normal.X);
|
||||
|
||||
for (int i = 0; i < _polygonB.Count; ++i)
|
||||
for (int i = 0; i < polygonB.Count; ++i)
|
||||
{
|
||||
Vector2 n = -_polygonB.Normals[i];
|
||||
Vector2 n = -polygonB.Normals[i];
|
||||
|
||||
float s1 = Vector2.Dot(n, _polygonB.Vertices[i] - _v1);
|
||||
float s2 = Vector2.Dot(n, _polygonB.Vertices[i] - _v2);
|
||||
float s1 = Vector2.Dot(n, polygonB.Vertices[i] - v1);
|
||||
float s2 = Vector2.Dot(n, polygonB.Vertices[i] - v2);
|
||||
float s = Math.Min(s1, s2);
|
||||
|
||||
if (s > _radius)
|
||||
if (s > radius)
|
||||
{
|
||||
// No collision
|
||||
axis.Type = EPAxisType.EdgeB;
|
||||
@@ -1596,14 +1605,14 @@ namespace FarseerPhysics.Collision
|
||||
// Adjacency
|
||||
if (Vector2.Dot(n, perp) >= 0.0f)
|
||||
{
|
||||
if (Vector2.Dot(n - _upperLimit, _normal) < -Settings.AngularSlop)
|
||||
if (Vector2.Dot(n - upperLimit, normal) < -Settings.AngularSlop)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Vector2.Dot(n - _lowerLimit, _normal) < -Settings.AngularSlop)
|
||||
if (Vector2.Dot(n - lowerLimit, normal) < -Settings.AngularSlop)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -1682,7 +1691,7 @@ namespace FarseerPhysics.Collision
|
||||
/// <param name="poly2">The poly2.</param>
|
||||
/// <param name="xf2">The XF2.</param>
|
||||
/// <returns></returns>
|
||||
private static float EdgeSeparation(PolygonShape poly1, ref Transform xf1, int edge1, PolygonShape poly2, ref Transform xf2)
|
||||
private static float EdgeSeparation(PolygonShape poly1, ref Transform xf1To2, int edge1, PolygonShape poly2)
|
||||
{
|
||||
List<Vector2> vertices1 = poly1.Vertices;
|
||||
List<Vector2> normals1 = poly1.Normals;
|
||||
@@ -1693,8 +1702,7 @@ namespace FarseerPhysics.Collision
|
||||
Debug.Assert(0 <= edge1 && edge1 < poly1.Vertices.Count);
|
||||
|
||||
// Convert normal from poly1's frame into poly2's frame.
|
||||
Vector2 normal1World = MathUtils.Mul(xf1.q, normals1[edge1]);
|
||||
Vector2 normal1 = MathUtils.MulT(xf2.q, normal1World);
|
||||
Vector2 normal1 = Complex.Multiply(normals1[edge1], ref xf1To2.q);
|
||||
|
||||
// Find support vertex on poly2 for -normal.
|
||||
int index = 0;
|
||||
@@ -1702,7 +1710,7 @@ namespace FarseerPhysics.Collision
|
||||
|
||||
for (int i = 0; i < count2; ++i)
|
||||
{
|
||||
float dot = Vector2.Dot(vertices2[i], normal1);
|
||||
float dot = MathUtils.Dot(vertices2[i], ref normal1);
|
||||
if (dot < minDot)
|
||||
{
|
||||
minDot = dot;
|
||||
@@ -1710,9 +1718,10 @@ namespace FarseerPhysics.Collision
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 v1 = MathUtils.Mul(ref xf1, vertices1[edge1]);
|
||||
Vector2 v2 = MathUtils.Mul(ref xf2, vertices2[index]);
|
||||
float separation = Vector2.Dot(v2 - v1, normal1World);
|
||||
Vector2 v1 = Transform.Multiply(vertices1[edge1], ref xf1To2);
|
||||
Vector2 v2 = vertices2[index];
|
||||
float separation = MathUtils.Dot(v2 - v1, ref normal1);
|
||||
|
||||
return separation;
|
||||
}
|
||||
|
||||
@@ -1730,16 +1739,18 @@ namespace FarseerPhysics.Collision
|
||||
int count1 = poly1.Vertices.Count;
|
||||
List<Vector2> normals1 = poly1.Normals;
|
||||
|
||||
var xf1To2 = Transform.Divide(ref xf1, ref xf2);
|
||||
|
||||
// Vector pointing from the centroid of poly1 to the centroid of poly2.
|
||||
Vector2 d = MathUtils.Mul(ref xf2, poly2.MassData.Centroid) - MathUtils.Mul(ref xf1, poly1.MassData.Centroid);
|
||||
Vector2 dLocal1 = MathUtils.MulT(xf1.q, d);
|
||||
Vector2 c2local = Transform.Divide(poly2.MassData.Centroid, ref xf1To2);
|
||||
Vector2 dLocal1 = c2local - poly1.MassData.Centroid;
|
||||
|
||||
// Find edge normal on poly1 that has the largest projection onto d.
|
||||
int edge = 0;
|
||||
float maxDot = -Settings.MaxFloat;
|
||||
for (int i = 0; i < count1; ++i)
|
||||
{
|
||||
float dot = Vector2.Dot(normals1[i], dLocal1);
|
||||
float dot = MathUtils.Dot(normals1[i], ref dLocal1);
|
||||
if (dot > maxDot)
|
||||
{
|
||||
maxDot = dot;
|
||||
@@ -1748,15 +1759,15 @@ namespace FarseerPhysics.Collision
|
||||
}
|
||||
|
||||
// Get the separation for the edge normal.
|
||||
float s = EdgeSeparation(poly1, ref xf1, edge, poly2, ref xf2);
|
||||
float s = EdgeSeparation(poly1, ref xf1To2, edge, poly2);
|
||||
|
||||
// Check the separation for the previous edge normal.
|
||||
int prevEdge = edge - 1 >= 0 ? edge - 1 : count1 - 1;
|
||||
float sPrev = EdgeSeparation(poly1, ref xf1, prevEdge, poly2, ref xf2);
|
||||
float sPrev = EdgeSeparation(poly1, ref xf1To2, prevEdge, poly2);
|
||||
|
||||
// Check the separation for the next edge normal.
|
||||
int nextEdge = edge + 1 < count1 ? edge + 1 : 0;
|
||||
float sNext = EdgeSeparation(poly1, ref xf1, nextEdge, poly2, ref xf2);
|
||||
float sNext = EdgeSeparation(poly1, ref xf1To2, nextEdge, poly2);
|
||||
|
||||
// Find the best edge and the search direction.
|
||||
int bestEdge;
|
||||
@@ -1788,7 +1799,7 @@ namespace FarseerPhysics.Collision
|
||||
else
|
||||
edge = bestEdge + 1 < count1 ? bestEdge + 1 : 0;
|
||||
|
||||
s = EdgeSeparation(poly1, ref xf1, edge, poly2, ref xf2);
|
||||
s = EdgeSeparation(poly1, ref xf1To2, edge, poly2);
|
||||
|
||||
if (s > bestSeparation)
|
||||
{
|
||||
@@ -1817,7 +1828,7 @@ namespace FarseerPhysics.Collision
|
||||
Debug.Assert(0 <= edge1 && edge1 < poly1.Vertices.Count);
|
||||
|
||||
// Get the normal of the reference edge in poly2's frame.
|
||||
Vector2 normal1 = MathUtils.MulT(xf2.q, MathUtils.Mul(xf1.q, normals1[edge1]));
|
||||
Vector2 normal1 = Complex.Divide(Complex.Multiply(normals1[edge1], ref xf1.q), ref xf2.q);
|
||||
|
||||
|
||||
// Find the incident edge on poly2.
|
||||
@@ -1839,7 +1850,7 @@ namespace FarseerPhysics.Collision
|
||||
|
||||
ClipVertex cv0 = c[0];
|
||||
|
||||
cv0.V = MathUtils.Mul(ref xf2, vertices2[i1]);
|
||||
cv0.V = Transform.Multiply(vertices2[i1], ref xf2);
|
||||
cv0.ID.Features.IndexA = (byte)edge1;
|
||||
cv0.ID.Features.IndexB = (byte)i1;
|
||||
cv0.ID.Features.TypeA = (byte)ContactFeatureType.Face;
|
||||
@@ -1848,7 +1859,7 @@ namespace FarseerPhysics.Collision
|
||||
c[0] = cv0;
|
||||
|
||||
ClipVertex cv1 = c[1];
|
||||
cv1.V = MathUtils.Mul(ref xf2, vertices2[i2]);
|
||||
cv1.V = Transform.Multiply(vertices2[i2], ref xf2);
|
||||
cv1.ID.Features.IndexA = (byte)edge1;
|
||||
cv1.ID.Features.IndexB = (byte)i2;
|
||||
cv1.ID.Features.TypeA = (byte)ContactFeatureType.Face;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/*
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
*
|
||||
@@ -24,6 +29,7 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using FarseerPhysics.Collision.Shapes;
|
||||
using FarseerPhysics.Common;
|
||||
using FarseerPhysics.Common.Maths;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Collision
|
||||
@@ -32,10 +38,10 @@ namespace FarseerPhysics.Collision
|
||||
/// A distance proxy is used by the GJK algorithm.
|
||||
/// It encapsulates any shape.
|
||||
/// </summary>
|
||||
public class DistanceProxy
|
||||
public struct DistanceProxy
|
||||
{
|
||||
internal float Radius;
|
||||
internal Vertices Vertices = new Vertices();
|
||||
internal Vertices Vertices;
|
||||
|
||||
// GJK using Voronoi regions (Christer Ericson) and Barycentric coordinates.
|
||||
|
||||
@@ -45,8 +51,10 @@ namespace FarseerPhysics.Collision
|
||||
/// </summary>
|
||||
/// <param name="shape">The shape.</param>
|
||||
/// <param name="index">The index.</param>
|
||||
public void Set(Shape shape, int index)
|
||||
public DistanceProxy(Shape shape, int index)
|
||||
{
|
||||
Vertices = new Vertices();
|
||||
|
||||
switch (shape.ShapeType)
|
||||
{
|
||||
case ShapeType.Circle:
|
||||
@@ -93,6 +101,7 @@ namespace FarseerPhysics.Collision
|
||||
break;
|
||||
|
||||
default:
|
||||
Radius = 0;
|
||||
Debug.Assert(false);
|
||||
break;
|
||||
}
|
||||
@@ -171,10 +180,10 @@ namespace FarseerPhysics.Collision
|
||||
/// Input for Distance.ComputeDistance().
|
||||
/// You have to option to use the shape radii in the computation.
|
||||
/// </summary>
|
||||
public class DistanceInput
|
||||
public struct DistanceInput
|
||||
{
|
||||
public DistanceProxy ProxyA = new DistanceProxy();
|
||||
public DistanceProxy ProxyB = new DistanceProxy();
|
||||
public DistanceProxy ProxyA;
|
||||
public DistanceProxy ProxyB;
|
||||
public Transform TransformA;
|
||||
public Transform TransformB;
|
||||
public bool UseRadii;
|
||||
@@ -241,7 +250,7 @@ namespace FarseerPhysics.Collision
|
||||
internal int Count;
|
||||
internal FixedArray3<SimplexVertex> V;
|
||||
|
||||
internal void ReadCache(ref SimplexCache cache, DistanceProxy proxyA, ref Transform transformA, DistanceProxy proxyB, ref Transform transformB)
|
||||
internal void ReadCache(ref SimplexCache cache, ref DistanceProxy proxyA, ref Transform transformA, ref DistanceProxy proxyB, ref Transform transformB)
|
||||
{
|
||||
Debug.Assert(cache.Count <= 3);
|
||||
|
||||
@@ -254,8 +263,8 @@ namespace FarseerPhysics.Collision
|
||||
v.IndexB = cache.IndexB[i];
|
||||
Vector2 wALocal = proxyA.Vertices[v.IndexA];
|
||||
Vector2 wBLocal = proxyB.Vertices[v.IndexB];
|
||||
v.WA = MathUtils.Mul(ref transformA, wALocal);
|
||||
v.WB = MathUtils.Mul(ref transformB, wBLocal);
|
||||
v.WA = Transform.Multiply(ref wALocal, ref transformA);
|
||||
v.WB = Transform.Multiply(ref wBLocal, ref transformB);
|
||||
v.W = v.WB - v.WA;
|
||||
v.A = 0.0f;
|
||||
V[i] = v;
|
||||
@@ -282,8 +291,8 @@ namespace FarseerPhysics.Collision
|
||||
v.IndexB = 0;
|
||||
Vector2 wALocal = proxyA.Vertices[0];
|
||||
Vector2 wBLocal = proxyB.Vertices[0];
|
||||
v.WA = MathUtils.Mul(ref transformA, wALocal);
|
||||
v.WB = MathUtils.Mul(ref transformB, wBLocal);
|
||||
v.WA = Transform.Multiply(ref wALocal, ref transformA);
|
||||
v.WB = Transform.Multiply(ref wBLocal, ref transformB);
|
||||
v.W = v.WB - v.WA;
|
||||
v.A = 1.0f;
|
||||
V[0] = v;
|
||||
@@ -514,11 +523,11 @@ namespace FarseerPhysics.Collision
|
||||
float d23_2 = -w2e23;
|
||||
|
||||
// Triangle123
|
||||
float n123 = MathUtils.Cross(e12, e13);
|
||||
float n123 = MathUtils.Cross(ref e12, ref e13);
|
||||
|
||||
float d123_1 = n123 * MathUtils.Cross(w2, w3);
|
||||
float d123_2 = n123 * MathUtils.Cross(w3, w1);
|
||||
float d123_3 = n123 * MathUtils.Cross(w1, w2);
|
||||
float d123_1 = n123 * MathUtils.Cross(ref w2, ref w3);
|
||||
float d123_2 = n123 * MathUtils.Cross(ref w3, ref w1);
|
||||
float d123_3 = n123 * MathUtils.Cross(ref w1, ref w2);
|
||||
|
||||
// w1 region
|
||||
if (d12_2 <= 0.0f && d13_2 <= 0.0f)
|
||||
@@ -646,7 +655,7 @@ namespace FarseerPhysics.Collision
|
||||
|
||||
// Initialize the simplex.
|
||||
Simplex simplex = new Simplex();
|
||||
simplex.ReadCache(ref cache, input.ProxyA, ref input.TransformA, input.ProxyB, ref input.TransformB);
|
||||
simplex.ReadCache(ref cache, ref input.ProxyA, ref input.TransformA, ref input.ProxyB, ref input.TransformB);
|
||||
|
||||
// These store the vertices of the last simplex so that we
|
||||
// can check for duplicates and prevent cycling.
|
||||
@@ -717,11 +726,11 @@ namespace FarseerPhysics.Collision
|
||||
|
||||
// Compute a tentative new simplex vertex using support points.
|
||||
SimplexVertex vertex = simplex.V[simplex.Count];
|
||||
vertex.IndexA = input.ProxyA.GetSupport(MathUtils.MulT(input.TransformA.q, -d));
|
||||
vertex.WA = MathUtils.Mul(ref input.TransformA, input.ProxyA.Vertices[vertex.IndexA]);
|
||||
vertex.IndexA = input.ProxyA.GetSupport(-Complex.Divide(ref d, ref input.TransformA.q));
|
||||
vertex.WA = Transform.Multiply(input.ProxyA.Vertices[vertex.IndexA], ref input.TransformA);
|
||||
|
||||
vertex.IndexB = input.ProxyB.GetSupport(MathUtils.MulT(input.TransformB.q, d));
|
||||
vertex.WB = MathUtils.Mul(ref input.TransformB, input.ProxyB.Vertices[vertex.IndexB]);
|
||||
vertex.IndexB = input.ProxyB.GetSupport( Complex.Divide(ref d, ref input.TransformB.q));
|
||||
vertex.WB = Transform.Multiply(input.ProxyB.Vertices[vertex.IndexB], ref input.TransformB);
|
||||
vertex.W = vertex.WB - vertex.WA;
|
||||
simplex.V[simplex.Count] = vertex;
|
||||
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
/*
|
||||
// Copyright (c) 2018 Kastellanos Nikolaos
|
||||
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
*
|
||||
@@ -24,6 +31,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using FarseerPhysics.Common;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Collision
|
||||
@@ -31,7 +39,7 @@ namespace FarseerPhysics.Collision
|
||||
/// <summary>
|
||||
/// A node in the dynamic tree. The client does not interact with this directly.
|
||||
/// </summary>
|
||||
internal class TreeNode<T>
|
||||
internal struct TreeNode<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Enlarged AABB
|
||||
@@ -41,8 +49,12 @@ namespace FarseerPhysics.Collision
|
||||
internal int Child1;
|
||||
internal int Child2;
|
||||
|
||||
// leaf = 0, free node = -1
|
||||
internal int Height;
|
||||
internal int ParentOrNext;
|
||||
|
||||
public object Body;
|
||||
|
||||
internal T UserData;
|
||||
|
||||
internal bool IsLeaf()
|
||||
@@ -85,13 +97,11 @@ namespace FarseerPhysics.Collision
|
||||
// Build a linked list for the free list.
|
||||
for (int i = 0; i < _nodeCapacity - 1; ++i)
|
||||
{
|
||||
_nodes[i] = new TreeNode<T>();
|
||||
_nodes[i].ParentOrNext = i + 1;
|
||||
_nodes[i].Height = 1;
|
||||
_nodes[i].Height = -1;
|
||||
}
|
||||
_nodes[_nodeCapacity - 1] = new TreeNode<T>();
|
||||
_nodes[_nodeCapacity - 1].ParentOrNext = NullNode;
|
||||
_nodes[_nodeCapacity - 1].Height = 1;
|
||||
_nodes[_nodeCapacity - 1].Height = -1;
|
||||
_freeList = 0;
|
||||
}
|
||||
|
||||
@@ -123,20 +133,20 @@ namespace FarseerPhysics.Collision
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
TreeNode<T> root = _nodes[_root];
|
||||
float rootArea = root.AABB.Perimeter;
|
||||
//TreeNode<T>* root = &_nodes[_root];
|
||||
float rootArea = _nodes[_root].AABB.Perimeter;
|
||||
|
||||
float totalArea = 0.0f;
|
||||
for (int i = 0; i < _nodeCapacity; ++i)
|
||||
{
|
||||
TreeNode<T> node = _nodes[i];
|
||||
if (node.Height < 0)
|
||||
//TreeNode<T>* node = &_nodes[i];
|
||||
if (_nodes[i].Height < 0)
|
||||
{
|
||||
// Free node in pool
|
||||
continue;
|
||||
}
|
||||
|
||||
totalArea += node.AABB.Perimeter;
|
||||
totalArea += _nodes[i].AABB.Perimeter;
|
||||
}
|
||||
|
||||
return totalArea / rootArea;
|
||||
@@ -154,16 +164,16 @@ namespace FarseerPhysics.Collision
|
||||
int maxBalance = 0;
|
||||
for (int i = 0; i < _nodeCapacity; ++i)
|
||||
{
|
||||
TreeNode<T> node = _nodes[i];
|
||||
if (node.Height <= 1)
|
||||
//TreeNode<T>* node = &_nodes[i];
|
||||
if (_nodes[i].Height <= 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Debug.Assert(node.IsLeaf() == false);
|
||||
Debug.Assert(_nodes[i].IsLeaf() == false);
|
||||
|
||||
int child1 = node.Child1;
|
||||
int child2 = node.Child2;
|
||||
int child1 = _nodes[i].Child1;
|
||||
int child2 = _nodes[i].Child2;
|
||||
int balance = Math.Abs(_nodes[child2].Height - _nodes[child1].Height);
|
||||
maxBalance = Math.Max(maxBalance, balance);
|
||||
}
|
||||
@@ -180,7 +190,7 @@ namespace FarseerPhysics.Collision
|
||||
/// <param name="aabb">The aabb.</param>
|
||||
/// <param name="userData">The user data.</param>
|
||||
/// <returns>Index of the created proxy</returns>
|
||||
public int AddProxy(ref AABB aabb, T userData)
|
||||
public int AddProxy(ref AABB aabb)
|
||||
{
|
||||
int proxyId = AllocateNode();
|
||||
|
||||
@@ -188,7 +198,6 @@ namespace FarseerPhysics.Collision
|
||||
Vector2 r = new Vector2(Settings.AABBExtension, Settings.AABBExtension);
|
||||
_nodes[proxyId].AABB.LowerBound = aabb.LowerBound - r;
|
||||
_nodes[proxyId].AABB.UpperBound = aabb.UpperBound + r;
|
||||
_nodes[proxyId].UserData = userData;
|
||||
_nodes[proxyId].Height = 0;
|
||||
|
||||
InsertLeaf(proxyId);
|
||||
@@ -264,6 +273,18 @@ namespace FarseerPhysics.Collision
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set proxy user data.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="proxyId">The proxy id.</param>
|
||||
/// <param name="userData">The proxy user data.</param>
|
||||
public void SetUserData(int proxyId, T userData, Body body)
|
||||
{
|
||||
_nodes[proxyId].UserData = userData;
|
||||
_nodes[proxyId].Body = body;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get proxy user data.
|
||||
/// </summary>
|
||||
@@ -287,12 +308,75 @@ namespace FarseerPhysics.Collision
|
||||
fatAABB = _nodes[proxyId].AABB;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the fat AABB for a proxy.
|
||||
/// </summary>
|
||||
/// <param name="proxyId">The proxy id.</param>
|
||||
/// <returns>The fat AABB.</returns>
|
||||
public AABB GetFatAABB(int proxyId)
|
||||
{
|
||||
Debug.Assert(0 <= proxyId && proxyId < _nodeCapacity);
|
||||
return _nodes[proxyId].AABB;
|
||||
}
|
||||
|
||||
public object GetBody(int proxyId)
|
||||
{
|
||||
Debug.Assert(0 <= proxyId && proxyId < _nodeCapacity);
|
||||
return _nodes[proxyId].Body;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Test overlap of fat AABBs.
|
||||
/// </summary>
|
||||
/// <param name="proxyIdA">The proxy id A.</param>
|
||||
/// <param name="proxyIdB">The proxy id B.</param>
|
||||
public bool TestFatAABBOverlap(int proxyIdA, int proxyIdB)
|
||||
{
|
||||
Debug.Assert(0 <= proxyIdA && proxyIdA < _nodeCapacity);
|
||||
Debug.Assert(0 <= proxyIdB && proxyIdB < _nodeCapacity);
|
||||
return AABB.TestOverlap(ref _nodes[proxyIdA].AABB, ref _nodes[proxyIdB].AABB);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query an AABB for overlapping proxies. The callback class
|
||||
/// is called for each proxy that overlaps the supplied AABB.
|
||||
/// </summary>
|
||||
/// <param name="callback">The callback.</param>
|
||||
/// <param name="aabb">The aabb.</param>
|
||||
public void Query(Func<int, bool> callback, ref AABB aabb, ref object body)
|
||||
{
|
||||
_queryStack.Clear();
|
||||
_queryStack.Push(_root);
|
||||
|
||||
while (_queryStack.Count > 0)
|
||||
{
|
||||
int nodeId = _queryStack.Pop();
|
||||
if (nodeId == NullNode)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//TreeNode<T>* node = &_nodes[nodeId];
|
||||
if (!ReferenceEquals(_nodes[nodeId].Body, body) && AABB.TestOverlap(ref _nodes[nodeId].AABB, ref aabb))
|
||||
{
|
||||
if (_nodes[nodeId].IsLeaf())
|
||||
{
|
||||
bool proceed = callback(nodeId);
|
||||
if (proceed == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_queryStack.Push(_nodes[nodeId].Child1);
|
||||
_queryStack.Push(_nodes[nodeId].Child2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Query(Func<int, bool> callback, ref AABB aabb)
|
||||
{
|
||||
_queryStack.Clear();
|
||||
@@ -306,11 +390,10 @@ namespace FarseerPhysics.Collision
|
||||
continue;
|
||||
}
|
||||
|
||||
TreeNode<T> node = _nodes[nodeId];
|
||||
|
||||
if (AABB.TestOverlap(ref node.AABB, ref aabb))
|
||||
//TreeNode<T>* node = &_nodes[nodeId];
|
||||
if (AABB.TestOverlap(ref _nodes[nodeId].AABB, ref aabb))
|
||||
{
|
||||
if (node.IsLeaf())
|
||||
if (_nodes[nodeId].IsLeaf())
|
||||
{
|
||||
bool proceed = callback(nodeId);
|
||||
if (proceed == false)
|
||||
@@ -320,8 +403,8 @@ namespace FarseerPhysics.Collision
|
||||
}
|
||||
else
|
||||
{
|
||||
_queryStack.Push(node.Child1);
|
||||
_queryStack.Push(node.Child2);
|
||||
_queryStack.Push(_nodes[nodeId].Child1);
|
||||
_queryStack.Push(_nodes[nodeId].Child2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -336,7 +419,8 @@ namespace FarseerPhysics.Collision
|
||||
/// </summary>
|
||||
/// <param name="callback">A callback class that is called for each proxy that is hit by the ray.</param>
|
||||
/// <param name="input">The ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).</param>
|
||||
public void RayCast(Func<RayCastInput, int, float> callback, ref RayCastInput input)
|
||||
/// <param name="collisionCategory">The collision categories of the fixtures to raycast against.</param>
|
||||
public void RayCast(IBroadPhase broadPhase, Func<RayCastInput, FixtureProxy, float> callback, ref RayCastInput input, Category collisionCategory = Category.All)
|
||||
{
|
||||
Vector2 p1 = input.Point1;
|
||||
Vector2 p2 = input.Point2;
|
||||
@@ -371,31 +455,39 @@ namespace FarseerPhysics.Collision
|
||||
continue;
|
||||
}
|
||||
|
||||
TreeNode<T> node = _nodes[nodeId];
|
||||
//TreeNode<T>* node = &_nodes[nodeId];
|
||||
|
||||
if (AABB.TestOverlap(ref node.AABB, ref segmentAABB) == false)
|
||||
if (AABB.TestOverlap(ref _nodes[nodeId].AABB, ref segmentAABB) == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Separating axis for segment (Gino, p80).
|
||||
// |dot(v, p1 - c)| > dot(|v|, h)
|
||||
Vector2 c = node.AABB.Center;
|
||||
Vector2 h = node.AABB.Extents;
|
||||
Vector2 c = _nodes[nodeId].AABB.Center;
|
||||
Vector2 h = _nodes[nodeId].AABB.Extents;
|
||||
float separation = Math.Abs(Vector2.Dot(new Vector2(-r.Y, r.X), p1 - c)) - Vector2.Dot(absV, h);
|
||||
if (separation > 0.0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node.IsLeaf())
|
||||
if (_nodes[nodeId].IsLeaf())
|
||||
{
|
||||
FixtureProxy proxy = broadPhase.GetProxy(nodeId);
|
||||
if (collisionCategory != Category.All &&
|
||||
//!collisionCategory.HasFlag(proxy.Fixture.CollisionCategories)
|
||||
(collisionCategory & proxy.Fixture.CollisionCategories) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RayCastInput subInput;
|
||||
subInput.Point1 = input.Point1;
|
||||
subInput.Point2 = input.Point2;
|
||||
subInput.MaxFraction = maxFraction;
|
||||
|
||||
float value = callback(subInput, nodeId);
|
||||
float value = callback(subInput, proxy);
|
||||
|
||||
if (value == 0.0f)
|
||||
{
|
||||
@@ -408,14 +500,14 @@ namespace FarseerPhysics.Collision
|
||||
// Update segment bounding box.
|
||||
maxFraction = value;
|
||||
Vector2 t = p1 + maxFraction * (p2 - p1);
|
||||
segmentAABB.LowerBound = Vector2.Min(p1, t);
|
||||
segmentAABB.UpperBound = Vector2.Max(p1, t);
|
||||
Vector2.Min(ref p1, ref t, out segmentAABB.LowerBound);
|
||||
Vector2.Max(ref p1, ref t, out segmentAABB.UpperBound);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_raycastStack.Push(node.Child1);
|
||||
_raycastStack.Push(node.Child2);
|
||||
_raycastStack.Push(_nodes[nodeId].Child1);
|
||||
_raycastStack.Push(_nodes[nodeId].Child2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -437,11 +529,9 @@ namespace FarseerPhysics.Collision
|
||||
// pointer becomes the "next" pointer.
|
||||
for (int i = _nodeCount; i < _nodeCapacity - 1; ++i)
|
||||
{
|
||||
_nodes[i] = new TreeNode<T>();
|
||||
_nodes[i].ParentOrNext = i + 1;
|
||||
_nodes[i].Height = -1;
|
||||
}
|
||||
_nodes[_nodeCapacity - 1] = new TreeNode<T>();
|
||||
_nodes[_nodeCapacity - 1].ParentOrNext = NullNode;
|
||||
_nodes[_nodeCapacity - 1].Height = -1;
|
||||
_freeList = _nodeCount;
|
||||
@@ -675,48 +765,48 @@ namespace FarseerPhysics.Collision
|
||||
{
|
||||
Debug.Assert(iA != NullNode);
|
||||
|
||||
TreeNode<T> A = _nodes[iA];
|
||||
if (A.IsLeaf() || A.Height < 2)
|
||||
//TreeNode<T>* A = &_nodes[iA];
|
||||
if (_nodes[iA].IsLeaf() || _nodes[iA].Height < 2)
|
||||
{
|
||||
return iA;
|
||||
}
|
||||
|
||||
int iB = A.Child1;
|
||||
int iC = A.Child2;
|
||||
int iB = _nodes[iA].Child1;
|
||||
int iC = _nodes[iA].Child2;
|
||||
Debug.Assert(0 <= iB && iB < _nodeCapacity);
|
||||
Debug.Assert(0 <= iC && iC < _nodeCapacity);
|
||||
|
||||
TreeNode<T> B = _nodes[iB];
|
||||
TreeNode<T> C = _nodes[iC];
|
||||
//TreeNode<T>* B = &_nodes[iB];
|
||||
//TreeNode<T>* C = &_nodes[iC];
|
||||
|
||||
int balance = C.Height - B.Height;
|
||||
int balance = _nodes[iC].Height - _nodes[iB].Height;
|
||||
|
||||
// Rotate C up
|
||||
if (balance > 1)
|
||||
{
|
||||
int iF = C.Child1;
|
||||
int iG = C.Child2;
|
||||
TreeNode<T> F = _nodes[iF];
|
||||
TreeNode<T> G = _nodes[iG];
|
||||
int iF = _nodes[iC].Child1;
|
||||
int iG = _nodes[iC].Child2;
|
||||
//TreeNode<T>* F = &_nodes[iF];
|
||||
//TreeNode<T>* G = &_nodes[iG];
|
||||
Debug.Assert(0 <= iF && iF < _nodeCapacity);
|
||||
Debug.Assert(0 <= iG && iG < _nodeCapacity);
|
||||
|
||||
// Swap A and C
|
||||
C.Child1 = iA;
|
||||
C.ParentOrNext = A.ParentOrNext;
|
||||
A.ParentOrNext = iC;
|
||||
_nodes[iC].Child1 = iA;
|
||||
_nodes[iC].ParentOrNext = _nodes[iA].ParentOrNext;
|
||||
_nodes[iA].ParentOrNext = iC;
|
||||
|
||||
// A's old parent should point to C
|
||||
if (C.ParentOrNext != NullNode)
|
||||
if (_nodes[iC].ParentOrNext != NullNode)
|
||||
{
|
||||
if (_nodes[C.ParentOrNext].Child1 == iA)
|
||||
if (_nodes[_nodes[iC].ParentOrNext].Child1 == iA)
|
||||
{
|
||||
_nodes[C.ParentOrNext].Child1 = iC;
|
||||
_nodes[_nodes[iC].ParentOrNext].Child1 = iC;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(_nodes[C.ParentOrNext].Child2 == iA);
|
||||
_nodes[C.ParentOrNext].Child2 = iC;
|
||||
Debug.Assert(_nodes[_nodes[iC].ParentOrNext].Child2 == iA);
|
||||
_nodes[_nodes[iC].ParentOrNext].Child2 = iC;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -725,27 +815,27 @@ namespace FarseerPhysics.Collision
|
||||
}
|
||||
|
||||
// Rotate
|
||||
if (F.Height > G.Height)
|
||||
if (_nodes[iF].Height > _nodes[iG].Height)
|
||||
{
|
||||
C.Child2 = iF;
|
||||
A.Child2 = iG;
|
||||
G.ParentOrNext = iA;
|
||||
A.AABB.Combine(ref B.AABB, ref G.AABB);
|
||||
C.AABB.Combine(ref A.AABB, ref F.AABB);
|
||||
_nodes[iC].Child2 = iF;
|
||||
_nodes[iA].Child2 = iG;
|
||||
_nodes[iG].ParentOrNext = iA;
|
||||
_nodes[iA].AABB.Combine(ref _nodes[iB].AABB, ref _nodes[iG].AABB);
|
||||
_nodes[iC].AABB.Combine(ref _nodes[iA].AABB, ref _nodes[iF].AABB);
|
||||
|
||||
A.Height = 1 + Math.Max(B.Height, G.Height);
|
||||
C.Height = 1 + Math.Max(A.Height, F.Height);
|
||||
_nodes[iA].Height = 1 + Math.Max(_nodes[iB].Height, _nodes[iG].Height);
|
||||
_nodes[iC].Height = 1 + Math.Max(_nodes[iA].Height, _nodes[iF].Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
C.Child2 = iG;
|
||||
A.Child2 = iF;
|
||||
F.ParentOrNext = iA;
|
||||
A.AABB.Combine(ref B.AABB, ref F.AABB);
|
||||
C.AABB.Combine(ref A.AABB, ref G.AABB);
|
||||
_nodes[iC].Child2 = iG;
|
||||
_nodes[iA].Child2 = iF;
|
||||
_nodes[iF].ParentOrNext = iA;
|
||||
_nodes[iA].AABB.Combine(ref _nodes[iB].AABB, ref _nodes[iF].AABB);
|
||||
_nodes[iC].AABB.Combine(ref _nodes[iA].AABB, ref _nodes[iG].AABB);
|
||||
|
||||
A.Height = 1 + Math.Max(B.Height, F.Height);
|
||||
C.Height = 1 + Math.Max(A.Height, G.Height);
|
||||
_nodes[iA].Height = 1 + Math.Max(_nodes[iB].Height, _nodes[iF].Height);
|
||||
_nodes[iC].Height = 1 + Math.Max(_nodes[iA].Height, _nodes[iG].Height);
|
||||
}
|
||||
|
||||
return iC;
|
||||
@@ -754,29 +844,29 @@ namespace FarseerPhysics.Collision
|
||||
// Rotate B up
|
||||
if (balance < -1)
|
||||
{
|
||||
int iD = B.Child1;
|
||||
int iE = B.Child2;
|
||||
TreeNode<T> D = _nodes[iD];
|
||||
TreeNode<T> E = _nodes[iE];
|
||||
int iD = _nodes[iB].Child1;
|
||||
int iE = _nodes[iB].Child2;
|
||||
//TreeNode<T>* D = &_nodes[iD];
|
||||
//TreeNode<T>* E = &_nodes[iE];
|
||||
Debug.Assert(0 <= iD && iD < _nodeCapacity);
|
||||
Debug.Assert(0 <= iE && iE < _nodeCapacity);
|
||||
|
||||
// Swap A and B
|
||||
B.Child1 = iA;
|
||||
B.ParentOrNext = A.ParentOrNext;
|
||||
A.ParentOrNext = iB;
|
||||
_nodes[iB].Child1 = iA;
|
||||
_nodes[iB].ParentOrNext = _nodes[iA].ParentOrNext;
|
||||
_nodes[iA].ParentOrNext = iB;
|
||||
|
||||
// A's old parent should point to B
|
||||
if (B.ParentOrNext != NullNode)
|
||||
if (_nodes[iB].ParentOrNext != NullNode)
|
||||
{
|
||||
if (_nodes[B.ParentOrNext].Child1 == iA)
|
||||
if (_nodes[_nodes[iB].ParentOrNext].Child1 == iA)
|
||||
{
|
||||
_nodes[B.ParentOrNext].Child1 = iB;
|
||||
_nodes[_nodes[iB].ParentOrNext].Child1 = iB;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(_nodes[B.ParentOrNext].Child2 == iA);
|
||||
_nodes[B.ParentOrNext].Child2 = iB;
|
||||
Debug.Assert(_nodes[_nodes[iB].ParentOrNext].Child2 == iA);
|
||||
_nodes[_nodes[iB].ParentOrNext].Child2 = iB;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -785,27 +875,27 @@ namespace FarseerPhysics.Collision
|
||||
}
|
||||
|
||||
// Rotate
|
||||
if (D.Height > E.Height)
|
||||
if (_nodes[iD].Height > _nodes[iE].Height)
|
||||
{
|
||||
B.Child2 = iD;
|
||||
A.Child1 = iE;
|
||||
E.ParentOrNext = iA;
|
||||
A.AABB.Combine(ref C.AABB, ref E.AABB);
|
||||
B.AABB.Combine(ref A.AABB, ref D.AABB);
|
||||
_nodes[iB].Child2 = iD;
|
||||
_nodes[iA].Child1 = iE;
|
||||
_nodes[iE].ParentOrNext = iA;
|
||||
_nodes[iA].AABB.Combine(ref _nodes[iC].AABB, ref _nodes[iE].AABB);
|
||||
_nodes[iB].AABB.Combine(ref _nodes[iA].AABB, ref _nodes[iD].AABB);
|
||||
|
||||
A.Height = 1 + Math.Max(C.Height, E.Height);
|
||||
B.Height = 1 + Math.Max(A.Height, D.Height);
|
||||
_nodes[iA].Height = 1 + Math.Max(_nodes[iC].Height, _nodes[iE].Height);
|
||||
_nodes[iB].Height = 1 + Math.Max(_nodes[iA].Height, _nodes[iD].Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
B.Child2 = iE;
|
||||
A.Child1 = iD;
|
||||
D.ParentOrNext = iA;
|
||||
A.AABB.Combine(ref C.AABB, ref D.AABB);
|
||||
B.AABB.Combine(ref A.AABB, ref E.AABB);
|
||||
_nodes[iB].Child2 = iE;
|
||||
_nodes[iA].Child1 = iD;
|
||||
_nodes[iD].ParentOrNext = iA;
|
||||
_nodes[iA].AABB.Combine(ref _nodes[iC].AABB, ref _nodes[iD].AABB);
|
||||
_nodes[iB].AABB.Combine(ref _nodes[iA].AABB, ref _nodes[iE].AABB);
|
||||
|
||||
A.Height = 1 + Math.Max(C.Height, D.Height);
|
||||
B.Height = 1 + Math.Max(A.Height, E.Height);
|
||||
_nodes[iA].Height = 1 + Math.Max(_nodes[iC].Height, _nodes[iD].Height);
|
||||
_nodes[iB].Height = 1 + Math.Max(_nodes[iA].Height, _nodes[iE].Height);
|
||||
}
|
||||
|
||||
return iB;
|
||||
@@ -822,15 +912,15 @@ namespace FarseerPhysics.Collision
|
||||
public int ComputeHeight(int nodeId)
|
||||
{
|
||||
Debug.Assert(0 <= nodeId && nodeId < _nodeCapacity);
|
||||
TreeNode<T> node = _nodes[nodeId];
|
||||
//TreeNode<T>* node = &_nodes[nodeId];
|
||||
|
||||
if (node.IsLeaf())
|
||||
if (_nodes[nodeId].IsLeaf())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int height1 = ComputeHeight(node.Child1);
|
||||
int height2 = ComputeHeight(node.Child2);
|
||||
int height1 = ComputeHeight(_nodes[nodeId].Child1);
|
||||
int height2 = ComputeHeight(_nodes[nodeId].Child2);
|
||||
return 1 + Math.Max(height1, height2);
|
||||
}
|
||||
|
||||
@@ -856,16 +946,16 @@ namespace FarseerPhysics.Collision
|
||||
Debug.Assert(_nodes[index].ParentOrNext == NullNode);
|
||||
}
|
||||
|
||||
TreeNode<T> node = _nodes[index];
|
||||
//TreeNode<T>* node = &_nodes[index];
|
||||
|
||||
int child1 = node.Child1;
|
||||
int child2 = node.Child2;
|
||||
int child1 = _nodes[index].Child1;
|
||||
int child2 = _nodes[index].Child2;
|
||||
|
||||
if (node.IsLeaf())
|
||||
if (_nodes[index].IsLeaf())
|
||||
{
|
||||
Debug.Assert(child1 == NullNode);
|
||||
Debug.Assert(child2 == NullNode);
|
||||
Debug.Assert(node.Height == 0);
|
||||
Debug.Assert(_nodes[index].Height == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -886,16 +976,16 @@ namespace FarseerPhysics.Collision
|
||||
return;
|
||||
}
|
||||
|
||||
TreeNode<T> node = _nodes[index];
|
||||
//TreeNode<T>* node = &_nodes[index];
|
||||
|
||||
int child1 = node.Child1;
|
||||
int child2 = node.Child2;
|
||||
int child1 = _nodes[index].Child1;
|
||||
int child2 = _nodes[index].Child2;
|
||||
|
||||
if (node.IsLeaf())
|
||||
if (_nodes[index].IsLeaf())
|
||||
{
|
||||
Debug.Assert(child1 == NullNode);
|
||||
Debug.Assert(child2 == NullNode);
|
||||
Debug.Assert(node.Height == 0);
|
||||
Debug.Assert(_nodes[index].Height == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -905,13 +995,13 @@ namespace FarseerPhysics.Collision
|
||||
int height1 = _nodes[child1].Height;
|
||||
int height2 = _nodes[child2].Height;
|
||||
int height = 1 + Math.Max(height1, height2);
|
||||
Debug.Assert(node.Height == height);
|
||||
Debug.Assert(_nodes[index].Height == height);
|
||||
|
||||
AABB AABB = new AABB();
|
||||
AABB.Combine(ref _nodes[child1].AABB, ref _nodes[child2].AABB);
|
||||
|
||||
Debug.Assert(AABB.LowerBound == node.AABB.LowerBound);
|
||||
Debug.Assert(AABB.UpperBound == node.AABB.UpperBound);
|
||||
Debug.Assert(AABB.LowerBound == _nodes[index].AABB.LowerBound);
|
||||
Debug.Assert(AABB.UpperBound == _nodes[index].AABB.UpperBound);
|
||||
|
||||
ValidateMetrics(child1);
|
||||
ValidateMetrics(child2);
|
||||
@@ -993,19 +1083,19 @@ namespace FarseerPhysics.Collision
|
||||
|
||||
int index1 = nodes[iMin];
|
||||
int index2 = nodes[jMin];
|
||||
TreeNode<T> child1 = _nodes[index1];
|
||||
TreeNode<T> child2 = _nodes[index2];
|
||||
//TreeNode<T>* child1 = &_nodes[index1];
|
||||
//TreeNode<T>* child2 = &_nodes[index2];
|
||||
|
||||
int parentIndex = AllocateNode();
|
||||
TreeNode<T> parent = _nodes[parentIndex];
|
||||
parent.Child1 = index1;
|
||||
parent.Child2 = index2;
|
||||
parent.Height = 1 + Math.Max(child1.Height, child2.Height);
|
||||
parent.AABB.Combine(ref child1.AABB, ref child2.AABB);
|
||||
parent.ParentOrNext = NullNode;
|
||||
//TreeNode<T>* parent = &_nodes[parentIndex];
|
||||
_nodes[parentIndex].Child1 = index1;
|
||||
_nodes[parentIndex].Child2 = index2;
|
||||
_nodes[parentIndex].Height = 1 + Math.Max(_nodes[index1].Height, _nodes[index2].Height);
|
||||
_nodes[parentIndex].AABB.Combine(ref _nodes[index1].AABB, ref _nodes[index2].AABB);
|
||||
_nodes[parentIndex].ParentOrNext = NullNode;
|
||||
|
||||
child1.ParentOrNext = parentIndex;
|
||||
child2.ParentOrNext = parentIndex;
|
||||
_nodes[index1].ParentOrNext = parentIndex;
|
||||
_nodes[index2].ParentOrNext = parentIndex;
|
||||
|
||||
nodes[jMin] = nodes[count - 1];
|
||||
nodes[iMin] = parentIndex;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/*
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
*
|
||||
@@ -21,6 +26,7 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
@@ -35,17 +41,17 @@ namespace FarseerPhysics.Collision
|
||||
|
||||
public int CompareTo(Pair other)
|
||||
{
|
||||
if (ProxyIdA < other.ProxyIdA)
|
||||
if (ProxyIdB < other.ProxyIdB)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (ProxyIdA == other.ProxyIdA)
|
||||
if (ProxyIdB == other.ProxyIdB)
|
||||
{
|
||||
if (ProxyIdB < other.ProxyIdB)
|
||||
if (ProxyIdA < other.ProxyIdA)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (ProxyIdB == other.ProxyIdB)
|
||||
if (ProxyIdA == other.ProxyIdA)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -109,11 +115,12 @@ namespace FarseerPhysics.Collision
|
||||
/// </summary>
|
||||
/// <param name="proxy">The user data.</param>
|
||||
/// <returns></returns>
|
||||
public int AddProxy(ref FixtureProxy proxy)
|
||||
public int AddProxy(ref AABB aabb)
|
||||
{
|
||||
int proxyId = _tree.AddProxy(ref proxy.AABB, proxy);
|
||||
int proxyId = _tree.AddProxy(ref aabb);
|
||||
++_proxyCount;
|
||||
BufferMove(proxyId);
|
||||
|
||||
return proxyId;
|
||||
}
|
||||
|
||||
@@ -206,6 +213,11 @@ namespace FarseerPhysics.Collision
|
||||
_tree.GetFatAABB(proxyId, out aabb);
|
||||
}
|
||||
|
||||
public void SetProxy(int proxyId, ref FixtureProxy proxy)
|
||||
{
|
||||
_tree.SetUserData(proxyId, proxy, proxy.Body);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get user data from a proxy. Returns null if the id is invalid.
|
||||
/// </summary>
|
||||
@@ -224,12 +236,11 @@ namespace FarseerPhysics.Collision
|
||||
/// <returns></returns>
|
||||
public bool TestOverlap(int proxyIdA, int proxyIdB)
|
||||
{
|
||||
AABB aabbA, aabbB;
|
||||
_tree.GetFatAABB(proxyIdA, out aabbA);
|
||||
_tree.GetFatAABB(proxyIdB, out aabbB);
|
||||
return AABB.TestOverlap(ref aabbA, ref aabbB);
|
||||
return _tree.TestFatAABBOverlap(proxyIdA, proxyIdB);
|
||||
}
|
||||
|
||||
private readonly HashSet<int> processedPairs = new HashSet<int>();
|
||||
|
||||
/// <summary>
|
||||
/// Update the pairs. This results in pair callbacks. This can only add pairs.
|
||||
/// </summary>
|
||||
@@ -250,32 +261,37 @@ namespace FarseerPhysics.Collision
|
||||
|
||||
// We have to query the tree with the fat AABB so that
|
||||
// we don't fail to create a pair that may touch later.
|
||||
AABB fatAABB;
|
||||
_tree.GetFatAABB(_queryProxyId, out fatAABB);
|
||||
AABB fatAABB = _tree.GetFatAABB(_queryProxyId);
|
||||
|
||||
object body = _tree.GetBody(_queryProxyId);
|
||||
|
||||
// Query tree, create pairs and add them pair buffer.
|
||||
_tree.Query(_queryCallback, ref fatAABB);
|
||||
_tree.Query(_queryCallback, ref fatAABB, ref body);
|
||||
}
|
||||
|
||||
// Reset move buffer
|
||||
_moveCount = 0;
|
||||
|
||||
// Sort the pair buffer to expose duplicates.
|
||||
Array.Sort(_pairBuffer, 0, _pairCount);
|
||||
//Array.Sort(_pairBuffer, 0, _pairCount);
|
||||
processedPairs.Clear();
|
||||
|
||||
// Send the pairs back to the client.
|
||||
int i = 0;
|
||||
while (i < _pairCount)
|
||||
{
|
||||
Pair primaryPair = _pairBuffer[i];
|
||||
FixtureProxy userDataA = _tree.GetUserData(primaryPair.ProxyIdA);
|
||||
FixtureProxy userDataB = _tree.GetUserData(primaryPair.ProxyIdB);
|
||||
int pairID = primaryPair.ProxyIdA + (primaryPair.ProxyIdB << 16);
|
||||
if (!processedPairs.Contains(pairID))
|
||||
{
|
||||
callback(primaryPair.ProxyIdA, primaryPair.ProxyIdB);
|
||||
processedPairs.Add(pairID);
|
||||
}
|
||||
|
||||
callback(ref userDataA, ref userDataB);
|
||||
++i;
|
||||
|
||||
// Skip any duplicate pairs.
|
||||
while (i < _pairCount)
|
||||
/*while (i < _pairCount)
|
||||
{
|
||||
Pair pair = _pairBuffer[i];
|
||||
if (pair.ProxyIdA != primaryPair.ProxyIdA || pair.ProxyIdB != primaryPair.ProxyIdB)
|
||||
@@ -283,7 +299,7 @@ namespace FarseerPhysics.Collision
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
// Try to keep the tree balanced.
|
||||
@@ -310,9 +326,10 @@ namespace FarseerPhysics.Collision
|
||||
/// </summary>
|
||||
/// <param name="callback">A callback class that is called for each proxy that is hit by the ray.</param>
|
||||
/// <param name="input">The ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).</param>
|
||||
public void RayCast(Func<RayCastInput, int, float> callback, ref RayCastInput input)
|
||||
/// <param name="collisionCategory">The collision categories of the fixtures to raycast against.</param>
|
||||
public void RayCast(Func<RayCastInput, FixtureProxy, float> callback, ref RayCastInput input, Category collisionCategory = Category.All)
|
||||
{
|
||||
_tree.RayCast(callback, ref input);
|
||||
_tree.RayCast(this, callback, ref input, collisionCategory);
|
||||
}
|
||||
|
||||
public void ShiftOrigin(Vector2 newOrigin)
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
@@ -11,12 +16,14 @@ namespace FarseerPhysics.Collision
|
||||
|
||||
bool TestOverlap(int proxyIdA, int proxyIdB);
|
||||
|
||||
int AddProxy(ref FixtureProxy proxy);
|
||||
int AddProxy(ref AABB aabb);
|
||||
|
||||
void RemoveProxy(int proxyId);
|
||||
|
||||
void MoveProxy(int proxyId, ref AABB aabb, Vector2 displacement);
|
||||
|
||||
void SetProxy(int proxyId, ref FixtureProxy proxy);
|
||||
|
||||
FixtureProxy GetProxy(int proxyId);
|
||||
|
||||
void TouchProxy(int proxyId);
|
||||
@@ -25,7 +32,7 @@ namespace FarseerPhysics.Collision
|
||||
|
||||
void Query(Func<int, bool> callback, ref AABB aabb);
|
||||
|
||||
void RayCast(Func<RayCastInput, int, float> callback, ref RayCastInput input);
|
||||
void RayCast(Func<RayCastInput, FixtureProxy, float> callback, ref RayCastInput input, Category collisionCategory = Category.All);
|
||||
|
||||
void ShiftOrigin(Vector2 newOrigin);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Collision
|
||||
{
|
||||
public class Element<T>
|
||||
{
|
||||
public QuadTree<T> Parent;
|
||||
public AABB Span;
|
||||
public T Value;
|
||||
|
||||
public Element(AABB span)
|
||||
{
|
||||
Span = span;
|
||||
Value = default(T);
|
||||
Parent = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class QuadTree<T>
|
||||
{
|
||||
public int MaxBucket;
|
||||
public int MaxDepth;
|
||||
public List<Element<T>> Nodes;
|
||||
public AABB Span;
|
||||
public QuadTree<T>[] SubTrees;
|
||||
|
||||
public QuadTree(AABB span, int maxbucket, int maxdepth)
|
||||
{
|
||||
Span = span;
|
||||
Nodes = new List<Element<T>>();
|
||||
|
||||
MaxBucket = maxbucket;
|
||||
MaxDepth = maxdepth;
|
||||
}
|
||||
|
||||
public bool IsPartitioned
|
||||
{
|
||||
get { return SubTrees != null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns the quadrant of span that entirely contains test. if none, return 0.
|
||||
/// </summary>
|
||||
/// <param name="span"></param>
|
||||
/// <param name="test"></param>
|
||||
/// <returns></returns>
|
||||
private int Partition(AABB span, AABB test)
|
||||
{
|
||||
if (span.Q1.Contains(ref test)) return 1;
|
||||
if (span.Q2.Contains(ref test)) return 2;
|
||||
if (span.Q3.Contains(ref test)) return 3;
|
||||
if (span.Q4.Contains(ref test)) return 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void AddNode(Element<T> node)
|
||||
{
|
||||
if (!IsPartitioned)
|
||||
{
|
||||
if (Nodes.Count >= MaxBucket && MaxDepth > 0) //bin is full and can still subdivide
|
||||
{
|
||||
//
|
||||
//partition into quadrants and sort existing nodes amonst quads.
|
||||
//
|
||||
Nodes.Add(node); //treat new node just like other nodes for partitioning
|
||||
|
||||
SubTrees = new QuadTree<T>[4];
|
||||
SubTrees[0] = new QuadTree<T>(Span.Q1, MaxBucket, MaxDepth - 1);
|
||||
SubTrees[1] = new QuadTree<T>(Span.Q2, MaxBucket, MaxDepth - 1);
|
||||
SubTrees[2] = new QuadTree<T>(Span.Q3, MaxBucket, MaxDepth - 1);
|
||||
SubTrees[3] = new QuadTree<T>(Span.Q4, MaxBucket, MaxDepth - 1);
|
||||
|
||||
List<Element<T>> remNodes = new List<Element<T>>();
|
||||
//nodes that are not fully contained by any quadrant
|
||||
|
||||
foreach (Element<T> n in Nodes)
|
||||
{
|
||||
switch (Partition(Span, n.Span))
|
||||
{
|
||||
case 1: //quadrant 1
|
||||
SubTrees[0].AddNode(n);
|
||||
break;
|
||||
case 2:
|
||||
SubTrees[1].AddNode(n);
|
||||
break;
|
||||
case 3:
|
||||
SubTrees[2].AddNode(n);
|
||||
break;
|
||||
case 4:
|
||||
SubTrees[3].AddNode(n);
|
||||
break;
|
||||
default:
|
||||
n.Parent = this;
|
||||
remNodes.Add(n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Nodes = remNodes;
|
||||
}
|
||||
else
|
||||
{
|
||||
node.Parent = this;
|
||||
Nodes.Add(node);
|
||||
//if bin is not yet full or max depth has been reached, just add the node without subdividing
|
||||
}
|
||||
}
|
||||
else //we already have children nodes
|
||||
{
|
||||
//
|
||||
//add node to specific sub-tree
|
||||
//
|
||||
switch (Partition(Span, node.Span))
|
||||
{
|
||||
case 1: //quadrant 1
|
||||
SubTrees[0].AddNode(node);
|
||||
break;
|
||||
case 2:
|
||||
SubTrees[1].AddNode(node);
|
||||
break;
|
||||
case 3:
|
||||
SubTrees[2].AddNode(node);
|
||||
break;
|
||||
case 4:
|
||||
SubTrees[3].AddNode(node);
|
||||
break;
|
||||
default:
|
||||
node.Parent = this;
|
||||
Nodes.Add(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// tests if ray intersects AABB
|
||||
/// </summary>
|
||||
/// <param name="aabb"></param>
|
||||
/// <returns></returns>
|
||||
public static bool RayCastAABB(AABB aabb, Vector2 p1, Vector2 p2)
|
||||
{
|
||||
AABB segmentAABB = new AABB();
|
||||
{
|
||||
Vector2.Min(ref p1, ref p2, out segmentAABB.LowerBound);
|
||||
Vector2.Max(ref p1, ref p2, out segmentAABB.UpperBound);
|
||||
}
|
||||
if (!AABB.TestOverlap(ref aabb, ref segmentAABB)) return false;
|
||||
|
||||
Vector2 rayDir = p2 - p1;
|
||||
Vector2 rayPos = p1;
|
||||
|
||||
Vector2 norm = new Vector2(-rayDir.Y, rayDir.X); //normal to ray
|
||||
if (norm.Length() == 0.0f)
|
||||
return true; //if ray is just a point, return true (iff point is within aabb, as tested earlier)
|
||||
norm.Normalize();
|
||||
|
||||
float dPos = Vector2.Dot(rayPos, norm);
|
||||
|
||||
var verts = aabb.Vertices;
|
||||
float d0 = Vector2.Dot(verts[0], norm) - dPos;
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
float d = Vector2.Dot(verts[i], norm) - dPos;
|
||||
if (Math.Sign(d) != Math.Sign(d0))
|
||||
//return true if the ray splits the vertices (ie: sign of dot products with normal are not all same)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void QueryAABB(Func<Element<T>, bool> callback, ref AABB searchR)
|
||||
{
|
||||
Stack<QuadTree<T>> stack = new Stack<QuadTree<T>>();
|
||||
stack.Push(this);
|
||||
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
QuadTree<T> qt = stack.Pop();
|
||||
if (!AABB.TestOverlap(ref searchR, ref qt.Span))
|
||||
continue;
|
||||
|
||||
foreach (Element<T> n in qt.Nodes)
|
||||
if (AABB.TestOverlap(ref searchR, ref n.Span))
|
||||
{
|
||||
if (!callback(n)) return;
|
||||
}
|
||||
|
||||
if (qt.IsPartitioned)
|
||||
foreach (QuadTree<T> st in qt.SubTrees)
|
||||
stack.Push(st);
|
||||
}
|
||||
}
|
||||
|
||||
public void RayCast(Func<RayCastInput, Element<T>, float> callback, ref RayCastInput input, Category collisionCategory = Category.All)
|
||||
{
|
||||
Stack<QuadTree<T>> stack = new Stack<QuadTree<T>>();
|
||||
stack.Push(this);
|
||||
|
||||
float maxFraction = input.MaxFraction;
|
||||
Vector2 p1 = input.Point1;
|
||||
Vector2 p2 = p1 + (input.Point2 - input.Point1) * maxFraction;
|
||||
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
QuadTree<T> qt = stack.Pop();
|
||||
|
||||
if (!RayCastAABB(qt.Span, p1, p2))
|
||||
continue;
|
||||
|
||||
foreach (Element<T> n in qt.Nodes)
|
||||
{
|
||||
if (!RayCastAABB(n.Span, p1, p2))
|
||||
continue;
|
||||
|
||||
RayCastInput subInput;
|
||||
subInput.Point1 = input.Point1;
|
||||
subInput.Point2 = input.Point2;
|
||||
subInput.MaxFraction = maxFraction;
|
||||
|
||||
float value = callback(subInput, n);
|
||||
if (value == 0.0f)
|
||||
return; // the client has terminated the raycast.
|
||||
|
||||
if (value <= 0.0f)
|
||||
continue;
|
||||
|
||||
maxFraction = value;
|
||||
p2 = p1 + (input.Point2 - input.Point1) * maxFraction; //update segment endpoint
|
||||
}
|
||||
if (qt.IsPartitioned)
|
||||
foreach (QuadTree<T> st in qt.SubTrees)
|
||||
stack.Push(st);
|
||||
}
|
||||
}
|
||||
|
||||
public void GetAllNodesR(ref List<Element<T>> nodes)
|
||||
{
|
||||
nodes.AddRange(Nodes);
|
||||
|
||||
if (IsPartitioned)
|
||||
foreach (QuadTree<T> st in SubTrees) st.GetAllNodesR(ref nodes);
|
||||
}
|
||||
|
||||
public void RemoveNode(Element<T> node)
|
||||
{
|
||||
node.Parent.Nodes.Remove(node);
|
||||
}
|
||||
|
||||
public void Reconstruct()
|
||||
{
|
||||
List<Element<T>> allNodes = new List<Element<T>>();
|
||||
GetAllNodesR(ref allNodes);
|
||||
|
||||
Clear();
|
||||
|
||||
foreach (var node in allNodes)
|
||||
AddNode(node);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Nodes.Clear();
|
||||
SubTrees = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using FarseerPhysics.Dynamics;
|
||||
|
||||
namespace FarseerPhysics.Collision
|
||||
{
|
||||
public class QuadTreeBroadPhase : IBroadPhase
|
||||
{
|
||||
private const int TreeUpdateThresh = 10000;
|
||||
private int _currId;
|
||||
private Dictionary<int, Element<FixtureProxy>> _idRegister;
|
||||
private List<Element<FixtureProxy>> _moveBuffer;
|
||||
private List<Pair> _pairBuffer;
|
||||
private QuadTree<FixtureProxy> _quadTree;
|
||||
private int _treeMoveNum;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new quad tree broadphase with the specified span.
|
||||
/// </summary>
|
||||
/// <param name="span">the maximum span of the tree (world size)</param>
|
||||
public QuadTreeBroadPhase(AABB span)
|
||||
{
|
||||
_quadTree = new QuadTree<FixtureProxy>(span, 5, 10);
|
||||
_idRegister = new Dictionary<int, Element<FixtureProxy>>();
|
||||
_moveBuffer = new List<Element<FixtureProxy>>();
|
||||
_pairBuffer = new List<Pair>();
|
||||
}
|
||||
|
||||
#region IBroadPhase Members
|
||||
|
||||
///<summary>
|
||||
/// The number of proxies
|
||||
///</summary>
|
||||
public int ProxyCount
|
||||
{
|
||||
get { return _idRegister.Count; }
|
||||
}
|
||||
|
||||
public void GetFatAABB(int proxyID, out AABB aabb)
|
||||
{
|
||||
if (_idRegister.ContainsKey(proxyID))
|
||||
aabb = _idRegister[proxyID].Span;
|
||||
else
|
||||
throw new KeyNotFoundException("proxyID not found in register");
|
||||
}
|
||||
|
||||
public void UpdatePairs(BroadphaseDelegate callback)
|
||||
{
|
||||
_pairBuffer.Clear();
|
||||
foreach (Element<FixtureProxy> qtnode in _moveBuffer)
|
||||
{
|
||||
// Query tree, create pairs and add them pair buffer.
|
||||
Query(proxyID => PairBufferQueryCallback(proxyID, qtnode.Value.ProxyId), ref qtnode.Span);
|
||||
}
|
||||
_moveBuffer.Clear();
|
||||
|
||||
// Sort the pair buffer to expose duplicates.
|
||||
_pairBuffer.Sort();
|
||||
|
||||
// Send the pairs back to the client.
|
||||
int i = 0;
|
||||
while (i < _pairBuffer.Count)
|
||||
{
|
||||
Pair primaryPair = _pairBuffer[i];
|
||||
|
||||
callback(primaryPair.ProxyIdA, primaryPair.ProxyIdB);
|
||||
++i;
|
||||
|
||||
// Skip any duplicate pairs.
|
||||
while (i < _pairBuffer.Count && _pairBuffer[i].ProxyIdA == primaryPair.ProxyIdA &&
|
||||
_pairBuffer[i].ProxyIdB == primaryPair.ProxyIdB)
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test overlap of fat AABBs.
|
||||
/// </summary>
|
||||
/// <param name="proxyIdA">The proxy id A.</param>
|
||||
/// <param name="proxyIdB">The proxy id B.</param>
|
||||
/// <returns></returns>
|
||||
public bool TestOverlap(int proxyIdA, int proxyIdB)
|
||||
{
|
||||
AABB aabb1;
|
||||
AABB aabb2;
|
||||
GetFatAABB(proxyIdA, out aabb1);
|
||||
GetFatAABB(proxyIdB, out aabb2);
|
||||
return AABB.TestOverlap(ref aabb1, ref aabb2);
|
||||
}
|
||||
|
||||
public int AddProxy(ref AABB uaabb)
|
||||
{
|
||||
int proxyId = _currId++;
|
||||
AABB aabb = Fatten(ref uaabb);
|
||||
Element<FixtureProxy> qtnode = new Element<FixtureProxy>(aabb);
|
||||
|
||||
_idRegister.Add(proxyId, qtnode);
|
||||
_quadTree.AddNode(qtnode);
|
||||
|
||||
return proxyId;
|
||||
}
|
||||
|
||||
public void RemoveProxy(int proxyId)
|
||||
{
|
||||
if (_idRegister.ContainsKey(proxyId))
|
||||
{
|
||||
Element<FixtureProxy> qtnode = _idRegister[proxyId];
|
||||
UnbufferMove(qtnode);
|
||||
_idRegister.Remove(proxyId);
|
||||
_quadTree.RemoveNode(qtnode);
|
||||
}
|
||||
else
|
||||
throw new KeyNotFoundException("proxyID not found in register");
|
||||
}
|
||||
|
||||
public void MoveProxy(int proxyId, ref AABB aabb, Vector2 displacement)
|
||||
{
|
||||
AABB fatAABB;
|
||||
GetFatAABB(proxyId, out fatAABB);
|
||||
|
||||
//exit if movement is within fat aabb
|
||||
if (fatAABB.Contains(ref aabb))
|
||||
return;
|
||||
|
||||
// Extend AABB.
|
||||
AABB b = aabb;
|
||||
Vector2 r = new Vector2(Settings.AABBExtension, Settings.AABBExtension);
|
||||
b.LowerBound = b.LowerBound - r;
|
||||
b.UpperBound = b.UpperBound + r;
|
||||
|
||||
// Predict AABB displacement.
|
||||
Vector2 d = Settings.AABBMultiplier * displacement;
|
||||
|
||||
if (d.X < 0.0f)
|
||||
b.LowerBound.X += d.X;
|
||||
else
|
||||
b.UpperBound.X += d.X;
|
||||
|
||||
if (d.Y < 0.0f)
|
||||
b.LowerBound.Y += d.Y;
|
||||
else
|
||||
b.UpperBound.Y += d.Y;
|
||||
|
||||
|
||||
Element<FixtureProxy> qtnode = _idRegister[proxyId];
|
||||
qtnode.Value.AABB = b; //not neccesary for QTree, but might be accessed externally
|
||||
qtnode.Span = b;
|
||||
|
||||
ReinsertNode(qtnode);
|
||||
|
||||
BufferMove(qtnode);
|
||||
}
|
||||
|
||||
public void SetProxy(int proxyId, ref FixtureProxy proxy)
|
||||
{
|
||||
_idRegister[proxyId].Value = proxy;
|
||||
}
|
||||
|
||||
public FixtureProxy GetProxy(int proxyId)
|
||||
{
|
||||
if (_idRegister.ContainsKey(proxyId))
|
||||
return _idRegister[proxyId].Value;
|
||||
|
||||
throw new KeyNotFoundException("proxyID not found in register");
|
||||
}
|
||||
|
||||
public void TouchProxy(int proxyId)
|
||||
{
|
||||
if (_idRegister.ContainsKey(proxyId))
|
||||
BufferMove(_idRegister[proxyId]);
|
||||
else
|
||||
throw new KeyNotFoundException("proxyID not found in register");
|
||||
}
|
||||
|
||||
public void Query(Func<int, bool> callback, ref AABB query)
|
||||
{
|
||||
_quadTree.QueryAABB(TransformPredicate(callback), ref query);
|
||||
}
|
||||
|
||||
public void RayCast(Func<RayCastInput, FixtureProxy, float> callback, ref RayCastInput input, Category collisionCategory = Category.All)
|
||||
{
|
||||
_quadTree.RayCast(TransformRayCallback(callback), ref input, collisionCategory);
|
||||
}
|
||||
|
||||
public void ShiftOrigin(Vector2 newOrigin)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private AABB Fatten(ref AABB aabb)
|
||||
{
|
||||
Vector2 r = new Vector2(Settings.AABBExtension, Settings.AABBExtension);
|
||||
return new AABB(aabb.LowerBound - r, aabb.UpperBound + r);
|
||||
}
|
||||
|
||||
private Func<Element<FixtureProxy>, bool> TransformPredicate(Func<int, bool> idPredicate)
|
||||
{
|
||||
Func<Element<FixtureProxy>, bool> qtPred = qtnode => idPredicate(qtnode.Value.ProxyId);
|
||||
return qtPred;
|
||||
}
|
||||
|
||||
private Func<RayCastInput, Element<FixtureProxy>, float> TransformRayCallback(Func<RayCastInput, FixtureProxy, float> callback)
|
||||
{
|
||||
Func<RayCastInput, Element<FixtureProxy>, float> newCallback =
|
||||
(input, qtnode) => callback(input, qtnode.Value);
|
||||
return newCallback;
|
||||
}
|
||||
|
||||
private bool PairBufferQueryCallback(int proxyId, int baseId)
|
||||
{
|
||||
// A proxy cannot form a pair with itself.
|
||||
if (proxyId == baseId)
|
||||
return true;
|
||||
|
||||
Pair p = new Pair();
|
||||
p.ProxyIdA = Math.Min(proxyId, baseId);
|
||||
p.ProxyIdB = Math.Max(proxyId, baseId);
|
||||
_pairBuffer.Add(p);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ReconstructTree()
|
||||
{
|
||||
//this is faster than _quadTree.Reconstruct(), since the quadtree method runs a recusive query to find all nodes.
|
||||
_quadTree.Clear();
|
||||
foreach (Element<FixtureProxy> elem in _idRegister.Values)
|
||||
_quadTree.AddNode(elem);
|
||||
}
|
||||
|
||||
private void ReinsertNode(Element<FixtureProxy> qtnode)
|
||||
{
|
||||
_quadTree.RemoveNode(qtnode);
|
||||
_quadTree.AddNode(qtnode);
|
||||
|
||||
if (++_treeMoveNum > TreeUpdateThresh)
|
||||
{
|
||||
ReconstructTree();
|
||||
_treeMoveNum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void BufferMove(Element<FixtureProxy> proxy)
|
||||
{
|
||||
_moveBuffer.Add(proxy);
|
||||
}
|
||||
|
||||
private void UnbufferMove(Element<FixtureProxy> proxy)
|
||||
{
|
||||
_moveBuffer.Remove(proxy);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,8 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
@@ -63,8 +68,8 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
{
|
||||
ShapeType = ShapeType.Chain;
|
||||
_radius = Settings.PolygonRadius;
|
||||
|
||||
Debug.Assert(vertices != null && vertices.Count >= 2);
|
||||
|
||||
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)
|
||||
@@ -73,7 +78,6 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -208,11 +212,11 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
i2 = 0;
|
||||
}
|
||||
|
||||
Vector2 v1 = MathUtils.Mul(ref transform, Vertices[i1]);
|
||||
Vector2 v2 = MathUtils.Mul(ref transform, Vertices[i2]);
|
||||
Vector2 v1 = Transform.Multiply(Vertices[i1], ref transform);
|
||||
Vector2 v2 = Transform.Multiply(Vertices[i2], ref transform);
|
||||
|
||||
aabb.LowerBound = Vector2.Min(v1, v2);
|
||||
aabb.UpperBound = Vector2.Max(v1, v2);
|
||||
Vector2.Min(ref v1, ref v2, out aabb.LowerBound);
|
||||
Vector2.Max(ref v1, ref v2, out aabb.UpperBound);
|
||||
}
|
||||
|
||||
protected override void ComputeProperties()
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/*
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
*
|
||||
@@ -23,6 +28,7 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using FarseerPhysics.Common;
|
||||
using FarseerPhysics.Common.Maths;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Collision.Shapes
|
||||
@@ -78,7 +84,7 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
|
||||
public override bool TestPoint(ref Transform transform, ref Vector2 point)
|
||||
{
|
||||
Vector2 center = transform.p + MathUtils.Mul(transform.q, Position);
|
||||
Vector2 center = transform.p + Complex.Multiply(ref _position, ref transform.q);
|
||||
Vector2 d = point - center;
|
||||
return Vector2.Dot(d, d) <= _2radius;
|
||||
}
|
||||
@@ -92,7 +98,7 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
|
||||
output = new RayCastOutput();
|
||||
|
||||
Vector2 position = transform.p + MathUtils.Mul(transform.q, Position);
|
||||
Vector2 position = transform.p + Complex.Multiply(ref _position, ref transform.q);
|
||||
Vector2 s = input.Point1 - position;
|
||||
float b = Vector2.Dot(s, s) - _2radius;
|
||||
|
||||
@@ -128,14 +134,21 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
|
||||
public override void ComputeAABB(out AABB aabb, ref Transform transform, int childIndex)
|
||||
{
|
||||
Vector2 p = transform.p + MathUtils.Mul(transform.q, Position);
|
||||
aabb.LowerBound = new Vector2(p.X - Radius, p.Y - Radius);
|
||||
aabb.UpperBound = new Vector2(p.X + Radius, p.Y + Radius);
|
||||
// OPT: Vector2 p = transform.p + Complex.Multiply(ref _position, ref transform.q);
|
||||
var pX = (_position.X * transform.q.Real - _position.Y * transform.q.Imaginary) + transform.p.X;
|
||||
var pY = (_position.Y * transform.q.Real + _position.X * transform.q.Imaginary) + transform.p.Y;
|
||||
|
||||
// OPT: aabb.LowerBound = new Vector2(p.X - Radius, p.Y - Radius);
|
||||
// OPT: aabb.UpperBound = new Vector2(p.X + Radius, p.Y + Radius);
|
||||
aabb.LowerBound.X = pX - Radius;
|
||||
aabb.LowerBound.Y = pY - Radius;
|
||||
aabb.UpperBound.X = pX + Radius;
|
||||
aabb.UpperBound.Y = pY + Radius;
|
||||
}
|
||||
|
||||
protected override sealed void ComputeProperties()
|
||||
{
|
||||
float area = Settings.Pi * _2radius;
|
||||
float area = MathHelper.Pi * _2radius;
|
||||
MassData.Area = area;
|
||||
MassData.Mass = Density * area;
|
||||
MassData.Centroid = Position;
|
||||
@@ -148,7 +161,7 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
{
|
||||
sc = Vector2.Zero;
|
||||
|
||||
Vector2 p = MathUtils.Mul(ref xf, Position);
|
||||
Vector2 p = Transform.Multiply(ref _position, ref xf);
|
||||
float l = -(Vector2.Dot(normal, p) - offset);
|
||||
if (l < -Radius + Settings.Epsilon)
|
||||
{
|
||||
@@ -159,12 +172,12 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
{
|
||||
//Completely wet
|
||||
sc = p;
|
||||
return Settings.Pi * _2radius;
|
||||
return MathHelper.Pi * _2radius;
|
||||
}
|
||||
|
||||
//Magic
|
||||
float l2 = l * l;
|
||||
float area = _2radius * (float)((Math.Asin(l / Radius) + Settings.Pi / 2) + l * Math.Sqrt(_2radius - l2));
|
||||
float area = _2radius * (float)((Math.Asin(l / Radius) + MathHelper.Pi / 2) + l * Math.Sqrt(_2radius - l2));
|
||||
float com = -2.0f / 3.0f * (float)Math.Pow(_2radius - l2, 1.5f) / area;
|
||||
|
||||
sc.X = p.X + normal.X * com;
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
@@ -21,6 +26,7 @@
|
||||
*/
|
||||
|
||||
using FarseerPhysics.Common;
|
||||
using FarseerPhysics.Common.Maths;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Collision.Shapes
|
||||
@@ -143,8 +149,8 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
output = new RayCastOutput();
|
||||
|
||||
// Put the ray into the edge's frame of reference.
|
||||
Vector2 p1 = MathUtils.MulT(transform.q, input.Point1 - transform.p);
|
||||
Vector2 p2 = MathUtils.MulT(transform.q, input.Point2 - transform.p);
|
||||
Vector2 p1 = Complex.Divide(input.Point1 - transform.p, ref transform.q);
|
||||
Vector2 p2 = Complex.Divide(input.Point2 - transform.p, ref transform.q);
|
||||
Vector2 d = p2 - p1;
|
||||
|
||||
Vector2 v1 = _vertex1;
|
||||
@@ -201,15 +207,43 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
|
||||
public override void ComputeAABB(out AABB aabb, ref Transform transform, int childIndex)
|
||||
{
|
||||
Vector2 v1 = MathUtils.Mul(ref transform, _vertex1);
|
||||
Vector2 v2 = MathUtils.Mul(ref transform, _vertex2);
|
||||
// OPT: Vector2 v1 = Transform.Multiply(ref _vertex1, ref transform);
|
||||
float v1X = (_vertex1.X * transform.q.Real - _vertex1.Y * transform.q.Imaginary) + transform.p.X;
|
||||
float v1Y = (_vertex1.Y * transform.q.Real + _vertex1.X * transform.q.Imaginary) + transform.p.Y;
|
||||
// OPT: Vector2 v2 = Transform.Multiply(ref _vertex2, ref transform);
|
||||
float v2X = (_vertex2.X * transform.q.Real - _vertex2.Y * transform.q.Imaginary) + transform.p.X;
|
||||
float v2Y = (_vertex2.Y * transform.q.Real + _vertex2.X * transform.q.Imaginary) + transform.p.Y;
|
||||
|
||||
Vector2 lower = Vector2.Min(v1, v2);
|
||||
Vector2 upper = Vector2.Max(v1, v2);
|
||||
// OPT: aabb.LowerBound = Vector2.Min(v1, v2);
|
||||
// OPT: aabb.UpperBound = Vector2.Max(v1, v2);
|
||||
if (v1X < v2X)
|
||||
{
|
||||
aabb.LowerBound.X = v1X;
|
||||
aabb.UpperBound.X = v2X;
|
||||
}
|
||||
else
|
||||
{
|
||||
aabb.LowerBound.X = v2X;
|
||||
aabb.UpperBound.X = v1X;
|
||||
}
|
||||
if (v1Y < v2Y)
|
||||
{
|
||||
aabb.LowerBound.Y = v1Y;
|
||||
aabb.UpperBound.Y = v2Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
aabb.LowerBound.Y = v2Y;
|
||||
aabb.UpperBound.Y = v1Y;
|
||||
}
|
||||
|
||||
Vector2 r = new Vector2(Radius, Radius);
|
||||
aabb.LowerBound = lower - r;
|
||||
aabb.UpperBound = upper + r;
|
||||
// OPT: Vector2 r = new Vector2(Radius, Radius);
|
||||
// OPT: aabb.LowerBound = aabb.LowerBound - r;
|
||||
// OPT: aabb.UpperBound = aabb.LowerBound + r;
|
||||
aabb.LowerBound.X -= Radius;
|
||||
aabb.LowerBound.Y -= Radius;
|
||||
aabb.UpperBound.X += Radius;
|
||||
aabb.UpperBound.Y += Radius;
|
||||
}
|
||||
|
||||
protected override void ComputeProperties()
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
@@ -23,6 +28,7 @@
|
||||
using System.Diagnostics;
|
||||
using FarseerPhysics.Common;
|
||||
using FarseerPhysics.Common.ConvexHull;
|
||||
using FarseerPhysics.Common.Maths;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Collision.Shapes
|
||||
@@ -87,7 +93,7 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
{
|
||||
_vertices = new Vertices(value);
|
||||
|
||||
//Debug.Assert(_vertices.Count >= 3 && _vertices.Count <= Settings.MaxPolygonVertices);
|
||||
Debug.Assert(_vertices.Count >= 3 && _vertices.Count <= Settings.MaxPolygonVertices);
|
||||
|
||||
if (Settings.UseConvexHullPolygons)
|
||||
{
|
||||
@@ -179,7 +185,7 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
Vector2 e1 = Vertices[i] - s;
|
||||
Vector2 e2 = i + 1 < Vertices.Count ? Vertices[i + 1] - s : Vertices[0] - s;
|
||||
|
||||
float D = MathUtils.Cross(e1, e2);
|
||||
float D = MathUtils.Cross(ref e1, ref e2);
|
||||
|
||||
float triangleArea = 0.5f * D;
|
||||
area += triangleArea;
|
||||
@@ -218,7 +224,7 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
|
||||
public override bool TestPoint(ref Transform transform, ref Vector2 point)
|
||||
{
|
||||
Vector2 pLocal = MathUtils.MulT(transform.q, point - transform.p);
|
||||
Vector2 pLocal = Complex.Divide(point - transform.p, ref transform.q);
|
||||
|
||||
for (int i = 0; i < Vertices.Count; ++i)
|
||||
{
|
||||
@@ -237,8 +243,8 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
output = new RayCastOutput();
|
||||
|
||||
// Put the ray into the polygon's frame of reference.
|
||||
Vector2 p1 = MathUtils.MulT(transform.q, input.Point1 - transform.p);
|
||||
Vector2 p2 = MathUtils.MulT(transform.q, input.Point2 - transform.p);
|
||||
Vector2 p1 = Complex.Divide(input.Point1 - transform.p, ref transform.q);
|
||||
Vector2 p2 = Complex.Divide(input.Point2 - transform.p, ref transform.q);
|
||||
Vector2 d = p2 - p1;
|
||||
|
||||
float lower = 0.0f, upper = input.MaxFraction;
|
||||
@@ -296,7 +302,7 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
if (index >= 0)
|
||||
{
|
||||
output.Fraction = lower;
|
||||
output.Normal = MathUtils.Mul(transform.q, Normals[index]);
|
||||
output.Normal = Complex.Multiply(Normals[index], ref transform.q);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -311,19 +317,36 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
/// <param name="childIndex">The child shape index.</param>
|
||||
public override void ComputeAABB(out AABB aabb, ref Transform transform, int childIndex)
|
||||
{
|
||||
Vector2 lower = MathUtils.Mul(ref transform, Vertices[0]);
|
||||
Vector2 upper = lower;
|
||||
// OPT: aabb.LowerBound = Transform.Multiply(Vertices[0], ref transform);
|
||||
var vert = Vertices[0];
|
||||
aabb.LowerBound.X = (vert.X * transform.q.Real - vert.Y * transform.q.Imaginary) + transform.p.X;
|
||||
aabb.LowerBound.Y = (vert.Y * transform.q.Real + vert.X * transform.q.Imaginary) + transform.p.Y;
|
||||
aabb.UpperBound = aabb.LowerBound;
|
||||
|
||||
for (int i = 1; i < Vertices.Count; ++i)
|
||||
{
|
||||
Vector2 v = MathUtils.Mul(ref transform, Vertices[i]);
|
||||
lower = Vector2.Min(lower, v);
|
||||
upper = Vector2.Max(upper, v);
|
||||
// OPT: Vector2 v = Transform.Multiply(Vertices[i], ref transform);
|
||||
vert = Vertices[i];
|
||||
float vX = (vert.X * transform.q.Real - vert.Y * transform.q.Imaginary) + transform.p.X;
|
||||
float vY = (vert.Y * transform.q.Real + vert.X * transform.q.Imaginary) + transform.p.Y;
|
||||
|
||||
// OPT: Vector2.Min(ref aabb.LowerBound, ref v, out aabb.LowerBound);
|
||||
// OPT: Vector2.Max(ref aabb.UpperBound, ref v, out aabb.UpperBound);
|
||||
Debug.Assert(aabb.LowerBound.X <= aabb.UpperBound.X);
|
||||
if (vX < aabb.LowerBound.X) aabb.LowerBound.X = vX;
|
||||
else if (vX > aabb.UpperBound.X) aabb.UpperBound.X = vX;
|
||||
Debug.Assert(aabb.LowerBound.Y <= aabb.UpperBound.Y);
|
||||
if (vY < aabb.LowerBound.Y) aabb.LowerBound.Y = vY;
|
||||
else if (vY > aabb.UpperBound.Y) aabb.UpperBound.Y = vY;
|
||||
}
|
||||
|
||||
Vector2 r = new Vector2(Radius, Radius);
|
||||
aabb.LowerBound = lower - r;
|
||||
aabb.UpperBound = upper + r;
|
||||
// OPT: Vector2 r = new Vector2(Radius, Radius);
|
||||
// OPT: aabb.LowerBound = aabb.LowerBound - r;
|
||||
// OPT: aabb.UpperBound = aabb.UpperBound + r;
|
||||
aabb.LowerBound.X -= Radius;
|
||||
aabb.LowerBound.Y -= Radius;
|
||||
aabb.UpperBound.X += Radius;
|
||||
aabb.UpperBound.Y += Radius;
|
||||
}
|
||||
|
||||
public override float ComputeSubmergedArea(ref Vector2 normal, float offset, ref Transform xf, out Vector2 sc)
|
||||
@@ -331,7 +354,7 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
sc = Vector2.Zero;
|
||||
|
||||
//Transform plane into shape co-ordinates
|
||||
Vector2 normalL = MathUtils.MulT(xf.q, normal);
|
||||
Vector2 normalL = Complex.Divide(ref normal, ref xf.q);
|
||||
float offsetL = offset - Vector2.Dot(normal, xf.p);
|
||||
|
||||
float[] depths = new float[Settings.MaxPolygonVertices];
|
||||
@@ -372,7 +395,7 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
if (lastSubmerged)
|
||||
{
|
||||
//Completely submerged
|
||||
sc = MathUtils.Mul(ref xf, MassData.Centroid);
|
||||
sc = Transform.Multiply(MassData.Centroid, ref xf);
|
||||
return MassData.Mass / Density;
|
||||
}
|
||||
|
||||
@@ -421,7 +444,7 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
Vector2 e1 = p2 - intoVec;
|
||||
Vector2 e2 = p3 - intoVec;
|
||||
|
||||
float D = MathUtils.Cross(e1, e2);
|
||||
float D = MathUtils.Cross(ref e1, ref e2);
|
||||
|
||||
float triangleArea = 0.5f * D;
|
||||
|
||||
@@ -437,7 +460,7 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
//Normalize and transform centroid
|
||||
center *= 1.0f / area;
|
||||
|
||||
sc = MathUtils.Mul(ref xf, center);
|
||||
sc = Transform.Multiply(ref center, ref xf);
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/*
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
*
|
||||
@@ -225,28 +230,6 @@ namespace FarseerPhysics.Collision.Shapes
|
||||
/// </summary>
|
||||
protected abstract void ComputeProperties();
|
||||
|
||||
/// <summary>
|
||||
/// Compare this shape to another shape based on type and properties.
|
||||
/// </summary>
|
||||
/// <param name="shape">The other shape</param>
|
||||
/// <returns>True if the two shapes are the same.</returns>
|
||||
public bool CompareTo(Shape shape)
|
||||
{
|
||||
if (shape is PolygonShape && this is PolygonShape)
|
||||
return ((PolygonShape)this).CompareTo((PolygonShape)shape);
|
||||
|
||||
if (shape is CircleShape && this is CircleShape)
|
||||
return ((CircleShape)this).CompareTo((CircleShape)shape);
|
||||
|
||||
if (shape is EdgeShape && this is EdgeShape)
|
||||
return ((EdgeShape)this).CompareTo((EdgeShape)shape);
|
||||
|
||||
if (shape is ChainShape && this is ChainShape)
|
||||
return ((ChainShape)this).CompareTo((ChainShape)shape);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used for the buoyancy controller
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/*
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
*
|
||||
@@ -23,6 +28,7 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using FarseerPhysics.Common;
|
||||
using FarseerPhysics.Common.Maths;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Collision
|
||||
@@ -32,8 +38,8 @@ namespace FarseerPhysics.Collision
|
||||
/// </summary>
|
||||
public class TOIInput
|
||||
{
|
||||
public DistanceProxy ProxyA = new DistanceProxy();
|
||||
public DistanceProxy ProxyB = new DistanceProxy();
|
||||
public DistanceProxy ProxyA;
|
||||
public DistanceProxy ProxyB;
|
||||
public Sweep SweepA;
|
||||
public Sweep SweepB;
|
||||
public float TMax; // defines sweep interval [0, tMax]
|
||||
@@ -76,7 +82,7 @@ namespace FarseerPhysics.Collision
|
||||
[ThreadStatic]
|
||||
private static SeparationFunctionType _type;
|
||||
|
||||
public static void Set(ref SimplexCache cache, DistanceProxy proxyA, ref Sweep sweepA, DistanceProxy proxyB, ref Sweep sweepB, float t1)
|
||||
public static void Set(ref SimplexCache cache, ref DistanceProxy proxyA, ref Sweep sweepA, ref DistanceProxy proxyB, ref Sweep sweepB, float t1)
|
||||
{
|
||||
_localPoint = Vector2.Zero;
|
||||
_proxyA = proxyA;
|
||||
@@ -96,8 +102,8 @@ namespace FarseerPhysics.Collision
|
||||
_type = SeparationFunctionType.Points;
|
||||
Vector2 localPointA = _proxyA.Vertices[cache.IndexA[0]];
|
||||
Vector2 localPointB = _proxyB.Vertices[cache.IndexB[0]];
|
||||
Vector2 pointA = MathUtils.Mul(ref xfA, localPointA);
|
||||
Vector2 pointB = MathUtils.Mul(ref xfB, localPointB);
|
||||
Vector2 pointA = Transform.Multiply(ref localPointA, ref xfA);
|
||||
Vector2 pointB = Transform.Multiply(ref localPointB, ref xfB);
|
||||
_axis = pointB - pointA;
|
||||
_axis.Normalize();
|
||||
}
|
||||
@@ -111,13 +117,13 @@ namespace FarseerPhysics.Collision
|
||||
Vector2 a = localPointB2 - localPointB1;
|
||||
_axis = new Vector2(a.Y, -a.X);
|
||||
_axis.Normalize();
|
||||
Vector2 normal = MathUtils.Mul(ref xfB.q, _axis);
|
||||
Vector2 normal = Complex.Multiply(ref _axis, ref xfB.q);
|
||||
|
||||
_localPoint = 0.5f * (localPointB1 + localPointB2);
|
||||
Vector2 pointB = MathUtils.Mul(ref xfB, _localPoint);
|
||||
Vector2 pointB = Transform.Multiply(ref _localPoint, ref xfB);
|
||||
|
||||
Vector2 localPointA = proxyA.Vertices[cache.IndexA[0]];
|
||||
Vector2 pointA = MathUtils.Mul(ref xfA, localPointA);
|
||||
Vector2 pointA = Transform.Multiply(ref localPointA, ref xfA);
|
||||
|
||||
float s = Vector2.Dot(pointA - pointB, normal);
|
||||
if (s < 0.0f)
|
||||
@@ -135,13 +141,13 @@ namespace FarseerPhysics.Collision
|
||||
Vector2 a = localPointA2 - localPointA1;
|
||||
_axis = new Vector2(a.Y, -a.X);
|
||||
_axis.Normalize();
|
||||
Vector2 normal = MathUtils.Mul(ref xfA.q, _axis);
|
||||
Vector2 normal = Complex.Multiply(ref _axis, ref xfA.q);
|
||||
|
||||
_localPoint = 0.5f * (localPointA1 + localPointA2);
|
||||
Vector2 pointA = MathUtils.Mul(ref xfA, _localPoint);
|
||||
Vector2 pointA = Transform.Multiply(ref _localPoint, ref xfA);
|
||||
|
||||
Vector2 localPointB = _proxyB.Vertices[cache.IndexB[0]];
|
||||
Vector2 pointB = MathUtils.Mul(ref xfB, localPointB);
|
||||
Vector2 pointB = Transform.Multiply(ref localPointB, ref xfB);
|
||||
|
||||
float s = Vector2.Dot(pointB - pointA, normal);
|
||||
if (s < 0.0f)
|
||||
@@ -149,8 +155,6 @@ namespace FarseerPhysics.Collision
|
||||
_axis = -_axis;
|
||||
}
|
||||
}
|
||||
|
||||
//FPE note: the returned value that used to be here has been removed, as it was not used.
|
||||
}
|
||||
|
||||
public static float FindMinSeparation(out int indexA, out int indexB, float t)
|
||||
@@ -163,8 +167,8 @@ namespace FarseerPhysics.Collision
|
||||
{
|
||||
case SeparationFunctionType.Points:
|
||||
{
|
||||
Vector2 axisA = MathUtils.MulT(ref xfA.q, _axis);
|
||||
Vector2 axisB = MathUtils.MulT(ref xfB.q, -_axis);
|
||||
Vector2 axisA = Complex.Divide(ref _axis, ref xfA.q);
|
||||
Vector2 axisB = -Complex.Divide(ref _axis, ref xfB.q);
|
||||
|
||||
indexA = _proxyA.GetSupport(axisA);
|
||||
indexB = _proxyB.GetSupport(axisB);
|
||||
@@ -172,8 +176,8 @@ namespace FarseerPhysics.Collision
|
||||
Vector2 localPointA = _proxyA.Vertices[indexA];
|
||||
Vector2 localPointB = _proxyB.Vertices[indexB];
|
||||
|
||||
Vector2 pointA = MathUtils.Mul(ref xfA, localPointA);
|
||||
Vector2 pointB = MathUtils.Mul(ref xfB, localPointB);
|
||||
Vector2 pointA = Transform.Multiply(ref localPointA, ref xfA);
|
||||
Vector2 pointB = Transform.Multiply(ref localPointB, ref xfB);
|
||||
|
||||
float separation = Vector2.Dot(pointB - pointA, _axis);
|
||||
return separation;
|
||||
@@ -181,16 +185,16 @@ namespace FarseerPhysics.Collision
|
||||
|
||||
case SeparationFunctionType.FaceA:
|
||||
{
|
||||
Vector2 normal = MathUtils.Mul(ref xfA.q, _axis);
|
||||
Vector2 pointA = MathUtils.Mul(ref xfA, _localPoint);
|
||||
Vector2 normal = Complex.Multiply(ref _axis, ref xfA.q);
|
||||
Vector2 pointA = Transform.Multiply(ref _localPoint, ref xfA);
|
||||
|
||||
Vector2 axisB = MathUtils.MulT(ref xfB.q, -normal);
|
||||
Vector2 axisB = -Complex.Divide(ref normal, ref xfB.q);
|
||||
|
||||
indexA = -1;
|
||||
indexB = _proxyB.GetSupport(axisB);
|
||||
|
||||
Vector2 localPointB = _proxyB.Vertices[indexB];
|
||||
Vector2 pointB = MathUtils.Mul(ref xfB, localPointB);
|
||||
Vector2 pointB = Transform.Multiply(ref localPointB, ref xfB);
|
||||
|
||||
float separation = Vector2.Dot(pointB - pointA, normal);
|
||||
return separation;
|
||||
@@ -198,16 +202,16 @@ namespace FarseerPhysics.Collision
|
||||
|
||||
case SeparationFunctionType.FaceB:
|
||||
{
|
||||
Vector2 normal = MathUtils.Mul(ref xfB.q, _axis);
|
||||
Vector2 pointB = MathUtils.Mul(ref xfB, _localPoint);
|
||||
Vector2 normal = Complex.Multiply(ref _axis, ref xfB.q);
|
||||
Vector2 pointB = Transform.Multiply(ref _localPoint, ref xfB);
|
||||
|
||||
Vector2 axisA = MathUtils.MulT(ref xfA.q, -normal);
|
||||
Vector2 axisA = -Complex.Divide(ref normal, ref xfA.q);
|
||||
|
||||
indexB = -1;
|
||||
indexA = _proxyA.GetSupport(axisA);
|
||||
|
||||
Vector2 localPointA = _proxyA.Vertices[indexA];
|
||||
Vector2 pointA = MathUtils.Mul(ref xfA, localPointA);
|
||||
Vector2 pointA = Transform.Multiply(ref localPointA, ref xfA);
|
||||
|
||||
float separation = Vector2.Dot(pointA - pointB, normal);
|
||||
return separation;
|
||||
@@ -223,8 +227,6 @@ namespace FarseerPhysics.Collision
|
||||
|
||||
public static float Evaluate(int indexA, int indexB, float t)
|
||||
{
|
||||
if (float.IsNaN(t)) return 0.0f;
|
||||
|
||||
Transform xfA, xfB;
|
||||
_sweepA.GetTransform(out xfA, t);
|
||||
_sweepB.GetTransform(out xfB, t);
|
||||
@@ -236,30 +238,30 @@ namespace FarseerPhysics.Collision
|
||||
Vector2 localPointA = _proxyA.Vertices[indexA];
|
||||
Vector2 localPointB = _proxyB.Vertices[indexB];
|
||||
|
||||
Vector2 pointA = MathUtils.Mul(ref xfA, localPointA);
|
||||
Vector2 pointB = MathUtils.Mul(ref xfB, localPointB);
|
||||
Vector2 pointA = Transform.Multiply(ref localPointA, ref xfA);
|
||||
Vector2 pointB = Transform.Multiply(ref localPointB, ref xfB);
|
||||
float separation = Vector2.Dot(pointB - pointA, _axis);
|
||||
|
||||
return separation;
|
||||
}
|
||||
case SeparationFunctionType.FaceA:
|
||||
{
|
||||
Vector2 normal = MathUtils.Mul(ref xfA.q, _axis);
|
||||
Vector2 pointA = MathUtils.Mul(ref xfA, _localPoint);
|
||||
Vector2 normal = Complex.Multiply(ref _axis, ref xfA.q);
|
||||
Vector2 pointA = Transform.Multiply(ref _localPoint, ref xfA);
|
||||
|
||||
Vector2 localPointB = _proxyB.Vertices[indexB];
|
||||
Vector2 pointB = MathUtils.Mul(ref xfB, localPointB);
|
||||
Vector2 pointB = Transform.Multiply(ref localPointB, ref xfB);
|
||||
|
||||
float separation = Vector2.Dot(pointB - pointA, normal);
|
||||
return separation;
|
||||
}
|
||||
case SeparationFunctionType.FaceB:
|
||||
{
|
||||
Vector2 normal = MathUtils.Mul(ref xfB.q, _axis);
|
||||
Vector2 pointB = MathUtils.Mul(ref xfB, _localPoint);
|
||||
Vector2 normal = Complex.Multiply(ref _axis, ref xfB.q);
|
||||
Vector2 pointB = Transform.Multiply(ref _localPoint, ref xfB);
|
||||
|
||||
Vector2 localPointA = _proxyA.Vertices[indexA];
|
||||
Vector2 pointA = MathUtils.Mul(ref xfA, localPointA);
|
||||
Vector2 pointA = Transform.Multiply(ref localPointA, ref xfA);
|
||||
|
||||
float separation = Vector2.Dot(pointA - pointB, normal);
|
||||
return separation;
|
||||
@@ -280,8 +282,6 @@ namespace FarseerPhysics.Collision
|
||||
public static int TOICalls, TOIIters, TOIMaxIters;
|
||||
[ThreadStatic]
|
||||
public static int TOIRootIters, TOIMaxRootIters;
|
||||
[ThreadStatic]
|
||||
private static DistanceInput _distanceInput;
|
||||
|
||||
/// <summary>
|
||||
/// Compute the upper bound on time before two shapes penetrate. Time is represented as
|
||||
@@ -292,7 +292,7 @@ namespace FarseerPhysics.Collision
|
||||
/// </summary>
|
||||
/// <param name="output">The output.</param>
|
||||
/// <param name="input">The input.</param>
|
||||
public static void CalculateTimeOfImpact(out TOIOutput output, TOIInput input)
|
||||
public static void CalculateTimeOfImpact(out TOIOutput output, ref TOIInput input)
|
||||
{
|
||||
if (Settings.EnableDiagnostics) //FPE: We only gather diagnostics when enabled
|
||||
++TOICalls;
|
||||
@@ -321,10 +321,10 @@ namespace FarseerPhysics.Collision
|
||||
int iter = 0;
|
||||
|
||||
// Prepare input for distance query.
|
||||
_distanceInput = _distanceInput ?? new DistanceInput();
|
||||
_distanceInput.ProxyA = input.ProxyA;
|
||||
_distanceInput.ProxyB = input.ProxyB;
|
||||
_distanceInput.UseRadii = false;
|
||||
DistanceInput distanceInput = new DistanceInput();
|
||||
distanceInput.ProxyA = input.ProxyA;
|
||||
distanceInput.ProxyB = input.ProxyB;
|
||||
distanceInput.UseRadii = false;
|
||||
|
||||
// The outer loop progressively attempts to compute new separating axes.
|
||||
// This loop terminates when an axis is repeated (no progress is made).
|
||||
@@ -336,11 +336,11 @@ namespace FarseerPhysics.Collision
|
||||
|
||||
// Get the distance between shapes. We can also use the results
|
||||
// to get a separating axis.
|
||||
_distanceInput.TransformA = xfA;
|
||||
_distanceInput.TransformB = xfB;
|
||||
distanceInput.TransformA = xfA;
|
||||
distanceInput.TransformB = xfB;
|
||||
DistanceOutput distanceOutput;
|
||||
SimplexCache cache;
|
||||
Distance.ComputeDistance(out distanceOutput, out cache, _distanceInput);
|
||||
Distance.ComputeDistance(out distanceOutput, out cache, distanceInput);
|
||||
|
||||
// If the shapes are overlapped, we give up on continuous collision.
|
||||
if (distanceOutput.Distance <= 0.0f)
|
||||
@@ -359,7 +359,7 @@ namespace FarseerPhysics.Collision
|
||||
break;
|
||||
}
|
||||
|
||||
SeparationFunction.Set(ref cache, input.ProxyA, ref sweepA, input.ProxyB, ref sweepB, t1);
|
||||
SeparationFunction.Set(ref cache, ref input.ProxyA, ref sweepA, ref input.ProxyB, ref sweepB, t1);
|
||||
|
||||
// Compute the TOI on the separating axis. We do this by successively
|
||||
// resolving the deepest point. This loop is bounded by the number of vertices.
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Common.ConvexHull
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Common.ConvexHull
|
||||
{
|
||||
@@ -53,7 +58,6 @@ namespace FarseerPhysics.Common.ConvexHull
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -83,7 +87,6 @@ namespace FarseerPhysics.Common.ConvexHull
|
||||
{
|
||||
result.Add(vertices[hull[i]]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Common.ConvexHull
|
||||
{
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
+11
-15
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
@@ -98,7 +103,6 @@ namespace FarseerPhysics.Common.Decomposition.CDT.Delaunay.Sweep
|
||||
EdgeEvent(tcx, e, node);
|
||||
}
|
||||
}
|
||||
tcx.Update(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,10 +522,7 @@ namespace FarseerPhysics.Common.Decomposition.CDT.Delaunay.Sweep
|
||||
{
|
||||
throw new PointOnEdgeException("EdgeEvent - Point on constrained edge not supported yet");
|
||||
}
|
||||
if (tcx.IsDebugEnabled)
|
||||
{
|
||||
Debug.WriteLine("EdgeEvent - Point on constrained edge");
|
||||
}
|
||||
Debug.WriteLine("EdgeEvent - Point on constrained edge");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -542,10 +543,7 @@ namespace FarseerPhysics.Common.Decomposition.CDT.Delaunay.Sweep
|
||||
{
|
||||
throw new PointOnEdgeException("EdgeEvent - Point on constrained edge not supported yet");
|
||||
}
|
||||
if (tcx.IsDebugEnabled)
|
||||
{
|
||||
Debug.WriteLine("EdgeEvent - Point on constrained edge");
|
||||
}
|
||||
Debug.WriteLine("EdgeEvent - Point on constrained edge");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -600,7 +598,7 @@ namespace FarseerPhysics.Common.Decomposition.CDT.Delaunay.Sweep
|
||||
if (eq == tcx.EdgeEvent.ConstrainedEdge.Q
|
||||
&& ep == tcx.EdgeEvent.ConstrainedEdge.P)
|
||||
{
|
||||
if (tcx.IsDebugEnabled) Console.WriteLine("[FLIP] - constrained edge done"); // TODO: remove
|
||||
Debug.WriteLine("[FLIP] - constrained edge done"); // TODO: remove
|
||||
t.MarkConstrainedEdge(ep, eq);
|
||||
ot.MarkConstrainedEdge(ep, eq);
|
||||
Legalize(tcx, t);
|
||||
@@ -608,15 +606,13 @@ namespace FarseerPhysics.Common.Decomposition.CDT.Delaunay.Sweep
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tcx.IsDebugEnabled) Console.WriteLine("[FLIP] - subedge done"); // TODO: remove
|
||||
Debug.WriteLine("[FLIP] - subedge done"); // TODO: remove
|
||||
// XXX: I think one of the triangles should be legalized here?
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tcx.IsDebugEnabled)
|
||||
Console.WriteLine("[FLIP] - flipping and continuing with triangle still crossing edge");
|
||||
// TODO: remove
|
||||
Debug.WriteLine("[FLIP] - flipping and continuing with triangle still crossing edge"); // TODO: remove
|
||||
Orientation o = TriangulationUtil.Orient2d(eq, op, ep);
|
||||
t = NextFlipTriangle(tcx, o, t, ot, p, op);
|
||||
FlipEdgeEvent(tcx, ep, eq, t, p);
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
+6
-7
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
@@ -53,7 +58,6 @@ namespace FarseerPhysics.Common.Decomposition.CDT
|
||||
public bool Terminated { get; set; }
|
||||
|
||||
public int StepCount { get; private set; }
|
||||
public virtual bool IsDebugEnabled { get; protected set; }
|
||||
|
||||
public void Done()
|
||||
{
|
||||
@@ -69,11 +73,6 @@ namespace FarseerPhysics.Common.Decomposition.CDT
|
||||
|
||||
public abstract TriangulationConstraint NewConstraint(TriangulationPoint a, TriangulationPoint b);
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public void Update(string message)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Clear()
|
||||
{
|
||||
Points.Clear();
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FarseerPhysics.Common.Decomposition.CDT.Util
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
/* Poly2Tri
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/* Poly2Tri
|
||||
* Copyright (c) 2009-2010, Poly2Tri Contributors
|
||||
* http://code.google.com/p/poly2tri/
|
||||
*
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/*
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/*
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* C# Version Ported by Matt Bettcher and Ian Qvist 2009-2010
|
||||
*
|
||||
* Original C++ Version Copyright (c) 2007 Eric Jordan
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FarseerPhysics.Common.Decomposition.Seidel
|
||||
{
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FarseerPhysics.Common.Decomposition.Seidel
|
||||
{
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
namespace FarseerPhysics.Common.Decomposition.Seidel
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
namespace FarseerPhysics.Common.Decomposition.Seidel
|
||||
{
|
||||
internal class Point
|
||||
{
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FarseerPhysics.Common.Decomposition.Seidel
|
||||
{
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
namespace FarseerPhysics.Common.Decomposition.Seidel
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
namespace FarseerPhysics.Common.Decomposition.Seidel
|
||||
{
|
||||
internal class Sink : Node
|
||||
{
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FarseerPhysics.Common.Decomposition.Seidel
|
||||
{
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FarseerPhysics.Common.Decomposition.Seidel
|
||||
{
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FarseerPhysics.Common.Decomposition.Seidel
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
namespace FarseerPhysics.Common.Decomposition.Seidel
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
namespace FarseerPhysics.Common.Decomposition.Seidel
|
||||
{
|
||||
internal class XNode : Node
|
||||
{
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
namespace FarseerPhysics.Common.Decomposition.Seidel
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
namespace FarseerPhysics.Common.Decomposition.Seidel
|
||||
{
|
||||
internal class YNode : Node
|
||||
{
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/*
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using FarseerPhysics.Common.ConvexHull;
|
||||
@@ -69,7 +74,12 @@ namespace FarseerPhysics.Common.Decomposition
|
||||
|
||||
public static class Triangulate
|
||||
{
|
||||
public static List<Vertices> ConvexPartition(Vertices vertices, TriangulationAlgorithm algorithm, bool discardAndFixInvalid = true, float tolerance = 0.001f)
|
||||
/// <param name="skipSanityChecks">
|
||||
/// Set this to true to skip sanity checks in the engine. This will speed up the
|
||||
/// tools by removing the overhead of the checks, but you will need to handle checks
|
||||
/// yourself where it is needed.
|
||||
/// </param>
|
||||
public static List<Vertices> ConvexPartition(Vertices vertices, TriangulationAlgorithm algorithm, bool discardAndFixInvalid = true, float tolerance = 0.001f, bool skipSanityChecks = false)
|
||||
{
|
||||
if (vertices.Count <= 3)
|
||||
return new List<Vertices> { vertices };
|
||||
@@ -79,49 +89,37 @@ namespace FarseerPhysics.Common.Decomposition
|
||||
switch (algorithm)
|
||||
{
|
||||
case TriangulationAlgorithm.Earclip:
|
||||
if (Settings.SkipSanityChecks)
|
||||
if (skipSanityChecks)
|
||||
Debug.Assert(!vertices.IsCounterClockWise(), "The Earclip algorithm expects the polygon to be clockwise.");
|
||||
else
|
||||
else if (vertices.IsCounterClockWise())
|
||||
{
|
||||
if (vertices.IsCounterClockWise())
|
||||
{
|
||||
Vertices temp = new Vertices(vertices);
|
||||
temp.Reverse();
|
||||
results = EarclipDecomposer.ConvexPartition(temp, tolerance);
|
||||
}
|
||||
else
|
||||
results = EarclipDecomposer.ConvexPartition(vertices, tolerance);
|
||||
Vertices temp = new Vertices(vertices);
|
||||
temp.Reverse();
|
||||
vertices = temp;
|
||||
}
|
||||
results = EarclipDecomposer.ConvexPartition(vertices, tolerance);
|
||||
break;
|
||||
case TriangulationAlgorithm.Bayazit:
|
||||
if (Settings.SkipSanityChecks)
|
||||
if (skipSanityChecks)
|
||||
Debug.Assert(vertices.IsCounterClockWise(), "The polygon is not counter clockwise. This is needed for Bayazit to work correctly.");
|
||||
else
|
||||
else if (!vertices.IsCounterClockWise())
|
||||
{
|
||||
if (!vertices.IsCounterClockWise())
|
||||
{
|
||||
Vertices temp = new Vertices(vertices);
|
||||
temp.Reverse();
|
||||
results = BayazitDecomposer.ConvexPartition(temp);
|
||||
}
|
||||
else
|
||||
results = BayazitDecomposer.ConvexPartition(vertices);
|
||||
Vertices temp = new Vertices(vertices);
|
||||
temp.Reverse();
|
||||
vertices = temp;
|
||||
}
|
||||
results = BayazitDecomposer.ConvexPartition(vertices);
|
||||
break;
|
||||
case TriangulationAlgorithm.Flipcode:
|
||||
if (Settings.SkipSanityChecks)
|
||||
if (skipSanityChecks)
|
||||
Debug.Assert(vertices.IsCounterClockWise(), "The polygon is not counter clockwise. This is needed for Bayazit to work correctly.");
|
||||
else
|
||||
else if (!vertices.IsCounterClockWise())
|
||||
{
|
||||
if (!vertices.IsCounterClockWise())
|
||||
{
|
||||
Vertices temp = new Vertices(vertices);
|
||||
temp.Reverse();
|
||||
results = FlipcodeDecomposer.ConvexPartition(temp);
|
||||
}
|
||||
else
|
||||
results = FlipcodeDecomposer.ConvexPartition(vertices);
|
||||
Vertices temp = new Vertices(vertices);
|
||||
temp.Reverse();
|
||||
vertices = temp;
|
||||
}
|
||||
results = FlipcodeDecomposer.ConvexPartition(vertices);
|
||||
break;
|
||||
case TriangulationAlgorithm.Seidel:
|
||||
results = SeidelDecomposer.ConvexPartition(vertices, tolerance);
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/*
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
*
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using FarseerPhysics.Collision;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/*
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
*
|
||||
@@ -24,6 +29,7 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Xna.Framework;
|
||||
using FarseerPhysics.Common.Maths;
|
||||
|
||||
namespace FarseerPhysics.Common
|
||||
{
|
||||
@@ -40,9 +46,11 @@ namespace FarseerPhysics.Common
|
||||
}
|
||||
|
||||
/// Perform the cross product on two vectors.
|
||||
public static Vector3 Cross(Vector3 a, Vector3 b)
|
||||
public static Vector3 Cross(ref Vector3 a, ref Vector3 b)
|
||||
{
|
||||
return new Vector3(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);
|
||||
return new Vector3( a.Y * b.Z - a.Z * b.Y,
|
||||
a.Z * b.X - a.X * b.Z,
|
||||
a.X * b.Y - a.Y * b.X);
|
||||
}
|
||||
|
||||
public static Vector2 Cross(Vector2 a, float s)
|
||||
@@ -50,11 +58,21 @@ namespace FarseerPhysics.Common
|
||||
return new Vector2(s * a.Y, -s * a.X);
|
||||
}
|
||||
|
||||
public static Vector2 Cross(float s, Vector2 a)
|
||||
public static Vector2 Rot270(ref Vector2 a)
|
||||
{
|
||||
return new Vector2(a.Y, -a.X);
|
||||
}
|
||||
|
||||
public static Vector2 Cross(float s, ref Vector2 a)
|
||||
{
|
||||
return new Vector2(-s * a.Y, s * a.X);
|
||||
}
|
||||
|
||||
public static Vector2 Rot90(ref Vector2 a)
|
||||
{
|
||||
return new Vector2(-a.Y, a.X);
|
||||
}
|
||||
|
||||
public static Vector2 Abs(Vector2 v)
|
||||
{
|
||||
return new Vector2(Math.Abs(v.X), Math.Abs(v.Y));
|
||||
@@ -69,19 +87,7 @@ namespace FarseerPhysics.Common
|
||||
{
|
||||
return new Vector2(A.ex.X * v.X + A.ey.X * v.Y, A.ex.Y * v.X + A.ey.Y * v.Y);
|
||||
}
|
||||
|
||||
public static Vector2 Mul(ref Transform T, Vector2 v)
|
||||
{
|
||||
return Mul(ref T, ref v);
|
||||
}
|
||||
|
||||
public static Vector2 Mul(ref Transform T, ref Vector2 v)
|
||||
{
|
||||
return new Vector2(
|
||||
(T.q.c * v.X - T.q.s * v.Y) + T.p.X,
|
||||
(T.q.s * v.X + T.q.c * v.Y) + T.p.Y);
|
||||
}
|
||||
|
||||
|
||||
public static Vector2 MulT(ref Mat22 A, Vector2 v)
|
||||
{
|
||||
return MulT(ref A, ref v);
|
||||
@@ -92,18 +98,6 @@ namespace FarseerPhysics.Common
|
||||
return new Vector2(v.X * A.ex.X + v.Y * A.ex.Y, v.X * A.ey.X + v.Y * A.ey.Y);
|
||||
}
|
||||
|
||||
public static Vector2 MulT(ref Transform T, Vector2 v)
|
||||
{
|
||||
return MulT(ref T, ref v);
|
||||
}
|
||||
|
||||
public static Vector2 MulT(ref Transform T, ref Vector2 v)
|
||||
{
|
||||
float px = v.X - T.p.X;
|
||||
float py = v.Y - T.p.Y;
|
||||
|
||||
return new Vector2(T.q.c * px + T.q.s * py, -T.q.s * px + T.q.c * py);
|
||||
}
|
||||
|
||||
// A^T * B
|
||||
public static void MulT(ref Mat22 A, ref Mat22 B, out Mat22 C)
|
||||
@@ -120,26 +114,7 @@ namespace FarseerPhysics.Common
|
||||
{
|
||||
return v.X * A.ex + v.Y * A.ey + v.Z * A.ez;
|
||||
}
|
||||
|
||||
// v2 = A.q.Rot(B.q.Rot(v1) + B.p) + A.p
|
||||
// = (A.q * B.q).Rot(v1) + A.q.Rot(B.p) + A.p
|
||||
public static Transform Mul(Transform A, Transform B)
|
||||
{
|
||||
Transform C = new Transform();
|
||||
C.q = Mul(A.q, B.q);
|
||||
C.p = Mul(A.q, B.p) + A.p;
|
||||
return C;
|
||||
}
|
||||
|
||||
// v2 = A.q' * (B.q * v1 + B.p - A.p)
|
||||
// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
|
||||
public static void MulT(ref Transform A, ref Transform B, out Transform C)
|
||||
{
|
||||
C = new Transform();
|
||||
C.q = MulT(A.q, B.q);
|
||||
C.p = MulT(A.q, B.p - A.p);
|
||||
}
|
||||
|
||||
|
||||
public static void Swap<T>(ref T a, ref T b)
|
||||
{
|
||||
T tmp = a;
|
||||
@@ -152,65 +127,7 @@ namespace FarseerPhysics.Common
|
||||
{
|
||||
return new Vector2(A.ex.X * v.X + A.ey.X * v.Y, A.ex.Y * v.X + A.ey.Y * v.Y);
|
||||
}
|
||||
|
||||
/// Multiply two rotations: q * r
|
||||
public static Rot Mul(Rot q, Rot r)
|
||||
{
|
||||
// [qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc]
|
||||
// [qs qc] [rs rc] [qs*rc+qc*rs -qs*rs+qc*rc]
|
||||
// s = qs * rc + qc * rs
|
||||
// c = qc * rc - qs * rs
|
||||
Rot qr;
|
||||
qr.s = q.s * r.c + q.c * r.s;
|
||||
qr.c = q.c * r.c - q.s * r.s;
|
||||
return qr;
|
||||
}
|
||||
|
||||
public static Vector2 MulT(Transform T, Vector2 v)
|
||||
{
|
||||
float px = v.X - T.p.X;
|
||||
float py = v.Y - T.p.Y;
|
||||
float x = (T.q.c * px + T.q.s * py);
|
||||
float y = (-T.q.s * px + T.q.c * py);
|
||||
|
||||
return new Vector2(x, y);
|
||||
}
|
||||
|
||||
/// Transpose multiply two rotations: qT * r
|
||||
public static Rot MulT(Rot q, Rot r)
|
||||
{
|
||||
// [ qc qs] * [rc -rs] = [qc*rc+qs*rs -qc*rs+qs*rc]
|
||||
// [-qs qc] [rs rc] [-qs*rc+qc*rs qs*rs+qc*rc]
|
||||
// s = qc * rs - qs * rc
|
||||
// c = qc * rc + qs * rs
|
||||
Rot qr;
|
||||
qr.s = q.c * r.s - q.s * r.c;
|
||||
qr.c = q.c * r.c + q.s * r.s;
|
||||
return qr;
|
||||
}
|
||||
|
||||
// v2 = A.q' * (B.q * v1 + B.p - A.p)
|
||||
// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
|
||||
public static Transform MulT(Transform A, Transform B)
|
||||
{
|
||||
Transform C = new Transform();
|
||||
C.q = MulT(A.q, B.q);
|
||||
C.p = MulT(A.q, B.p - A.p);
|
||||
return C;
|
||||
}
|
||||
|
||||
/// Rotate a vector
|
||||
public static Vector2 Mul(Rot q, Vector2 v)
|
||||
{
|
||||
return new Vector2(q.c * v.X - q.s * v.Y, q.s * v.X + q.c * v.Y);
|
||||
}
|
||||
|
||||
/// Inverse rotate a vector
|
||||
public static Vector2 MulT(Rot q, Vector2 v)
|
||||
{
|
||||
return new Vector2(q.c * v.X + q.s * v.Y, -q.s * v.X + q.c * v.Y);
|
||||
}
|
||||
|
||||
|
||||
/// Get the skew vector such that dot(skew_vec, other) == cross(vec, other)
|
||||
public static Vector2 Skew(Vector2 input)
|
||||
{
|
||||
@@ -301,6 +218,12 @@ namespace FarseerPhysics.Common
|
||||
return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
|
||||
}
|
||||
|
||||
/// Perform the dot product on two vectors.
|
||||
public static float Dot(Vector2 a, ref Vector2 b)
|
||||
{
|
||||
return a.X * b.X + a.Y * b.Y;
|
||||
}
|
||||
|
||||
public static double VectorAngle(Vector2 p1, Vector2 p2)
|
||||
{
|
||||
return VectorAngle(ref p1, ref p2);
|
||||
@@ -389,15 +312,6 @@ namespace FarseerPhysics.Common
|
||||
|
||||
#endregion
|
||||
|
||||
public static Vector2 Mul(ref Rot rot, Vector2 axis)
|
||||
{
|
||||
return Mul(rot, axis);
|
||||
}
|
||||
|
||||
public static Vector2 MulT(ref Rot rot, Vector2 axis)
|
||||
{
|
||||
return MulT(rot, axis);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -598,7 +512,7 @@ namespace FarseerPhysics.Common
|
||||
/// Returns the zero matrix if singular.
|
||||
public void GetSymInverse33(ref Mat33 M)
|
||||
{
|
||||
float det = MathUtils.Dot(ex, MathUtils.Cross(ey, ez));
|
||||
float det = MathUtils.Dot(ex, MathUtils.Cross(ref ey, ref ez));
|
||||
if (det != 0.0f)
|
||||
{
|
||||
det = 1.0f / det;
|
||||
@@ -622,108 +536,108 @@ namespace FarseerPhysics.Common
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotation
|
||||
/// </summary>
|
||||
public struct Rot
|
||||
{
|
||||
/// Sine and cosine
|
||||
public float s, c;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize from an angle in radians
|
||||
/// </summary>
|
||||
/// <param name="angle">Angle in radians</param>
|
||||
public Rot(float angle)
|
||||
{
|
||||
// TODO_ERIN optimize
|
||||
s = (float)Math.Sin(angle);
|
||||
c = (float)Math.Cos(angle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set using an angle in radians.
|
||||
/// </summary>
|
||||
/// <param name="angle"></param>
|
||||
public void Set(float angle)
|
||||
{
|
||||
// TODO_ERIN optimize
|
||||
s = (float)Math.Sin(angle);
|
||||
c = (float)Math.Cos(angle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set to the identity rotation
|
||||
/// </summary>
|
||||
public void SetIdentity()
|
||||
{
|
||||
s = 0.0f;
|
||||
c = 1.0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the angle in radians
|
||||
/// </summary>
|
||||
public float GetAngle()
|
||||
{
|
||||
return (float)Math.Atan2(s, c);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the x-axis
|
||||
/// </summary>
|
||||
public Vector2 GetXAxis()
|
||||
{
|
||||
return new Vector2(c, s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the y-axis
|
||||
/// </summary>
|
||||
public Vector2 GetYAxis()
|
||||
{
|
||||
return new Vector2(-s, c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A transform contains translation and rotation. It is used to represent
|
||||
/// the position and orientation of rigid frames.
|
||||
/// </summary>
|
||||
public struct Transform
|
||||
{
|
||||
private static readonly Transform _identity = new Transform(Vector2.Zero, Complex.One);
|
||||
|
||||
public Complex q;
|
||||
public Vector2 p;
|
||||
public Rot q;
|
||||
|
||||
public static Transform Identity { get { return _identity; } }
|
||||
|
||||
/// <summary>
|
||||
/// Initialize using a position vector and a rotation matrix.
|
||||
/// Initialize using a position vector and a Complex rotation.
|
||||
/// </summary>
|
||||
/// <param name="position">The position.</param>
|
||||
/// <param name="rotation">The r.</param>
|
||||
public Transform(ref Vector2 position, ref Rot rotation)
|
||||
/// <param name="rotation">The rotation</param>
|
||||
public Transform(Vector2 position, Complex rotation)
|
||||
{
|
||||
p = position;
|
||||
q = rotation;
|
||||
p = position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set this to the identity transform.
|
||||
/// </summary>
|
||||
public void SetIdentity()
|
||||
{
|
||||
p = Vector2.Zero;
|
||||
q.SetIdentity();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set this based on the position and angle.
|
||||
/// Initialize using a position vector and a rotation.
|
||||
/// </summary>
|
||||
/// <param name="position">The position.</param>
|
||||
/// <param name="angle">The angle.</param>
|
||||
public void Set(Vector2 position, float angle)
|
||||
/// <param name="angle">The rotation angle</param>
|
||||
public Transform(Vector2 position, float angle)
|
||||
: this(position, Complex.FromAngle(angle))
|
||||
{
|
||||
p = position;
|
||||
q.Set(angle);
|
||||
}
|
||||
|
||||
public static Vector2 Multiply(Vector2 left, ref Transform right)
|
||||
{
|
||||
return Multiply(ref left, ref right);
|
||||
}
|
||||
|
||||
public static Vector2 Multiply(ref Vector2 left, ref Transform right)
|
||||
{
|
||||
// Opt: var result = Complex.Multiply(left, right.q) + right.p;
|
||||
return new Vector2(
|
||||
(left.X * right.q.Real - left.Y * right.q.Imaginary) + right.p.X,
|
||||
(left.Y * right.q.Real + left.X * right.q.Imaginary) + right.p.Y);
|
||||
}
|
||||
|
||||
public static Vector2 Divide(Vector2 left, ref Transform right)
|
||||
{
|
||||
return Divide(ref left, ref right);
|
||||
}
|
||||
|
||||
public static Vector2 Divide(ref Vector2 left, ref Transform right)
|
||||
{
|
||||
// Opt: var result = Complex.Divide(left - right.p, right);
|
||||
float px = left.X - right.p.X;
|
||||
float py = left.Y - right.p.Y;
|
||||
return new Vector2(
|
||||
(px * right.q.Real + py * right.q.Imaginary),
|
||||
(py * right.q.Real - px * right.q.Imaginary));
|
||||
}
|
||||
|
||||
public static void Divide(Vector2 left, ref Transform right, out Vector2 result)
|
||||
{
|
||||
// Opt: var result = Complex.Divide(left - right.p, right);
|
||||
float px = left.X - right.p.X;
|
||||
float py = left.Y - right.p.Y;
|
||||
result.X = (px * right.q.Real + py * right.q.Imaginary);
|
||||
result.Y = (py * right.q.Real - px * right.q.Imaginary);
|
||||
}
|
||||
|
||||
public static Transform Multiply(ref Transform left, ref Transform right)
|
||||
{
|
||||
return new Transform(
|
||||
Complex.Multiply(ref left.p, ref right.q) + right.p,
|
||||
Complex.Multiply(ref left.q, ref right.q));
|
||||
}
|
||||
|
||||
public static Transform Divide(ref Transform left, ref Transform right)
|
||||
{
|
||||
return new Transform(
|
||||
Complex.Divide(left.p - right.p, ref right.q),
|
||||
Complex.Divide(ref left.q, ref right.q));
|
||||
}
|
||||
|
||||
public static void Divide(ref Transform left, ref Transform right, out Transform result)
|
||||
{
|
||||
Complex.Divide(left.p - right.p, ref right.q, out result.p);
|
||||
Complex.Divide(ref left.q, ref right.q, out result.q);
|
||||
}
|
||||
|
||||
public static void Multiply(ref Transform left, Complex right, out Transform result)
|
||||
{
|
||||
result.p = Complex.Multiply(ref left.p, ref right);
|
||||
result.q = Complex.Multiply(ref left.q, ref right);
|
||||
}
|
||||
|
||||
public static void Divide(ref Transform left, Complex right, out Transform result)
|
||||
{
|
||||
result.p = Complex.Divide(ref left.p, ref right);
|
||||
result.q = Complex.Divide(ref left.q, ref right);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -771,10 +685,10 @@ namespace FarseerPhysics.Common
|
||||
xfb.p.X = (1.0f - beta) * C0.X + beta * C.X;
|
||||
xfb.p.Y = (1.0f - beta) * C0.Y + beta * C.Y;
|
||||
float angle = (1.0f - beta) * A0 + beta * A;
|
||||
xfb.q.Set(angle);
|
||||
xfb.q.Phase = angle;
|
||||
|
||||
// Shift to origin
|
||||
xfb.p -= MathUtils.Mul(xfb.q, LocalCenter);
|
||||
xfb.p -= Complex.Multiply(ref LocalCenter, ref xfb.q);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
#if !XNA && !WINDOWS_PHONE && !XBOX && !ANDROID
|
||||
|
||||
#region License
|
||||
|
||||
/*
|
||||
MIT License
|
||||
Copyright © 2006 The Mono.Xna Team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#endregion License
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Xna.Framework
|
||||
{
|
||||
public static class MathHelper
|
||||
{
|
||||
public const float E = (float) Math.E;
|
||||
public const float Log10E = 0.4342945f;
|
||||
public const float Log2E = 1.442695f;
|
||||
public const float Pi = (float) Math.PI;
|
||||
public const float PiOver2 = (float) (Math.PI/2.0);
|
||||
public const float PiOver4 = (float) (Math.PI/4.0);
|
||||
public const float TwoPi = (float) (Math.PI*2.0);
|
||||
|
||||
public static float Barycentric(float value1, float value2, float value3, float amount1, float amount2)
|
||||
{
|
||||
return value1 + (value2 - value1)*amount1 + (value3 - value1)*amount2;
|
||||
}
|
||||
|
||||
public static float CatmullRom(float value1, float value2, float value3, float value4, float amount)
|
||||
{
|
||||
// Using formula from http://www.mvps.org/directx/articles/catmull/
|
||||
// Internally using doubles not to lose precission
|
||||
double amountSquared = amount*amount;
|
||||
double amountCubed = amountSquared*amount;
|
||||
return (float) (0.5*(2.0*value2 +
|
||||
(value3 - value1)*amount +
|
||||
(2.0*value1 - 5.0*value2 + 4.0*value3 - value4)*amountSquared +
|
||||
(3.0*value2 - value1 - 3.0*value3 + value4)*amountCubed));
|
||||
}
|
||||
|
||||
public static float Clamp(float value, float min, float max)
|
||||
{
|
||||
// First we check to see if we're greater than the max
|
||||
value = (value > max) ? max : value;
|
||||
|
||||
// Then we check to see if we're less than the min.
|
||||
value = (value < min) ? min : value;
|
||||
|
||||
// There's no check to see if min > max.
|
||||
return value;
|
||||
}
|
||||
|
||||
public static int Clamp(int value, int min, int max)
|
||||
{
|
||||
// First we check to see if we're greater than the max
|
||||
value = (value > max) ? max : value;
|
||||
|
||||
// Then we check to see if we're less than the min.
|
||||
value = (value < min) ? min : value;
|
||||
|
||||
// There's no check to see if min > max.
|
||||
return value;
|
||||
}
|
||||
|
||||
public static float Distance(float value1, float value2)
|
||||
{
|
||||
return Math.Abs(value1 - value2);
|
||||
}
|
||||
|
||||
public static float Hermite(float value1, float tangent1, float value2, float tangent2, float amount)
|
||||
{
|
||||
// All transformed to double not to lose precission
|
||||
// Otherwise, for high numbers of param:amount the result is NaN instead of Infinity
|
||||
double v1 = value1, v2 = value2, t1 = tangent1, t2 = tangent2, s = amount, result;
|
||||
double sCubed = s*s*s;
|
||||
double sSquared = s*s;
|
||||
|
||||
if (amount == 0f)
|
||||
result = value1;
|
||||
else if (amount == 1f)
|
||||
result = value2;
|
||||
else
|
||||
result = (2*v1 - 2*v2 + t2 + t1)*sCubed +
|
||||
(3*v2 - 3*v1 - 2*t1 - t2)*sSquared +
|
||||
t1*s +
|
||||
v1;
|
||||
return (float) result;
|
||||
}
|
||||
|
||||
public static float Lerp(float value1, float value2, float amount)
|
||||
{
|
||||
return value1 + (value2 - value1)*amount;
|
||||
}
|
||||
|
||||
public static float Max(float value1, float value2)
|
||||
{
|
||||
return Math.Max(value1, value2);
|
||||
}
|
||||
|
||||
public static float Min(float value1, float value2)
|
||||
{
|
||||
return Math.Min(value1, value2);
|
||||
}
|
||||
|
||||
public static float SmoothStep(float value1, float value2, float amount)
|
||||
{
|
||||
// It is expected that 0 < amount < 1
|
||||
// If amount < 0, return value1
|
||||
// If amount > 1, return value2
|
||||
float result = Clamp(amount, 0f, 1f);
|
||||
result = Hermite(value1, 0f, value2, 0f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static float ToDegrees(float radians)
|
||||
{
|
||||
// This method uses double precission internally,
|
||||
// though it returns single float
|
||||
// Factor = 180 / pi
|
||||
return (float) (radians*57.295779513082320876798154814105);
|
||||
}
|
||||
|
||||
public static float ToRadians(float degrees)
|
||||
{
|
||||
// This method uses double precission internally,
|
||||
// though it returns single float
|
||||
// Factor = pi / 180
|
||||
return (float) (degrees*0.017453292519943295769236907684886);
|
||||
}
|
||||
|
||||
public static float WrapAngle(float angle)
|
||||
{
|
||||
angle = (float) Math.IEEERemainder((double) angle, 6.2831854820251465); //2xPi precission is double
|
||||
if (angle <= -3.141593f)
|
||||
{
|
||||
angle += 6.283185f;
|
||||
return angle;
|
||||
}
|
||||
if (angle > 3.141593f)
|
||||
{
|
||||
angle -= 6.283185f;
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,155 @@
|
||||
// Copyright (c) 2017 Kastellanos Nikolaos
|
||||
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Common.Maths
|
||||
{
|
||||
public struct Complex
|
||||
{
|
||||
private static readonly Complex _one = new Complex(1, 0);
|
||||
private static readonly Complex _imaginaryOne = new Complex(0, 1);
|
||||
|
||||
public float Real;
|
||||
public float Imaginary;
|
||||
|
||||
public static Complex One { get { return _one; } }
|
||||
public static Complex ImaginaryOne { get { return _imaginaryOne; } }
|
||||
|
||||
public float Phase
|
||||
{
|
||||
get { return (float)Math.Atan2(Imaginary, Real); }
|
||||
set
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
this = Complex.One;
|
||||
return;
|
||||
}
|
||||
this.Real = (float)Math.Cos(value);
|
||||
this.Imaginary = (float)Math.Sin(value);
|
||||
}
|
||||
}
|
||||
|
||||
public float Magnitude
|
||||
{
|
||||
get { return (float)Math.Round(Math.Sqrt(MagnitudeSquared())); }
|
||||
}
|
||||
|
||||
|
||||
public Complex(float real, float imaginary)
|
||||
{
|
||||
Real = real;
|
||||
Imaginary = imaginary;
|
||||
}
|
||||
|
||||
public static Complex FromAngle(float angle)
|
||||
{
|
||||
if (angle == 0)
|
||||
return Complex.One;
|
||||
|
||||
return new Complex(
|
||||
(float)Math.Cos(angle),
|
||||
(float)Math.Sin(angle));
|
||||
}
|
||||
|
||||
public void Conjugate()
|
||||
{
|
||||
Imaginary = -Imaginary;
|
||||
}
|
||||
|
||||
public void Negate()
|
||||
{
|
||||
Real = -Real;
|
||||
Imaginary = -Imaginary;
|
||||
}
|
||||
|
||||
public float MagnitudeSquared()
|
||||
{
|
||||
return (Real * Real) + (Imaginary * Imaginary);
|
||||
}
|
||||
|
||||
public void Normalize()
|
||||
{
|
||||
var mag = Magnitude;
|
||||
Real = Real / mag;
|
||||
Imaginary = Imaginary / mag;
|
||||
}
|
||||
|
||||
public Vector2 ToVector2()
|
||||
{
|
||||
return new Vector2(Real, Imaginary);
|
||||
}
|
||||
|
||||
public static Complex Multiply(ref Complex left, ref Complex right)
|
||||
{
|
||||
return new Complex( left.Real * right.Real - left.Imaginary * right.Imaginary,
|
||||
left.Imaginary * right.Real + left.Real * right.Imaginary);
|
||||
}
|
||||
|
||||
public static Complex Divide(ref Complex left, ref Complex right)
|
||||
{
|
||||
return new Complex( right.Real * left.Real + right.Imaginary * left.Imaginary,
|
||||
right.Real * left.Imaginary - right.Imaginary * left.Real);
|
||||
}
|
||||
public static void Divide(ref Complex left, ref Complex right, out Complex result)
|
||||
{
|
||||
result = new Complex(right.Real * left.Real + right.Imaginary * left.Imaginary,
|
||||
right.Real * left.Imaginary - right.Imaginary * left.Real);
|
||||
}
|
||||
|
||||
public static Vector2 Multiply(ref Vector2 left, ref Complex right)
|
||||
{
|
||||
return new Vector2(left.X * right.Real - left.Y * right.Imaginary,
|
||||
left.Y * right.Real + left.X * right.Imaginary);
|
||||
}
|
||||
public static void Multiply(ref Vector2 left, ref Complex right, out Vector2 result)
|
||||
{
|
||||
result = new Vector2(left.X * right.Real - left.Y * right.Imaginary,
|
||||
left.Y * right.Real + left.X * right.Imaginary);
|
||||
}
|
||||
public static Vector2 Multiply(Vector2 left, ref Complex right)
|
||||
{
|
||||
return new Vector2(left.X * right.Real - left.Y * right.Imaginary,
|
||||
left.Y * right.Real + left.X * right.Imaginary);
|
||||
}
|
||||
|
||||
public static Vector2 Divide(ref Vector2 left, ref Complex right)
|
||||
{
|
||||
return new Vector2(left.X * right.Real + left.Y * right.Imaginary,
|
||||
left.Y * right.Real - left.X * right.Imaginary);
|
||||
}
|
||||
|
||||
public static Vector2 Divide(Vector2 left, ref Complex right)
|
||||
{
|
||||
return new Vector2(left.X * right.Real + left.Y * right.Imaginary,
|
||||
left.Y * right.Real - left.X * right.Imaginary);
|
||||
}
|
||||
public static void Divide(Vector2 left, ref Complex right, out Vector2 result)
|
||||
{
|
||||
result = new Vector2(left.X * right.Real + left.Y * right.Imaginary,
|
||||
left.Y * right.Real - left.X * right.Imaginary);
|
||||
}
|
||||
|
||||
public static Complex Conjugate(ref Complex value)
|
||||
{
|
||||
return new Complex(value.Real, -value.Imaginary);
|
||||
}
|
||||
|
||||
public static Complex Negate(ref Complex value)
|
||||
{
|
||||
return new Complex(-value.Real, -value.Real);
|
||||
}
|
||||
|
||||
public static Complex Normalize(ref Complex value)
|
||||
{
|
||||
var mag = value.Magnitude;
|
||||
return new Complex(value.Real / mag, -value.Imaginary / mag);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("{{Real: {0} Imaginary: {1} Phase: {2} Magnitude: {3}}}", Real, Imaginary, Phase, Magnitude);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,9 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Xna.Framework;
|
||||
@@ -239,9 +244,6 @@ namespace FarseerPhysics.Common
|
||||
|
||||
Vector2.Subtract(ref a, ref b, out temp);
|
||||
|
||||
#if (XBOX360 || WINDOWS_PHONE)
|
||||
output = new Vector2();
|
||||
#endif
|
||||
output.X = -temp.Y;
|
||||
output.Y = temp.X;
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FarseerPhysics.Collision.Shapes;
|
||||
using FarseerPhysics.Common.Decomposition;
|
||||
@@ -90,7 +95,7 @@ namespace FarseerPhysics.Common
|
||||
|
||||
for (int i = 0; i < centers.Count; i++)
|
||||
{
|
||||
Body b = new Body(world);
|
||||
Body b = world.CreateBody();
|
||||
|
||||
// copy the type from original body
|
||||
b.BodyType = type;
|
||||
@@ -120,20 +125,14 @@ namespace FarseerPhysics.Common
|
||||
/// <param name="copies">The copies.</param>
|
||||
/// <param name="userData">The user data.</param>
|
||||
/// <returns></returns>
|
||||
public static List<Body> EvenlyDistributeShapesAlongPath(World world, Path path, Shape shape, BodyType type,
|
||||
int copies, object userData)
|
||||
public static List<Body> EvenlyDistributeShapesAlongPath(World world, Path path, Shape shape, BodyType type, int copies, object userData = null)
|
||||
{
|
||||
List<Shape> shapes = new List<Shape>(1);
|
||||
shapes.Add(shape);
|
||||
|
||||
return EvenlyDistributeShapesAlongPath(world, path, shapes, type, copies, userData);
|
||||
}
|
||||
|
||||
public static List<Body> EvenlyDistributeShapesAlongPath(World world, Path path, Shape shape, BodyType type, int copies)
|
||||
{
|
||||
return EvenlyDistributeShapesAlongPath(world, path, shape, type, copies, null);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Moves the given body along the defined path.
|
||||
/// </summary>
|
||||
@@ -168,7 +167,7 @@ namespace FarseerPhysics.Common
|
||||
{
|
||||
RevoluteJoint joint = new RevoluteJoint(bodies[i], bodies[i - 1], localAnchorA, localAnchorB);
|
||||
joint.CollideConnected = collideConnected;
|
||||
world.AddJoint(joint);
|
||||
world.Add(joint);
|
||||
joints.Add(joint);
|
||||
}
|
||||
|
||||
@@ -176,7 +175,7 @@ namespace FarseerPhysics.Common
|
||||
{
|
||||
RevoluteJoint lastjoint = new RevoluteJoint(bodies[0], bodies[bodies.Count - 1], localAnchorA, localAnchorB);
|
||||
lastjoint.CollideConnected = collideConnected;
|
||||
world.AddJoint(lastjoint);
|
||||
world.Add(lastjoint);
|
||||
joints.Add(lastjoint);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using FarseerPhysics.Collision.Shapes;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using FarseerPhysics.Dynamics.Contacts;
|
||||
using FarseerPhysics.Common.Decomposition;
|
||||
|
||||
namespace FarseerPhysics.Common.PhysicsLogic
|
||||
{
|
||||
/// <summary>
|
||||
/// A type of body that supports multiple fixtures that can break apart.
|
||||
/// </summary>
|
||||
public class BreakableBody
|
||||
{
|
||||
public enum BreakableBodyState
|
||||
{
|
||||
Unbroken,
|
||||
ShouldBreak,
|
||||
Broken,
|
||||
}
|
||||
|
||||
private float[] _angularVelocitiesCache = new float[8];
|
||||
private Vector2[] _velocitiesCache = new Vector2[8];
|
||||
|
||||
public List<Fixture> Parts = new List<Fixture>(8);
|
||||
|
||||
public World World { get; private set; }
|
||||
public Body MainBody { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The force needed to break the body apart.
|
||||
/// Default: 500
|
||||
/// </summary>
|
||||
public float Strength = 500.0f;
|
||||
|
||||
public BreakableBodyState State { get; private set; }
|
||||
|
||||
private BreakableBody(World world)
|
||||
{
|
||||
World = world;
|
||||
World.ContactManager.PostSolve += PostSolve;
|
||||
|
||||
State = BreakableBodyState.Unbroken;
|
||||
}
|
||||
|
||||
public BreakableBody(World world, IEnumerable<Vertices> vertices, float density, Vector2 position = new Vector2(), float rotation = 0) : this(world)
|
||||
{
|
||||
MainBody = World.CreateBody(position, rotation, BodyType.Dynamic);
|
||||
|
||||
foreach (Vertices part in vertices)
|
||||
{
|
||||
PolygonShape polygonShape = new PolygonShape(part, density);
|
||||
Fixture fixture = MainBody.CreateFixture(polygonShape);
|
||||
Parts.Add(fixture);
|
||||
}
|
||||
}
|
||||
|
||||
public BreakableBody(World world, IEnumerable<Shape> shapes, Vector2 position = new Vector2(), float rotation = 0) : this(world)
|
||||
{
|
||||
MainBody = World.CreateBody(position, rotation, BodyType.Dynamic);
|
||||
|
||||
foreach (Shape part in shapes)
|
||||
{
|
||||
Fixture fixture = MainBody.CreateFixture(part);
|
||||
Parts.Add(fixture);
|
||||
}
|
||||
}
|
||||
|
||||
public BreakableBody(World world, Vertices vertices, float density, Vector2 position = new Vector2(), float rotation = 0) : this(world)
|
||||
{
|
||||
MainBody = World.CreateBody(position, rotation, BodyType.Dynamic);
|
||||
|
||||
//TODO: Implement a Voronoi diagram algorithm to split up the vertices
|
||||
List<Vertices> triangles = Triangulate.ConvexPartition(vertices, TriangulationAlgorithm.Earclip);
|
||||
|
||||
foreach (Vertices part in triangles)
|
||||
{
|
||||
PolygonShape polygonShape = new PolygonShape(part, density);
|
||||
Fixture fixture = MainBody.CreateFixture(polygonShape);
|
||||
Parts.Add(fixture);
|
||||
}
|
||||
}
|
||||
|
||||
private void PostSolve(Contact contact, ContactVelocityConstraint impulse)
|
||||
{
|
||||
if (State != BreakableBodyState.Broken)
|
||||
{
|
||||
if (Parts.Contains(contact.FixtureA) || Parts.Contains(contact.FixtureB))
|
||||
{
|
||||
float maxImpulse = 0.0f;
|
||||
int count = contact.Manifold.PointCount;
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
maxImpulse = Math.Max(maxImpulse, impulse.points[i].normalImpulse);
|
||||
}
|
||||
|
||||
if (maxImpulse > Strength)
|
||||
{
|
||||
// Flag the body for breaking.
|
||||
State = BreakableBodyState.ShouldBreak;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
switch (State)
|
||||
{
|
||||
case BreakableBodyState.Unbroken:
|
||||
CacheVelocities();
|
||||
break;
|
||||
case BreakableBodyState.ShouldBreak:
|
||||
Decompose();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cache velocities to improve movement on breakage.
|
||||
private void CacheVelocities()
|
||||
{
|
||||
//Enlarge the cache if needed
|
||||
if (Parts.Count > _angularVelocitiesCache.Length)
|
||||
{
|
||||
_velocitiesCache = new Vector2[Parts.Count];
|
||||
_angularVelocitiesCache = new float[Parts.Count];
|
||||
}
|
||||
|
||||
//Cache the linear and angular velocities.
|
||||
for (int i = 0; i < Parts.Count; i++)
|
||||
{
|
||||
_velocitiesCache[i] = Parts[i].Body.LinearVelocity;
|
||||
_angularVelocitiesCache[i] = Parts[i].Body.AngularVelocity;
|
||||
}
|
||||
}
|
||||
|
||||
private void Decompose()
|
||||
{
|
||||
if (State == BreakableBodyState.Broken)
|
||||
throw new InvalidOperationException("BreakableBody is allready broken");
|
||||
|
||||
//Unsubsribe from the PostSolve delegate
|
||||
World.ContactManager.PostSolve -= PostSolve;
|
||||
|
||||
for (int i = 0; i < Parts.Count; i++)
|
||||
{
|
||||
Fixture oldFixture = Parts[i];
|
||||
|
||||
Shape shape = oldFixture.Shape.Clone();
|
||||
object fixtureTag = oldFixture.UserData;
|
||||
|
||||
MainBody.Remove(oldFixture);
|
||||
|
||||
Body body = World.CreateBody(MainBody.Position, MainBody.Rotation, BodyType.Dynamic);
|
||||
body.UserData = MainBody.UserData;
|
||||
|
||||
Fixture newFixture = body.CreateFixture(shape);
|
||||
newFixture.UserData = fixtureTag;
|
||||
Parts[i] = newFixture;
|
||||
|
||||
body.AngularVelocity = _angularVelocitiesCache[i];
|
||||
body.LinearVelocity = _velocitiesCache[i];
|
||||
}
|
||||
|
||||
World.Remove(MainBody);
|
||||
|
||||
State = BreakableBodyState.Broken;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2017 Kastellanos Nikolaos
|
||||
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace FarseerPhysics.Common.PhysicsLogic
|
||||
{
|
||||
[Flags]
|
||||
public enum ControllerCategory
|
||||
{
|
||||
None = 0x00000000,
|
||||
Cat01 = 0x00000001,
|
||||
Cat02 = 0x00000002,
|
||||
Cat03 = 0x00000004,
|
||||
Cat04 = 0x00000008,
|
||||
Cat05 = 0x00000010,
|
||||
Cat06 = 0x00000020,
|
||||
Cat07 = 0x00000040,
|
||||
Cat08 = 0x00000080,
|
||||
Cat09 = 0x00000100,
|
||||
Cat10 = 0x00000200,
|
||||
Cat11 = 0x00000400,
|
||||
Cat12 = 0x00000800,
|
||||
Cat13 = 0x00001000,
|
||||
Cat14 = 0x00002000,
|
||||
Cat15 = 0x00004000,
|
||||
Cat16 = 0x00008000,
|
||||
Cat17 = 0x00010000,
|
||||
Cat18 = 0x00020000,
|
||||
Cat19 = 0x00040000,
|
||||
Cat20 = 0x00080000,
|
||||
Cat21 = 0x00100000,
|
||||
Cat22 = 0x00200000,
|
||||
Cat23 = 0x00400000,
|
||||
Cat24 = 0x00800000,
|
||||
Cat25 = 0x01000000,
|
||||
Cat26 = 0x02000000,
|
||||
Cat27 = 0x04000000,
|
||||
Cat28 = 0x08000000,
|
||||
Cat29 = 0x10000000,
|
||||
Cat30 = 0x20000000,
|
||||
Cat31 = 0x40000000,
|
||||
All = int.MaxValue,
|
||||
}
|
||||
|
||||
public struct ControllerFilter
|
||||
{
|
||||
public ControllerCategory ControllerCategories;
|
||||
|
||||
public ControllerFilter(ControllerCategory controllerCategory)
|
||||
{
|
||||
this.ControllerCategories = controllerCategory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ignores the controller. The controller has no effect on this body.
|
||||
/// </summary>
|
||||
/// <param name="type">The logic type.</param>
|
||||
public void IgnoreController(ControllerCategory category)
|
||||
{
|
||||
ControllerCategories &= ~category;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restore the controller. The controller affects this body.
|
||||
/// </summary>
|
||||
/// <param name="category">The logic type.</param>
|
||||
public void RestoreController(ControllerCategory category)
|
||||
{
|
||||
ControllerCategories |= category;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this body ignores the the specified controller.
|
||||
/// </summary>
|
||||
/// <param name="category">The logic type.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the body has the specified flag; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool IsControllerIgnored(ControllerCategory category)
|
||||
{
|
||||
return (ControllerCategories & category) != category;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
using FarseerPhysics.Dynamics;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using FarseerPhysics.Dynamics;
|
||||
|
||||
namespace FarseerPhysics.Common.PhysicsLogic
|
||||
{
|
||||
@@ -36,7 +41,7 @@ namespace FarseerPhysics.Common.PhysicsLogic
|
||||
/// <returns></returns>
|
||||
public virtual bool IsActiveOn(Body body)
|
||||
{
|
||||
if (body == null || !body.Enabled || body.IsStatic)
|
||||
if (body == null || !body.Enabled || body.BodyType == BodyType.Static)
|
||||
return false;
|
||||
|
||||
if (body.FixtureList == null)
|
||||
|
||||
@@ -1,66 +1,29 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using FarseerPhysics.Dynamics;
|
||||
|
||||
namespace FarseerPhysics.Common.PhysicsLogic
|
||||
{
|
||||
[Flags]
|
||||
public enum PhysicsLogicType
|
||||
{
|
||||
Explosion = (1 << 0)
|
||||
}
|
||||
|
||||
public struct PhysicsLogicFilter
|
||||
{
|
||||
public PhysicsLogicType ControllerIgnores;
|
||||
|
||||
/// <summary>
|
||||
/// Ignores the controller. The controller has no effect on this body.
|
||||
/// </summary>
|
||||
/// <param name="type">The logic type.</param>
|
||||
public void IgnorePhysicsLogic(PhysicsLogicType type)
|
||||
{
|
||||
ControllerIgnores |= type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restore the controller. The controller affects this body.
|
||||
/// </summary>
|
||||
/// <param name="type">The logic type.</param>
|
||||
public void RestorePhysicsLogic(PhysicsLogicType type)
|
||||
{
|
||||
ControllerIgnores &= ~type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this body ignores the the specified controller.
|
||||
/// </summary>
|
||||
/// <param name="type">The logic type.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the body has the specified flag; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool IsPhysicsLogicIgnored(PhysicsLogicType type)
|
||||
{
|
||||
return (ControllerIgnores & type) == type;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class PhysicsLogic : FilterData
|
||||
{
|
||||
private PhysicsLogicType _type;
|
||||
public World World;
|
||||
public ControllerCategory ControllerCategory = ControllerCategory.Cat01;
|
||||
|
||||
public World World { get; internal set; }
|
||||
|
||||
public PhysicsLogic(World world)
|
||||
{
|
||||
World = world;
|
||||
}
|
||||
public override bool IsActiveOn(Body body)
|
||||
{
|
||||
if (body.PhysicsLogicFilter.IsPhysicsLogicIgnored(_type))
|
||||
if (body.ControllerFilter.IsControllerIgnored(ControllerCategory))
|
||||
return false;
|
||||
|
||||
return base.IsActiveOn(body);
|
||||
}
|
||||
|
||||
public PhysicsLogic(World world, PhysicsLogicType type)
|
||||
{
|
||||
_type = type;
|
||||
World = world;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,15 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using FarseerPhysics.Collision;
|
||||
using FarseerPhysics.Collision.Shapes;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Common.PhysicsLogic
|
||||
{
|
||||
@@ -98,8 +103,7 @@ namespace FarseerPhysics.Common.PhysicsLogic
|
||||
private List<ShapeData> _data = new List<ShapeData>();
|
||||
private RayDataComparer _rdc;
|
||||
|
||||
public RealExplosion(World world)
|
||||
: base(world, PhysicsLogicType.Explosion)
|
||||
public RealExplosion(World world) : base(world)
|
||||
{
|
||||
_rdc = new RayDataComparer();
|
||||
_data = new List<ShapeData>();
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using FarseerPhysics.Collision;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Common.PhysicsLogic
|
||||
{
|
||||
@@ -11,8 +16,7 @@ namespace FarseerPhysics.Common.PhysicsLogic
|
||||
/// </summary>
|
||||
public sealed class SimpleExplosion : PhysicsLogic
|
||||
{
|
||||
public SimpleExplosion(World world)
|
||||
: base(world, PhysicsLogicType.Explosion)
|
||||
public SimpleExplosion(World world): base(world)
|
||||
{
|
||||
Power = 1; //linear
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using FarseerPhysics.Collision.Shapes;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using FarseerPhysics.Factories;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Common.PolygonManipulation
|
||||
@@ -191,7 +195,7 @@ namespace FarseerPhysics.Common.PolygonManipulation
|
||||
//Delete the original shape and create two new. Retain the properties of the body.
|
||||
if (first.CheckPolygon() == PolygonError.NoError)
|
||||
{
|
||||
Body firstFixture = BodyFactory.CreatePolygon(world, first, fixtures[i].Shape.Density, fixtures[i].Body.Position);
|
||||
Body firstFixture = world.CreatePolygon(first, fixtures[i].Shape.Density, fixtures[i].Body.Position);
|
||||
firstFixture.Rotation = fixtures[i].Body.Rotation;
|
||||
firstFixture.LinearVelocity = fixtures[i].Body.LinearVelocity;
|
||||
firstFixture.AngularVelocity = fixtures[i].Body.AngularVelocity;
|
||||
@@ -200,14 +204,14 @@ namespace FarseerPhysics.Common.PolygonManipulation
|
||||
|
||||
if (second.CheckPolygon() == PolygonError.NoError)
|
||||
{
|
||||
Body secondFixture = BodyFactory.CreatePolygon(world, second, fixtures[i].Shape.Density, fixtures[i].Body.Position);
|
||||
Body secondFixture = world.CreatePolygon(second, fixtures[i].Shape.Density, fixtures[i].Body.Position);
|
||||
secondFixture.Rotation = fixtures[i].Body.Rotation;
|
||||
secondFixture.LinearVelocity = fixtures[i].Body.LinearVelocity;
|
||||
secondFixture.AngularVelocity = fixtures[i].Body.AngularVelocity;
|
||||
secondFixture.BodyType = BodyType.Dynamic;
|
||||
}
|
||||
|
||||
world.RemoveBody(fixtures[i].Body);
|
||||
world.Remove(fixtures[i].Body);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/*
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* C# Version Ported by Matt Bettcher and Ian Qvist 2009-2010
|
||||
*
|
||||
* Original C++ Version Copyright (c) 2007 Eric Jordan
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
+466
-461
@@ -1,514 +1,519 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Common.PolygonManipulation
|
||||
{
|
||||
internal enum PolyClipType
|
||||
{
|
||||
Intersect,
|
||||
Union,
|
||||
Difference
|
||||
}
|
||||
|
||||
public enum PolyClipError
|
||||
{
|
||||
None,
|
||||
DegeneratedOutput,
|
||||
NonSimpleInput,
|
||||
BrokenResult
|
||||
}
|
||||
|
||||
//Clipper contributed by Helge Backhaus
|
||||
|
||||
public static class YuPengClipper
|
||||
{
|
||||
private const float ClipperEpsilonSquared = 1.192092896e-07f;
|
||||
|
||||
public static List<Vertices> Union(Vertices polygon1, Vertices polygon2, out PolyClipError error)
|
||||
internal enum PolyClipType
|
||||
{
|
||||
return Execute(polygon1, polygon2, PolyClipType.Union, out error);
|
||||
Intersect,
|
||||
Union,
|
||||
Difference
|
||||
}
|
||||
|
||||
public static List<Vertices> Difference(Vertices polygon1, Vertices polygon2, out PolyClipError error)
|
||||
public enum PolyClipError
|
||||
{
|
||||
return Execute(polygon1, polygon2, PolyClipType.Difference, out error);
|
||||
None,
|
||||
DegeneratedOutput,
|
||||
NonSimpleInput,
|
||||
BrokenResult
|
||||
}
|
||||
|
||||
public static List<Vertices> Intersect(Vertices polygon1, Vertices polygon2, out PolyClipError error)
|
||||
//Clipper contributed by Helge Backhaus
|
||||
|
||||
public static class YuPengClipper
|
||||
{
|
||||
return Execute(polygon1, polygon2, PolyClipType.Intersect, out error);
|
||||
}
|
||||
private const float ClipperEpsilonSquared = 1.192092896e-07f;
|
||||
|
||||
/// <summary>
|
||||
/// Implements "A new algorithm for Boolean operations on general polygons"
|
||||
/// available here: http://liama.ia.ac.cn/wiki/_media/user:dong:dong_cg_05.pdf
|
||||
/// Merges two polygons, a subject and a clip with the specified operation. Polygons may not be
|
||||
/// self-intersecting.
|
||||
///
|
||||
/// Warning: May yield incorrect results or even crash if polygons contain collinear points.
|
||||
/// </summary>
|
||||
/// <param name="subject">The subject polygon.</param>
|
||||
/// <param name="clip">The clip polygon, which is added,
|
||||
/// substracted or intersected with the subject</param>
|
||||
/// <param name="clipType">The operation to be performed. Either
|
||||
/// Union, Difference or Intersection.</param>
|
||||
/// <param name="error">The error generated (if any)</param>
|
||||
/// <returns>A list of closed polygons, which make up the result of the clipping operation.
|
||||
/// Outer contours are ordered counter clockwise, holes are ordered clockwise.</returns>
|
||||
private static List<Vertices> Execute(Vertices subject, Vertices clip, PolyClipType clipType, out PolyClipError error)
|
||||
{
|
||||
Debug.Assert(subject.IsSimple() && clip.IsSimple(), "Non simple input!", "Input polygons must be simple (cannot intersect themselves).");
|
||||
|
||||
// Copy polygons
|
||||
Vertices slicedSubject;
|
||||
Vertices slicedClip;
|
||||
// Calculate the intersection and touch points between
|
||||
// subject and clip and add them to both
|
||||
CalculateIntersections(subject, clip, out slicedSubject, out slicedClip);
|
||||
|
||||
// Translate polygons into upper right quadrant
|
||||
// as the algorithm depends on it
|
||||
Vector2 lbSubject = subject.GetAABB().LowerBound;
|
||||
Vector2 lbClip = clip.GetAABB().LowerBound;
|
||||
Vector2 translate;
|
||||
Vector2.Min(ref lbSubject, ref lbClip, out translate);
|
||||
translate = Vector2.One - translate;
|
||||
if (translate != Vector2.Zero)
|
||||
{
|
||||
slicedSubject.Translate(ref translate);
|
||||
slicedClip.Translate(ref translate);
|
||||
}
|
||||
|
||||
// Enforce counterclockwise contours
|
||||
slicedSubject.ForceCounterClockWise();
|
||||
slicedClip.ForceCounterClockWise();
|
||||
|
||||
List<Edge> subjectSimplices;
|
||||
List<float> subjectCoeff;
|
||||
List<Edge> clipSimplices;
|
||||
List<float> clipCoeff;
|
||||
// Build simplical chains from the polygons and calculate the
|
||||
// the corresponding coefficients
|
||||
CalculateSimplicalChain(slicedSubject, out subjectCoeff, out subjectSimplices);
|
||||
CalculateSimplicalChain(slicedClip, out clipCoeff, out clipSimplices);
|
||||
|
||||
List<Edge> resultSimplices;
|
||||
|
||||
// Determine the characteristics function for all non-original edges
|
||||
// in subject and clip simplical chain and combine the edges contributing
|
||||
// to the result, depending on the clipType
|
||||
CalculateResultChain(subjectCoeff, subjectSimplices, clipCoeff, clipSimplices, clipType,
|
||||
out resultSimplices);
|
||||
|
||||
List<Vertices> result;
|
||||
// Convert result chain back to polygon(s)
|
||||
error = BuildPolygonsFromChain(resultSimplices, out result);
|
||||
|
||||
// Reverse the polygon translation from the beginning
|
||||
// and remove collinear points from output
|
||||
translate *= -1f;
|
||||
for (int i = 0; i < result.Count; ++i)
|
||||
{
|
||||
result[i].Translate(ref translate);
|
||||
SimplifyTools.CollinearSimplify(result[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates all intersections between two polygons.
|
||||
/// </summary>
|
||||
/// <param name="polygon1">The first polygon.</param>
|
||||
/// <param name="polygon2">The second polygon.</param>
|
||||
/// <param name="slicedPoly1">Returns the first polygon with added intersection points.</param>
|
||||
/// <param name="slicedPoly2">Returns the second polygon with added intersection points.</param>
|
||||
private static void CalculateIntersections(Vertices polygon1, Vertices polygon2,
|
||||
out Vertices slicedPoly1, out Vertices slicedPoly2)
|
||||
{
|
||||
slicedPoly1 = new Vertices(polygon1);
|
||||
slicedPoly2 = new Vertices(polygon2);
|
||||
|
||||
// Iterate through polygon1's edges
|
||||
for (int i = 0; i < polygon1.Count; i++)
|
||||
{
|
||||
// Get edge vertices
|
||||
Vector2 a = polygon1[i];
|
||||
Vector2 b = polygon1[polygon1.NextIndex(i)];
|
||||
|
||||
// Get intersections between this edge and polygon2
|
||||
for (int j = 0; j < polygon2.Count; j++)
|
||||
public static List<Vertices> Union(Vertices polygon1, Vertices polygon2, out PolyClipError error)
|
||||
{
|
||||
Vector2 c = polygon2[j];
|
||||
Vector2 d = polygon2[polygon2.NextIndex(j)];
|
||||
return Execute(polygon1, polygon2, PolyClipType.Union, out error);
|
||||
}
|
||||
|
||||
Vector2 intersectionPoint;
|
||||
// Check if the edges intersect
|
||||
if (LineTools.LineIntersect(a, b, c, d, out intersectionPoint))
|
||||
{
|
||||
// calculate alpha values for sorting multiple intersections points on a edge
|
||||
float alpha;
|
||||
// Insert intersection point into first polygon
|
||||
alpha = GetAlpha(a, b, intersectionPoint);
|
||||
if (alpha > 0f && alpha < 1f)
|
||||
public static List<Vertices> Difference(Vertices polygon1, Vertices polygon2, out PolyClipError error)
|
||||
{
|
||||
return Execute(polygon1, polygon2, PolyClipType.Difference, out error);
|
||||
}
|
||||
|
||||
public static List<Vertices> Intersect(Vertices polygon1, Vertices polygon2, out PolyClipError error)
|
||||
{
|
||||
return Execute(polygon1, polygon2, PolyClipType.Intersect, out error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements "A new algorithm for Boolean operations on general polygons"
|
||||
/// available here: http://liama.ia.ac.cn/wiki/_media/user:dong:dong_cg_05.pdf
|
||||
/// Merges two polygons, a subject and a clip with the specified operation. Polygons may not be
|
||||
/// self-intersecting.
|
||||
///
|
||||
/// Warning: May yield incorrect results or even crash if polygons contain collinear points.
|
||||
/// </summary>
|
||||
/// <param name="subject">The subject polygon.</param>
|
||||
/// <param name="clip">The clip polygon, which is added,
|
||||
/// substracted or intersected with the subject</param>
|
||||
/// <param name="clipType">The operation to be performed. Either
|
||||
/// Union, Difference or Intersection.</param>
|
||||
/// <param name="error">The error generated (if any)</param>
|
||||
/// <returns>A list of closed polygons, which make up the result of the clipping operation.
|
||||
/// Outer contours are ordered counter clockwise, holes are ordered clockwise.</returns>
|
||||
private static List<Vertices> Execute(Vertices subject, Vertices clip, PolyClipType clipType, out PolyClipError error)
|
||||
{
|
||||
Debug.Assert(subject.IsSimple() && clip.IsSimple(), "Non simple input! Input polygons must be simple (cannot intersect themselves).");
|
||||
|
||||
// Copy polygons
|
||||
Vertices slicedSubject;
|
||||
Vertices slicedClip;
|
||||
// Calculate the intersection and touch points between
|
||||
// subject and clip and add them to both
|
||||
CalculateIntersections(subject, clip, out slicedSubject, out slicedClip);
|
||||
|
||||
// Translate polygons into upper right quadrant
|
||||
// as the algorithm depends on it
|
||||
Vector2 lbSubject = subject.GetAABB().LowerBound;
|
||||
Vector2 lbClip = clip.GetAABB().LowerBound;
|
||||
Vector2 translate;
|
||||
Vector2.Min(ref lbSubject, ref lbClip, out translate);
|
||||
translate = Vector2.One - translate;
|
||||
if (translate != Vector2.Zero)
|
||||
{
|
||||
int index = slicedPoly1.IndexOf(a) + 1;
|
||||
while (index < slicedPoly1.Count &&
|
||||
GetAlpha(a, b, slicedPoly1[index]) <= alpha)
|
||||
{
|
||||
++index;
|
||||
}
|
||||
slicedPoly1.Insert(index, intersectionPoint);
|
||||
slicedSubject.Translate(ref translate);
|
||||
slicedClip.Translate(ref translate);
|
||||
}
|
||||
// Insert intersection point into second polygon
|
||||
alpha = GetAlpha(c, d, intersectionPoint);
|
||||
if (alpha > 0f && alpha < 1f)
|
||||
|
||||
// Enforce counterclockwise contours
|
||||
slicedSubject.ForceCounterClockWise();
|
||||
slicedClip.ForceCounterClockWise();
|
||||
|
||||
List<Edge> subjectSimplices;
|
||||
List<float> subjectCoeff;
|
||||
List<Edge> clipSimplices;
|
||||
List<float> clipCoeff;
|
||||
// Build simplical chains from the polygons and calculate the
|
||||
// the corresponding coefficients
|
||||
CalculateSimplicalChain(slicedSubject, out subjectCoeff, out subjectSimplices);
|
||||
CalculateSimplicalChain(slicedClip, out clipCoeff, out clipSimplices);
|
||||
|
||||
List<Edge> resultSimplices;
|
||||
|
||||
// Determine the characteristics function for all non-original edges
|
||||
// in subject and clip simplical chain and combine the edges contributing
|
||||
// to the result, depending on the clipType
|
||||
CalculateResultChain(subjectCoeff, subjectSimplices, clipCoeff, clipSimplices, clipType,
|
||||
out resultSimplices);
|
||||
|
||||
List<Vertices> result;
|
||||
// Convert result chain back to polygon(s)
|
||||
error = BuildPolygonsFromChain(resultSimplices, out result);
|
||||
|
||||
// Reverse the polygon translation from the beginning
|
||||
// and remove collinear points from output
|
||||
translate *= -1f;
|
||||
for (int i = 0; i < result.Count; ++i)
|
||||
{
|
||||
int index = slicedPoly2.IndexOf(c) + 1;
|
||||
while (index < slicedPoly2.Count &&
|
||||
GetAlpha(c, d, slicedPoly2[index]) <= alpha)
|
||||
{
|
||||
++index;
|
||||
}
|
||||
slicedPoly2.Insert(index, intersectionPoint);
|
||||
result[i].Translate(ref translate);
|
||||
SimplifyTools.CollinearSimplify(result[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// Check for very small edges
|
||||
for (int i = 0; i < slicedPoly1.Count; ++i)
|
||||
{
|
||||
int iNext = slicedPoly1.NextIndex(i);
|
||||
//If they are closer than the distance remove vertex
|
||||
if ((slicedPoly1[iNext] - slicedPoly1[i]).LengthSquared() <= ClipperEpsilonSquared)
|
||||
{
|
||||
slicedPoly1.RemoveAt(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < slicedPoly2.Count; ++i)
|
||||
{
|
||||
int iNext = slicedPoly2.NextIndex(i);
|
||||
//If they are closer than the distance remove vertex
|
||||
if ((slicedPoly2[iNext] - slicedPoly2[i]).LengthSquared() <= ClipperEpsilonSquared)
|
||||
{
|
||||
slicedPoly2.RemoveAt(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the simplical chain corresponding to the input polygon.
|
||||
/// </summary>
|
||||
/// <remarks>Used by method <c>Execute()</c>.</remarks>
|
||||
private static void CalculateSimplicalChain(Vertices poly, out List<float> coeff,
|
||||
out List<Edge> simplicies)
|
||||
{
|
||||
simplicies = new List<Edge>();
|
||||
coeff = new List<float>();
|
||||
for (int i = 0; i < poly.Count; ++i)
|
||||
{
|
||||
simplicies.Add(new Edge(poly[i], poly[poly.NextIndex(i)]));
|
||||
coeff.Add(CalculateSimplexCoefficient(Vector2.Zero, poly[i], poly[poly.NextIndex(i)]));
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Calculates all intersections between two polygons.
|
||||
/// </summary>
|
||||
/// <param name="polygon1">The first polygon.</param>
|
||||
/// <param name="polygon2">The second polygon.</param>
|
||||
/// <param name="slicedPoly1">Returns the first polygon with added intersection points.</param>
|
||||
/// <param name="slicedPoly2">Returns the second polygon with added intersection points.</param>
|
||||
private static void CalculateIntersections(Vertices polygon1, Vertices polygon2,
|
||||
out Vertices slicedPoly1, out Vertices slicedPoly2)
|
||||
{
|
||||
slicedPoly1 = new Vertices(polygon1);
|
||||
slicedPoly2 = new Vertices(polygon2);
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the characteristics function for all edges of
|
||||
/// the given simplical chains and builds the result chain.
|
||||
/// </summary>
|
||||
/// <remarks>Used by method <c>Execute()</c>.</remarks>
|
||||
private static void CalculateResultChain(List<float> poly1Coeff, List<Edge> poly1Simplicies,
|
||||
List<float> poly2Coeff, List<Edge> poly2Simplicies,
|
||||
PolyClipType clipType, out List<Edge> resultSimplices)
|
||||
{
|
||||
resultSimplices = new List<Edge>();
|
||||
|
||||
for (int i = 0; i < poly1Simplicies.Count; ++i)
|
||||
{
|
||||
float edgeCharacter = 0;
|
||||
if (poly2Simplicies.Contains(poly1Simplicies[i]))
|
||||
{
|
||||
edgeCharacter = 1f;
|
||||
}
|
||||
else if (poly2Simplicies.Contains(-poly1Simplicies[i]) && clipType == PolyClipType.Union)
|
||||
{
|
||||
edgeCharacter = 1f;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < poly2Simplicies.Count; ++j)
|
||||
{
|
||||
if (!poly2Simplicies.Contains(-poly1Simplicies[i]))
|
||||
// Iterate through polygon1's edges
|
||||
for (int i = 0; i < polygon1.Count; i++)
|
||||
{
|
||||
edgeCharacter += CalculateBeta(poly1Simplicies[i].GetCenter(),
|
||||
poly2Simplicies[j], poly2Coeff[j]);
|
||||
// Get edge vertices
|
||||
Vector2 a = polygon1[i];
|
||||
Vector2 b = polygon1[polygon1.NextIndex(i)];
|
||||
|
||||
// Get intersections between this edge and polygon2
|
||||
for (int j = 0; j < polygon2.Count; j++)
|
||||
{
|
||||
Vector2 c = polygon2[j];
|
||||
Vector2 d = polygon2[polygon2.NextIndex(j)];
|
||||
|
||||
Vector2 intersectionPoint;
|
||||
// Check if the edges intersect
|
||||
if (LineTools.LineIntersect(a, b, c, d, out intersectionPoint))
|
||||
{
|
||||
// calculate alpha values for sorting multiple intersections points on a edge
|
||||
float alpha;
|
||||
// Insert intersection point into first polygon
|
||||
alpha = GetAlpha(a, b, intersectionPoint);
|
||||
if (alpha > 0f && alpha < 1f)
|
||||
{
|
||||
int index = slicedPoly1.IndexOf(a) + 1;
|
||||
while (index < slicedPoly1.Count &&
|
||||
GetAlpha(a, b, slicedPoly1[index]) <= alpha)
|
||||
{
|
||||
++index;
|
||||
}
|
||||
slicedPoly1.Insert(index, intersectionPoint);
|
||||
}
|
||||
// Insert intersection point into second polygon
|
||||
alpha = GetAlpha(c, d, intersectionPoint);
|
||||
if (alpha > 0f && alpha < 1f)
|
||||
{
|
||||
int index = slicedPoly2.IndexOf(c) + 1;
|
||||
while (index < slicedPoly2.Count &&
|
||||
GetAlpha(c, d, slicedPoly2[index]) <= alpha)
|
||||
{
|
||||
++index;
|
||||
}
|
||||
slicedPoly2.Insert(index, intersectionPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check for very small edges
|
||||
for (int i = 0; i < slicedPoly1.Count; ++i)
|
||||
{
|
||||
int iNext = slicedPoly1.NextIndex(i);
|
||||
//If they are closer than the distance remove vertex
|
||||
if ((slicedPoly1[iNext] - slicedPoly1[i]).LengthSquared() <= ClipperEpsilonSquared)
|
||||
{
|
||||
slicedPoly1.RemoveAt(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < slicedPoly2.Count; ++i)
|
||||
{
|
||||
int iNext = slicedPoly2.NextIndex(i);
|
||||
//If they are closer than the distance remove vertex
|
||||
if ((slicedPoly2[iNext] - slicedPoly2[i]).LengthSquared() <= ClipperEpsilonSquared)
|
||||
{
|
||||
slicedPoly2.RemoveAt(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clipType == PolyClipType.Intersect)
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the simplical chain corresponding to the input polygon.
|
||||
/// </summary>
|
||||
/// <remarks>Used by method <c>Execute()</c>.</remarks>
|
||||
private static void CalculateSimplicalChain(Vertices poly, out List<float> coeff,
|
||||
out List<Edge> simplicies)
|
||||
{
|
||||
if (edgeCharacter == 1f)
|
||||
{
|
||||
resultSimplices.Add(poly1Simplicies[i]);
|
||||
}
|
||||
simplicies = new List<Edge>();
|
||||
coeff = new List<float>();
|
||||
for (int i = 0; i < poly.Count; ++i)
|
||||
{
|
||||
simplicies.Add(new Edge(poly[i], poly[poly.NextIndex(i)]));
|
||||
coeff.Add(CalculateSimplexCoefficient(Vector2.Zero, poly[i], poly[poly.NextIndex(i)]));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the characteristics function for all edges of
|
||||
/// the given simplical chains and builds the result chain.
|
||||
/// </summary>
|
||||
/// <remarks>Used by method <c>Execute()</c>.</remarks>
|
||||
private static void CalculateResultChain(List<float> poly1Coeff, List<Edge> poly1Simplicies,
|
||||
List<float> poly2Coeff, List<Edge> poly2Simplicies,
|
||||
PolyClipType clipType, out List<Edge> resultSimplices)
|
||||
{
|
||||
if (edgeCharacter == 0f)
|
||||
{
|
||||
resultSimplices.Add(poly1Simplicies[i]);
|
||||
}
|
||||
resultSimplices = new List<Edge>();
|
||||
|
||||
for (int i = 0; i < poly1Simplicies.Count; ++i)
|
||||
{
|
||||
float edgeCharacter = 0;
|
||||
if (poly2Simplicies.Contains(poly1Simplicies[i]))
|
||||
{
|
||||
edgeCharacter = 1f;
|
||||
}
|
||||
else if (poly2Simplicies.Contains(-poly1Simplicies[i]) && clipType == PolyClipType.Union)
|
||||
{
|
||||
edgeCharacter = 1f;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < poly2Simplicies.Count; ++j)
|
||||
{
|
||||
if (!poly2Simplicies.Contains(-poly1Simplicies[i]))
|
||||
{
|
||||
edgeCharacter += CalculateBeta(poly1Simplicies[i].GetCenter(),
|
||||
poly2Simplicies[j], poly2Coeff[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clipType == PolyClipType.Intersect)
|
||||
{
|
||||
if (edgeCharacter == 1f)
|
||||
{
|
||||
resultSimplices.Add(poly1Simplicies[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (edgeCharacter == 0f)
|
||||
{
|
||||
resultSimplices.Add(poly1Simplicies[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < poly2Simplicies.Count; ++i)
|
||||
{
|
||||
float edgeCharacter = 0f;
|
||||
if (!resultSimplices.Contains(poly2Simplicies[i]) &&
|
||||
!resultSimplices.Contains(-poly2Simplicies[i]))
|
||||
{
|
||||
if (poly1Simplicies.Contains(-poly2Simplicies[i]) && clipType == PolyClipType.Union)
|
||||
{
|
||||
edgeCharacter = 1f;
|
||||
}
|
||||
else
|
||||
{
|
||||
edgeCharacter = 0f;
|
||||
for (int j = 0; j < poly1Simplicies.Count; ++j)
|
||||
{
|
||||
if (!poly1Simplicies.Contains(poly2Simplicies[i]) && !poly1Simplicies.Contains(-poly2Simplicies[i]))
|
||||
{
|
||||
edgeCharacter += CalculateBeta(poly2Simplicies[i].GetCenter(),
|
||||
poly1Simplicies[j], poly1Coeff[j]);
|
||||
}
|
||||
}
|
||||
if (clipType == PolyClipType.Intersect || clipType == PolyClipType.Difference)
|
||||
{
|
||||
if (edgeCharacter == 1f)
|
||||
{
|
||||
resultSimplices.Add(-poly2Simplicies[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (edgeCharacter == 0f)
|
||||
{
|
||||
resultSimplices.Add(poly2Simplicies[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < poly2Simplicies.Count; ++i)
|
||||
{
|
||||
float edgeCharacter = 0f;
|
||||
if (!resultSimplices.Contains(poly2Simplicies[i]) &&
|
||||
!resultSimplices.Contains(-poly2Simplicies[i]))
|
||||
|
||||
/// <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)
|
||||
{
|
||||
if (poly1Simplicies.Contains(-poly2Simplicies[i]) && clipType == PolyClipType.Union)
|
||||
{
|
||||
edgeCharacter = 1f;
|
||||
}
|
||||
else
|
||||
{
|
||||
edgeCharacter = 0f;
|
||||
for (int j = 0; j < poly1Simplicies.Count; ++j)
|
||||
result = new List<Vertices>();
|
||||
PolyClipError errVal = PolyClipError.None;
|
||||
|
||||
while (simplicies.Count > 0)
|
||||
{
|
||||
if (!poly1Simplicies.Contains(poly2Simplicies[i]) && !poly1Simplicies.Contains(-poly2Simplicies[i]))
|
||||
{
|
||||
edgeCharacter += CalculateBeta(poly2Simplicies[i].GetCenter(),
|
||||
poly1Simplicies[j], poly1Coeff[j]);
|
||||
}
|
||||
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);
|
||||
}
|
||||
if (clipType == PolyClipType.Intersect || clipType == PolyClipType.Difference)
|
||||
{
|
||||
if (edgeCharacter == 1f)
|
||||
{
|
||||
resultSimplices.Add(-poly2Simplicies[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (edgeCharacter == 0f)
|
||||
{
|
||||
resultSimplices.Add(poly2Simplicies[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return errVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <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)
|
||||
/// <summary>
|
||||
/// Needed to calculate the characteristics function of a simplex.
|
||||
/// </summary>
|
||||
/// <remarks>Used by method <c>CalculateEdgeCharacter()</c>.</remarks>
|
||||
private static float CalculateBeta(Vector2 point, Edge e, float coefficient)
|
||||
{
|
||||
if (VectorEqual(output[output.Count - 1], simplicies[index].EdgeStart))
|
||||
{
|
||||
if (VectorEqual(simplicies[index].EdgeEnd, output[0]))
|
||||
float result = 0f;
|
||||
if (PointInSimplex(point, e))
|
||||
{
|
||||
closed = true;
|
||||
result = coefficient;
|
||||
}
|
||||
else
|
||||
if (PointOnLineSegment(Vector2.Zero, e.EdgeStart, point) ||
|
||||
PointOnLineSegment(Vector2.Zero, e.EdgeEnd, point))
|
||||
{
|
||||
output.Add(simplicies[index].EdgeEnd);
|
||||
result = .5f * coefficient;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (output.Count < 3)
|
||||
|
||||
/// <summary>
|
||||
/// Needed for sorting multiple intersections points on the same edge.
|
||||
/// </summary>
|
||||
/// <remarks>Used by method <c>CalculateIntersections()</c>.</remarks>
|
||||
private static float GetAlpha(Vector2 start, Vector2 end, Vector2 point)
|
||||
{
|
||||
errVal = PolyClipError.DegeneratedOutput;
|
||||
Debug.WriteLine("Degenerated output polygon produced (vertices < 3).");
|
||||
return (point - start).LengthSquared() / (end - start).LengthSquared();
|
||||
}
|
||||
result.Add(output);
|
||||
}
|
||||
return errVal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Needed to calculate the characteristics function of a simplex.
|
||||
/// </summary>
|
||||
/// <remarks>Used by method <c>CalculateEdgeCharacter()</c>.</remarks>
|
||||
private static float CalculateBeta(Vector2 point, Edge e, float coefficient)
|
||||
{
|
||||
float result = 0f;
|
||||
if (PointInSimplex(point, e))
|
||||
{
|
||||
result = coefficient;
|
||||
}
|
||||
if (PointOnLineSegment(Vector2.Zero, e.EdgeStart, point) ||
|
||||
PointOnLineSegment(Vector2.Zero, e.EdgeEnd, point))
|
||||
{
|
||||
result = .5f * coefficient;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Needed for sorting multiple intersections points on the same edge.
|
||||
/// </summary>
|
||||
/// <remarks>Used by method <c>CalculateIntersections()</c>.</remarks>
|
||||
private static float GetAlpha(Vector2 start, Vector2 end, Vector2 point)
|
||||
{
|
||||
return (point - start).LengthSquared() / (end - start).LengthSquared();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the coefficient of a simplex.
|
||||
/// </summary>
|
||||
/// <remarks>Used by method <c>CalculateSimplicalChain()</c>.</remarks>
|
||||
private static float CalculateSimplexCoefficient(Vector2 a, Vector2 b, Vector2 c)
|
||||
{
|
||||
float isLeft = MathUtils.Area(ref a, ref b, ref c);
|
||||
if (isLeft < 0f)
|
||||
{
|
||||
return -1f;
|
||||
}
|
||||
|
||||
if (isLeft > 0f)
|
||||
{
|
||||
return 1f;
|
||||
}
|
||||
|
||||
return 0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Winding number test for a point in a simplex.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to be tested.</param>
|
||||
/// <param name="edge">The edge that the point is tested against.</param>
|
||||
/// <returns>False if the winding number is even and the point is outside
|
||||
/// the simplex and True otherwise.</returns>
|
||||
private static bool PointInSimplex(Vector2 point, Edge edge)
|
||||
{
|
||||
Vertices polygon = new Vertices();
|
||||
polygon.Add(Vector2.Zero);
|
||||
polygon.Add(edge.EdgeStart);
|
||||
polygon.Add(edge.EdgeEnd);
|
||||
return (polygon.PointInPolygon(ref point) == 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests if a point lies on a line segment.
|
||||
/// </summary>
|
||||
/// <remarks>Used by method <c>CalculateBeta()</c>.</remarks>
|
||||
private static bool PointOnLineSegment(Vector2 start, Vector2 end, Vector2 point)
|
||||
{
|
||||
Vector2 segment = end - start;
|
||||
return MathUtils.Area(ref start, ref end, ref point) == 0f &&
|
||||
Vector2.Dot(point - start, segment) >= 0f &&
|
||||
Vector2.Dot(point - end, segment) <= 0f;
|
||||
}
|
||||
|
||||
private static bool VectorEqual(Vector2 vec1, Vector2 vec2)
|
||||
{
|
||||
return (vec2 - vec1).LengthSquared() <= ClipperEpsilonSquared;
|
||||
}
|
||||
|
||||
#region Nested type: Edge
|
||||
|
||||
/// <summary>Specifies an Edge. Edges are used to represent simplicies in simplical chains</summary>
|
||||
private sealed class Edge
|
||||
{
|
||||
public Edge(Vector2 edgeStart, Vector2 edgeEnd)
|
||||
{
|
||||
EdgeStart = edgeStart;
|
||||
EdgeEnd = edgeEnd;
|
||||
}
|
||||
|
||||
public Vector2 EdgeStart { get; private set; }
|
||||
public Vector2 EdgeEnd { get; private set; }
|
||||
|
||||
public Vector2 GetCenter()
|
||||
{
|
||||
return (EdgeStart + EdgeEnd) / 2f;
|
||||
}
|
||||
|
||||
public static Edge operator -(Edge e)
|
||||
{
|
||||
return new Edge(e.EdgeEnd, e.EdgeStart);
|
||||
}
|
||||
|
||||
public override bool Equals(Object obj)
|
||||
{
|
||||
// If parameter is null return false.
|
||||
if (obj == null)
|
||||
/// <summary>
|
||||
/// Returns the coefficient of a simplex.
|
||||
/// </summary>
|
||||
/// <remarks>Used by method <c>CalculateSimplicalChain()</c>.</remarks>
|
||||
private static float CalculateSimplexCoefficient(Vector2 a, Vector2 b, Vector2 c)
|
||||
{
|
||||
return false;
|
||||
float isLeft = MathUtils.Area(ref a, ref b, ref c);
|
||||
if (isLeft < 0f)
|
||||
{
|
||||
return -1f;
|
||||
}
|
||||
|
||||
if (isLeft > 0f)
|
||||
{
|
||||
return 1f;
|
||||
}
|
||||
|
||||
return 0f;
|
||||
}
|
||||
|
||||
// If parameter cannot be cast to Point return false.
|
||||
return Equals(obj as Edge);
|
||||
}
|
||||
|
||||
public bool Equals(Edge e)
|
||||
{
|
||||
// If parameter is null return false:
|
||||
if (e == null)
|
||||
/// <summary>
|
||||
/// Winding number test for a point in a simplex.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to be tested.</param>
|
||||
/// <param name="edge">The edge that the point is tested against.</param>
|
||||
/// <returns>False if the winding number is even and the point is outside
|
||||
/// the simplex and True otherwise.</returns>
|
||||
private static bool PointInSimplex(Vector2 point, Edge edge)
|
||||
{
|
||||
return false;
|
||||
Vertices polygon = new Vertices();
|
||||
polygon.Add(Vector2.Zero);
|
||||
polygon.Add(edge.EdgeStart);
|
||||
polygon.Add(edge.EdgeEnd);
|
||||
return (polygon.PointInPolygon(ref point) == 1);
|
||||
}
|
||||
|
||||
// Return true if the fields match
|
||||
return VectorEqual(EdgeStart, e.EdgeStart) && VectorEqual(EdgeEnd, e.EdgeEnd);
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests if a point lies on a line segment.
|
||||
/// </summary>
|
||||
/// <remarks>Used by method <c>CalculateBeta()</c>.</remarks>
|
||||
private static bool PointOnLineSegment(Vector2 start, Vector2 end, Vector2 point)
|
||||
{
|
||||
Vector2 segment = end - start;
|
||||
return MathUtils.Area(ref start, ref end, ref point) == 0f &&
|
||||
Vector2.Dot(point - start, segment) >= 0f &&
|
||||
Vector2.Dot(point - end, segment) <= 0f;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return EdgeStart.GetHashCode() ^ EdgeEnd.GetHashCode();
|
||||
}
|
||||
private static bool VectorEqual(Vector2 vec1, Vector2 vec2)
|
||||
{
|
||||
return (vec2 - vec1).LengthSquared() <= ClipperEpsilonSquared;
|
||||
}
|
||||
|
||||
#region Nested type: Edge
|
||||
|
||||
/// <summary>Specifies an Edge. Edges are used to represent simplicies in simplical chains</summary>
|
||||
private sealed class Edge
|
||||
{
|
||||
public Edge(Vector2 edgeStart, Vector2 edgeEnd)
|
||||
{
|
||||
EdgeStart = edgeStart;
|
||||
EdgeEnd = edgeEnd;
|
||||
}
|
||||
|
||||
public Vector2 EdgeStart { get; private set; }
|
||||
public Vector2 EdgeEnd { get; private set; }
|
||||
|
||||
public Vector2 GetCenter()
|
||||
{
|
||||
return (EdgeStart + EdgeEnd) / 2f;
|
||||
}
|
||||
|
||||
public static Edge operator -(Edge e)
|
||||
{
|
||||
return new Edge(e.EdgeEnd, e.EdgeStart);
|
||||
}
|
||||
|
||||
public override bool Equals(Object obj)
|
||||
{
|
||||
// If parameter is null return false.
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If parameter cannot be cast to Point return false.
|
||||
return Equals(obj as Edge);
|
||||
}
|
||||
|
||||
public bool Equals(Edge e)
|
||||
{
|
||||
// If parameter is null return false:
|
||||
if (e == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return true if the fields match
|
||||
return VectorEqual(EdgeStart, e.EdgeStart) && VectorEqual(EdgeEnd, e.EdgeEnd);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return EdgeStart.GetHashCode() ^ EdgeEnd.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,13 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using FarseerPhysics.Common.TextureTools;
|
||||
using FarseerPhysics.Common.Maths;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Common
|
||||
@@ -35,14 +41,12 @@ namespace FarseerPhysics.Common
|
||||
{
|
||||
Vertices vertices = CreateRectangle(hx, hy);
|
||||
|
||||
Transform xf = new Transform();
|
||||
xf.p = center;
|
||||
xf.q.Set(angle);
|
||||
Transform xf = new Transform(center, angle);
|
||||
|
||||
// Transform vertices
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
vertices[i] = MathUtils.Mul(ref xf, vertices[i]);
|
||||
vertices[i] = Transform.Multiply(vertices[i], ref xf);
|
||||
}
|
||||
|
||||
return vertices;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -18,28 +23,22 @@ namespace FarseerPhysics.Common
|
||||
public static class WorldSerializer
|
||||
{
|
||||
/// <summary>
|
||||
/// Serialize the world to an XML file
|
||||
/// Serialize the world to a stream in XML format
|
||||
/// </summary>
|
||||
/// <param name="world"></param>
|
||||
/// <param name="filename"></param>
|
||||
public static void Serialize(World world, string filename)
|
||||
/// <param name="stream"></param>
|
||||
public static void Serialize(World world, Stream stream)
|
||||
{
|
||||
using (FileStream fs = new FileStream(filename, FileMode.Create))
|
||||
{
|
||||
WorldXmlSerializer.Serialize(world, fs);
|
||||
}
|
||||
WorldXmlSerializer.Serialize(world, stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserialize the world from an XML file
|
||||
/// Deserialize the world from a stream XML
|
||||
/// </summary>
|
||||
/// <param name="filename"></param>
|
||||
public static World Deserialize(string filename)
|
||||
/// <param name="stream"></param>
|
||||
public static World Deserialize(Stream stream)
|
||||
{
|
||||
using (FileStream fs = new FileStream(filename, FileMode.Open))
|
||||
{
|
||||
return WorldXmlDeserializer.Deserialize(fs);
|
||||
}
|
||||
return WorldXmlDeserializer.Deserialize(stream);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +50,7 @@ namespace FarseerPhysics.Common
|
||||
{
|
||||
_writer.WriteStartElement("Shape");
|
||||
_writer.WriteAttributeString("Type", shape.ShapeType.ToString());
|
||||
_writer.WriteAttributeString("Density", shape.Density.ToString());
|
||||
_writer.WriteAttributeString("Density", FloatToString(shape.Density));
|
||||
|
||||
switch (shape.ShapeType)
|
||||
{
|
||||
@@ -59,7 +58,7 @@ namespace FarseerPhysics.Common
|
||||
{
|
||||
CircleShape circle = (CircleShape)shape;
|
||||
|
||||
_writer.WriteElementString("Radius", circle.Radius.ToString());
|
||||
WriteElement("Radius", circle.Radius);
|
||||
|
||||
WriteElement("Position", circle.Position);
|
||||
}
|
||||
@@ -103,51 +102,50 @@ namespace FarseerPhysics.Common
|
||||
_writer.WriteEndElement();
|
||||
}
|
||||
|
||||
private static void SerializeFixture(Fixture fixture)
|
||||
private static void SerializeFixture(List<Fixture> fixtures, Fixture fixture)
|
||||
{
|
||||
_writer.WriteStartElement("Fixture");
|
||||
_writer.WriteAttributeString("Id", fixture.FixtureId.ToString());
|
||||
_writer.WriteAttributeString("Id", fixtures.IndexOf(fixture).ToString());
|
||||
|
||||
_writer.WriteStartElement("FilterData");
|
||||
_writer.WriteElementString("CategoryBits", ((int)fixture.CollisionCategories).ToString());
|
||||
_writer.WriteElementString("MaskBits", ((int)fixture.CollidesWith).ToString());
|
||||
_writer.WriteElementString("GroupIndex", fixture.CollisionGroup.ToString());
|
||||
_writer.WriteElementString("CollisionIgnores", Join("|", fixture._collisionIgnores));
|
||||
_writer.WriteEndElement();
|
||||
|
||||
_writer.WriteElementString("Friction", fixture.Friction.ToString());
|
||||
WriteElement("Friction", fixture.Friction);
|
||||
_writer.WriteElementString("IsSensor", fixture.IsSensor.ToString());
|
||||
_writer.WriteElementString("Restitution", fixture.Restitution.ToString());
|
||||
WriteElement("Restitution", fixture.Restitution);
|
||||
|
||||
if (fixture.UserData != null)
|
||||
{
|
||||
_writer.WriteStartElement("UserData");
|
||||
_writer.WriteStartElement("Tag");
|
||||
WriteDynamicType(fixture.UserData.GetType(), fixture.UserData);
|
||||
_writer.WriteEndElement();
|
||||
}
|
||||
|
||||
_writer.WriteEndElement();
|
||||
}
|
||||
|
||||
|
||||
private static void SerializeBody(List<Fixture> fixtures, List<Shape> shapes, Body body)
|
||||
{
|
||||
_writer.WriteStartElement("Body");
|
||||
_writer.WriteAttributeString("Type", body.BodyType.ToString());
|
||||
_writer.WriteElementString("Active", body.Enabled.ToString());
|
||||
_writer.WriteElementString("AllowSleep", body.SleepingAllowed.ToString());
|
||||
_writer.WriteElementString("Angle", body.Rotation.ToString());
|
||||
_writer.WriteElementString("AngularDamping", body.AngularDamping.ToString());
|
||||
_writer.WriteElementString("AngularVelocity", body.AngularVelocity.ToString());
|
||||
WriteElement("Angle", body.Rotation);
|
||||
WriteElement("AngularDamping", body.AngularDamping);
|
||||
WriteElement("AngularVelocity", body.AngularVelocity);
|
||||
_writer.WriteElementString("Awake", body.Awake.ToString());
|
||||
_writer.WriteElementString("Bullet", body.IsBullet.ToString());
|
||||
_writer.WriteElementString("FixedRotation", body.FixedRotation.ToString());
|
||||
_writer.WriteElementString("LinearDamping", body.LinearDamping.ToString());
|
||||
WriteElement("LinearDamping", body.LinearDamping);
|
||||
WriteElement("LinearVelocity", body.LinearVelocity);
|
||||
WriteElement("Position", body.Position);
|
||||
|
||||
if (body.UserData != null)
|
||||
{
|
||||
_writer.WriteStartElement("UserData");
|
||||
_writer.WriteStartElement("Tag");
|
||||
WriteDynamicType(body.UserData.GetType(), body.UserData);
|
||||
_writer.WriteEndElement();
|
||||
}
|
||||
@@ -156,8 +154,8 @@ namespace FarseerPhysics.Common
|
||||
for (int i = 0; i < body.FixtureList.Count; i++)
|
||||
{
|
||||
_writer.WriteStartElement("Pair");
|
||||
_writer.WriteAttributeString("FixtureId", FindIndex(fixtures, body.FixtureList[i]).ToString());
|
||||
_writer.WriteAttributeString("ShapeId", FindIndex(shapes, body.FixtureList[i].Shape).ToString());
|
||||
_writer.WriteAttributeString("FixtureId", fixtures.IndexOf(body.FixtureList[i]).ToString());
|
||||
_writer.WriteAttributeString("ShapeId", shapes.IndexOf(body.FixtureList[i].Shape).ToString());
|
||||
_writer.WriteEndElement();
|
||||
}
|
||||
|
||||
@@ -170,17 +168,17 @@ namespace FarseerPhysics.Common
|
||||
_writer.WriteStartElement("Joint");
|
||||
_writer.WriteAttributeString("Type", joint.JointType.ToString());
|
||||
|
||||
WriteElement("BodyA", FindIndex(bodies, joint.BodyA));
|
||||
WriteElement("BodyB", FindIndex(bodies, joint.BodyB));
|
||||
WriteElement("BodyA", bodies.IndexOf(joint.BodyA));
|
||||
WriteElement("BodyB", bodies.IndexOf(joint.BodyB));
|
||||
|
||||
WriteElement("CollideConnected", joint.CollideConnected);
|
||||
|
||||
WriteElement("Breakpoint", joint.Breakpoint);
|
||||
|
||||
if (joint.UserData != null)
|
||||
if (joint.Tag != null)
|
||||
{
|
||||
_writer.WriteStartElement("UserData");
|
||||
WriteDynamicType(joint.UserData.GetType(), joint.UserData);
|
||||
_writer.WriteStartElement("Tag");
|
||||
WriteDynamicType(joint.Tag.GetType(), joint.Tag);
|
||||
_writer.WriteEndElement();
|
||||
}
|
||||
|
||||
@@ -313,15 +311,13 @@ namespace FarseerPhysics.Common
|
||||
|
||||
_writer.WriteStartElement("Value");
|
||||
XmlSerializer serializer = new XmlSerializer(type);
|
||||
XmlSerializerNamespaces xmlnsEmpty = new XmlSerializerNamespaces();
|
||||
xmlnsEmpty.Add("", "");
|
||||
serializer.Serialize(_writer, val, xmlnsEmpty);
|
||||
serializer.Serialize(_writer, val);
|
||||
_writer.WriteEndElement();
|
||||
}
|
||||
|
||||
private static void WriteElement(string name, Vector2 vec)
|
||||
{
|
||||
_writer.WriteElementString(name, vec.X + " " + vec.Y);
|
||||
_writer.WriteElementString(name, FloatToString(vec.X) + " " + FloatToString(vec.Y));
|
||||
}
|
||||
|
||||
private static void WriteElement(string name, int val)
|
||||
@@ -336,39 +332,17 @@ namespace FarseerPhysics.Common
|
||||
|
||||
private static void WriteElement(string name, float val)
|
||||
{
|
||||
_writer.WriteElementString(name, val.ToString());
|
||||
_writer.WriteElementString(name, FloatToString(val));
|
||||
}
|
||||
|
||||
private static int FindIndex(List<Body> list, Body item)
|
||||
private static string FloatToString(float value)
|
||||
{
|
||||
for (int i = 0; i < list.Count; ++i)
|
||||
if (list[i] == item)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
return value.ToString(System.Globalization.CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
private static int FindIndex(List<Fixture> list, Fixture item)
|
||||
private static String Join(List<Fixture> fixtures, IEnumerable<Fixture> values)
|
||||
{
|
||||
for (int i = 0; i < list.Count; ++i)
|
||||
if (list[i].CompareTo(item))
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int FindIndex(List<Shape> list, Shape item)
|
||||
{
|
||||
for (int i = 0; i < list.Count; ++i)
|
||||
if (list[i].CompareTo(item))
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static String Join<T>(String separator, IEnumerable<T> values)
|
||||
{
|
||||
using (IEnumerator<T> en = values.GetEnumerator())
|
||||
using (var en = values.GetEnumerator())
|
||||
{
|
||||
if (!en.MoveNext())
|
||||
return String.Empty;
|
||||
@@ -376,24 +350,18 @@ namespace FarseerPhysics.Common
|
||||
StringBuilder result = new StringBuilder();
|
||||
if (en.Current != null)
|
||||
{
|
||||
// handle the case that the enumeration has null entries
|
||||
// and the case where their ToString() override is broken
|
||||
string value = en.Current.ToString();
|
||||
if (value != null)
|
||||
result.Append(value);
|
||||
var fixture = en.Current;
|
||||
var fixtureId = fixtures.IndexOf(fixture);
|
||||
result.Append(fixtureId.ToString());
|
||||
}
|
||||
|
||||
while (en.MoveNext())
|
||||
{
|
||||
result.Append(separator);
|
||||
if (en.Current != null)
|
||||
{
|
||||
// handle the case that the enumeration has null entries
|
||||
// and the case where their ToString() override is broken
|
||||
string value = en.Current.ToString();
|
||||
if (value != null)
|
||||
result.Append(value);
|
||||
}
|
||||
result.Append("|");
|
||||
|
||||
var fixture = en.Current;
|
||||
var fixtureId = fixtures.IndexOf(fixture);
|
||||
result.Append(fixtureId.ToString());
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
@@ -422,10 +390,10 @@ namespace FarseerPhysics.Common
|
||||
{
|
||||
foreach (Fixture fixture in body.FixtureList)
|
||||
{
|
||||
if (!shapes.Any(s2 => fixture.Shape.CompareTo(s2)))
|
||||
if (!shapes.Contains(fixture.Shape))
|
||||
{
|
||||
SerializeShape(fixture.Shape);
|
||||
shapes.Add(fixture.Shape);
|
||||
SerializeShape(fixture.Shape);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -437,10 +405,10 @@ namespace FarseerPhysics.Common
|
||||
{
|
||||
foreach (Fixture fixture in body.FixtureList)
|
||||
{
|
||||
if (!fixtures.Any(f2 => fixture.CompareTo(f2)))
|
||||
if (!fixtures.Contains(fixture))
|
||||
{
|
||||
SerializeFixture(fixture);
|
||||
fixtures.Add(fixture);
|
||||
SerializeFixture(fixtures, fixture);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -466,7 +434,6 @@ namespace FarseerPhysics.Common
|
||||
_writer.WriteEndElement();
|
||||
|
||||
_writer.Flush();
|
||||
_writer.Close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,6 +450,7 @@ namespace FarseerPhysics.Common
|
||||
{
|
||||
List<Body> bodies = new List<Body>();
|
||||
List<Fixture> fixtures = new List<Fixture>();
|
||||
|
||||
List<Joint> joints = new List<Joint>();
|
||||
List<Shape> shapes = new List<Shape>();
|
||||
|
||||
@@ -512,7 +480,7 @@ namespace FarseerPhysics.Common
|
||||
throw new Exception();
|
||||
|
||||
ShapeType type = (ShapeType)Enum.Parse(typeof(ShapeType), element.Attributes[0].Value, true);
|
||||
float density = float.Parse(element.Attributes[1].Value);
|
||||
float density = ParseFloat(element.Attributes[1].Value);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
@@ -526,7 +494,7 @@ namespace FarseerPhysics.Common
|
||||
switch (sn.Name.ToLower())
|
||||
{
|
||||
case "radius":
|
||||
shape.Radius = float.Parse(sn.Value);
|
||||
shape.Radius = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "position":
|
||||
shape.Position = ReadVector(sn);
|
||||
@@ -651,7 +619,7 @@ namespace FarseerPhysics.Common
|
||||
if (element.Name.ToLower() != "fixture")
|
||||
throw new Exception();
|
||||
|
||||
fixture.FixtureId = int.Parse(element.Attributes[0].Value);
|
||||
int fixtureId = int.Parse(element.Attributes[0].Value);
|
||||
|
||||
foreach (XMLFragmentElement sn in element.Elements)
|
||||
{
|
||||
@@ -671,27 +639,20 @@ namespace FarseerPhysics.Common
|
||||
case "groupindex":
|
||||
fixture._collisionGroup = short.Parse(ssn.Value);
|
||||
break;
|
||||
case "CollisionIgnores":
|
||||
string[] split = ssn.Value.Split('|');
|
||||
foreach (string s in split)
|
||||
{
|
||||
fixture._collisionIgnores.Add(int.Parse(s));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case "friction":
|
||||
fixture.Friction = float.Parse(sn.Value);
|
||||
fixture.Friction = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "issensor":
|
||||
fixture.IsSensor = bool.Parse(sn.Value);
|
||||
break;
|
||||
case "restitution":
|
||||
fixture.Restitution = float.Parse(sn.Value);
|
||||
fixture.Restitution = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "userdata":
|
||||
case "tag":
|
||||
fixture.UserData = ReadSimpleType(sn, null, false);
|
||||
break;
|
||||
}
|
||||
@@ -701,15 +662,16 @@ namespace FarseerPhysics.Common
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Read bodies
|
||||
Dictionary<Fixture, Fixture> mapFixtureClones = new Dictionary<Fixture,Fixture>();
|
||||
foreach (XMLFragmentElement bodyElement in root.Elements)
|
||||
{
|
||||
if (bodyElement.Name.ToLower() == "bodies")
|
||||
{
|
||||
foreach (XMLFragmentElement element in bodyElement.Elements)
|
||||
{
|
||||
Body body = new Body(world);
|
||||
Body body = world.CreateBody();
|
||||
|
||||
if (element.Name.ToLower() != "body")
|
||||
throw new Exception();
|
||||
@@ -729,14 +691,14 @@ namespace FarseerPhysics.Common
|
||||
case "angle":
|
||||
{
|
||||
Vector2 position = body.Position;
|
||||
body.SetTransformIgnoreContacts(ref position, float.Parse(sn.Value));
|
||||
body.SetTransformIgnoreContacts(ref position, ParseFloat(sn.Value));
|
||||
}
|
||||
break;
|
||||
case "angulardamping":
|
||||
body.AngularDamping = float.Parse(sn.Value);
|
||||
body.AngularDamping = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "angularvelocity":
|
||||
body.AngularVelocity = float.Parse(sn.Value);
|
||||
body.AngularVelocity = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "awake":
|
||||
body.Awake = bool.Parse(sn.Value);
|
||||
@@ -748,7 +710,7 @@ namespace FarseerPhysics.Common
|
||||
body.FixedRotation = bool.Parse(sn.Value);
|
||||
break;
|
||||
case "lineardamping":
|
||||
body.LinearDamping = float.Parse(sn.Value);
|
||||
body.LinearDamping = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "linearvelocity":
|
||||
body.LinearVelocity = ReadVector(sn);
|
||||
@@ -760,7 +722,7 @@ namespace FarseerPhysics.Common
|
||||
body.SetTransformIgnoreContacts(ref position, rotation);
|
||||
}
|
||||
break;
|
||||
case "userdata":
|
||||
case "tag":
|
||||
body.UserData = ReadSimpleType(sn, null, false);
|
||||
break;
|
||||
case "bindings":
|
||||
@@ -768,8 +730,9 @@ namespace FarseerPhysics.Common
|
||||
foreach (XMLFragmentElement pair in sn.Elements)
|
||||
{
|
||||
Fixture fix = fixtures[int.Parse(pair.Attributes[0].Value)];
|
||||
fix.Shape = shapes[int.Parse(pair.Attributes[1].Value)].Clone();
|
||||
fix.CloneOnto(body);
|
||||
var shape = shapes[int.Parse(pair.Attributes[1].Value)].Clone();
|
||||
var clone = fix.CloneOnto(body, shape);
|
||||
mapFixtureClones[fix] = clone;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -797,7 +760,7 @@ namespace FarseerPhysics.Common
|
||||
|
||||
int bodyAIndex = -1, bodyBIndex = -1;
|
||||
bool collideConnected = false;
|
||||
object userData = null;
|
||||
object jointTag = null;
|
||||
|
||||
foreach (XMLFragmentElement sn in n.Elements)
|
||||
{
|
||||
@@ -812,8 +775,8 @@ namespace FarseerPhysics.Common
|
||||
case "collideconnected":
|
||||
collideConnected = bool.Parse(sn.Value);
|
||||
break;
|
||||
case "userdata":
|
||||
userData = ReadSimpleType(sn, null, false);
|
||||
case "tag":
|
||||
jointTag = ReadSimpleType(sn, null, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -875,11 +838,11 @@ namespace FarseerPhysics.Common
|
||||
}
|
||||
|
||||
joint.CollideConnected = collideConnected;
|
||||
joint.UserData = userData;
|
||||
joint.Tag = jointTag;
|
||||
joint.BodyA = bodyA;
|
||||
joint.BodyB = bodyB;
|
||||
joints.Add(joint);
|
||||
world.AddJoint(joint);
|
||||
world.Add(joint);
|
||||
|
||||
foreach (XMLFragmentElement sn in n.Elements)
|
||||
{
|
||||
@@ -891,13 +854,13 @@ namespace FarseerPhysics.Common
|
||||
switch (sn.Name.ToLower())
|
||||
{
|
||||
case "dampingratio":
|
||||
((DistanceJoint)joint).DampingRatio = float.Parse(sn.Value);
|
||||
((DistanceJoint)joint).DampingRatio = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "frequencyhz":
|
||||
((DistanceJoint)joint).Frequency = float.Parse(sn.Value);
|
||||
((DistanceJoint)joint).Frequency = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "length":
|
||||
((DistanceJoint)joint).Length = float.Parse(sn.Value);
|
||||
((DistanceJoint)joint).Length = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "localanchora":
|
||||
((DistanceJoint)joint).LocalAnchorA = ReadVector(sn);
|
||||
@@ -919,10 +882,10 @@ namespace FarseerPhysics.Common
|
||||
((FrictionJoint)joint).LocalAnchorB = ReadVector(sn);
|
||||
break;
|
||||
case "maxforce":
|
||||
((FrictionJoint)joint).MaxForce = float.Parse(sn.Value);
|
||||
((FrictionJoint)joint).MaxForce = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "maxtorque":
|
||||
((FrictionJoint)joint).MaxTorque = float.Parse(sn.Value);
|
||||
((FrictionJoint)joint).MaxTorque = ParseFloat(sn.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -941,16 +904,16 @@ namespace FarseerPhysics.Common
|
||||
((WheelJoint)joint).LocalAnchorB = ReadVector(sn);
|
||||
break;
|
||||
case "motorspeed":
|
||||
((WheelJoint)joint).MotorSpeed = float.Parse(sn.Value);
|
||||
((WheelJoint)joint).MotorSpeed = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "dampingratio":
|
||||
((WheelJoint)joint).DampingRatio = float.Parse(sn.Value);
|
||||
((WheelJoint)joint).DampingRatio = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "maxmotortorque":
|
||||
((WheelJoint)joint).MaxMotorTorque = float.Parse(sn.Value);
|
||||
((WheelJoint)joint).MaxMotorTorque = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "frequencyhz":
|
||||
((WheelJoint)joint).Frequency = float.Parse(sn.Value);
|
||||
((WheelJoint)joint).Frequency = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "axis":
|
||||
((WheelJoint)joint).Axis = ReadVector(sn);
|
||||
@@ -978,19 +941,19 @@ namespace FarseerPhysics.Common
|
||||
((PrismaticJoint)joint).Axis = ReadVector(sn);
|
||||
break;
|
||||
case "maxmotorforce":
|
||||
((PrismaticJoint)joint).MaxMotorForce = float.Parse(sn.Value);
|
||||
((PrismaticJoint)joint).MaxMotorForce = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "motorspeed":
|
||||
((PrismaticJoint)joint).MotorSpeed = float.Parse(sn.Value);
|
||||
((PrismaticJoint)joint).MotorSpeed = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "lowertranslation":
|
||||
((PrismaticJoint)joint).LowerLimit = float.Parse(sn.Value);
|
||||
((PrismaticJoint)joint).LowerLimit = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "uppertranslation":
|
||||
((PrismaticJoint)joint).UpperLimit = float.Parse(sn.Value);
|
||||
((PrismaticJoint)joint).UpperLimit = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "referenceangle":
|
||||
((PrismaticJoint)joint).ReferenceAngle = float.Parse(sn.Value);
|
||||
((PrismaticJoint)joint).ReferenceAngle = ParseFloat(sn.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1006,10 +969,10 @@ namespace FarseerPhysics.Common
|
||||
((PulleyJoint)joint).WorldAnchorB = ReadVector(sn);
|
||||
break;
|
||||
case "lengtha":
|
||||
((PulleyJoint)joint).LengthA = float.Parse(sn.Value);
|
||||
((PulleyJoint)joint).LengthA = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "lengthb":
|
||||
((PulleyJoint)joint).LengthB = float.Parse(sn.Value);
|
||||
((PulleyJoint)joint).LengthB = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "localanchora":
|
||||
((PulleyJoint)joint).LocalAnchorA = ReadVector(sn);
|
||||
@@ -1018,10 +981,10 @@ namespace FarseerPhysics.Common
|
||||
((PulleyJoint)joint).LocalAnchorB = ReadVector(sn);
|
||||
break;
|
||||
case "ratio":
|
||||
((PulleyJoint)joint).Ratio = float.Parse(sn.Value);
|
||||
((PulleyJoint)joint).Ratio = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "constant":
|
||||
((PulleyJoint)joint).Constant = float.Parse(sn.Value);
|
||||
((PulleyJoint)joint).Constant = ParseFloat(sn.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1043,19 +1006,19 @@ namespace FarseerPhysics.Common
|
||||
((RevoluteJoint)joint).LocalAnchorB = ReadVector(sn);
|
||||
break;
|
||||
case "maxmotortorque":
|
||||
((RevoluteJoint)joint).MaxMotorTorque = float.Parse(sn.Value);
|
||||
((RevoluteJoint)joint).MaxMotorTorque = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "motorspeed":
|
||||
((RevoluteJoint)joint).MotorSpeed = float.Parse(sn.Value);
|
||||
((RevoluteJoint)joint).MotorSpeed = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "lowerangle":
|
||||
((RevoluteJoint)joint).LowerLimit = float.Parse(sn.Value);
|
||||
((RevoluteJoint)joint).LowerLimit = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "upperangle":
|
||||
((RevoluteJoint)joint).UpperLimit = float.Parse(sn.Value);
|
||||
((RevoluteJoint)joint).UpperLimit = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "referenceangle":
|
||||
((RevoluteJoint)joint).ReferenceAngle = float.Parse(sn.Value);
|
||||
((RevoluteJoint)joint).ReferenceAngle = ParseFloat(sn.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1084,7 +1047,7 @@ namespace FarseerPhysics.Common
|
||||
((RopeJoint)joint).LocalAnchorB = ReadVector(sn);
|
||||
break;
|
||||
case "maxlength":
|
||||
((RopeJoint)joint).MaxLength = float.Parse(sn.Value);
|
||||
((RopeJoint)joint).MaxLength = ParseFloat(sn.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1096,16 +1059,16 @@ namespace FarseerPhysics.Common
|
||||
switch (sn.Name.ToLower())
|
||||
{
|
||||
case "biasfactor":
|
||||
((AngleJoint)joint).BiasFactor = float.Parse(sn.Value);
|
||||
((AngleJoint)joint).BiasFactor = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "maximpulse":
|
||||
((AngleJoint)joint).MaxImpulse = float.Parse(sn.Value);
|
||||
((AngleJoint)joint).MaxImpulse = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "softness":
|
||||
((AngleJoint)joint).Softness = float.Parse(sn.Value);
|
||||
((AngleJoint)joint).Softness = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "targetangle":
|
||||
((AngleJoint)joint).TargetAngle = float.Parse(sn.Value);
|
||||
((AngleJoint)joint).TargetAngle = ParseFloat(sn.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1114,19 +1077,19 @@ namespace FarseerPhysics.Common
|
||||
switch (sn.Name.ToLower())
|
||||
{
|
||||
case "angularoffset":
|
||||
((MotorJoint)joint).AngularOffset = float.Parse(sn.Value);
|
||||
((MotorJoint)joint).AngularOffset = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "linearoffset":
|
||||
((MotorJoint)joint).LinearOffset = ReadVector(sn);
|
||||
break;
|
||||
case "maxforce":
|
||||
((MotorJoint)joint).MaxForce = float.Parse(sn.Value);
|
||||
((MotorJoint)joint).MaxForce = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "maxtorque":
|
||||
((MotorJoint)joint).MaxTorque = float.Parse(sn.Value);
|
||||
((MotorJoint)joint).MaxTorque = ParseFloat(sn.Value);
|
||||
break;
|
||||
case "correctionfactor":
|
||||
((MotorJoint)joint).CorrectionFactor = float.Parse(sn.Value);
|
||||
((MotorJoint)joint).CorrectionFactor = ParseFloat(sn.Value);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1142,7 +1105,7 @@ namespace FarseerPhysics.Common
|
||||
private static Vector2 ReadVector(XMLFragmentElement node)
|
||||
{
|
||||
string[] values = node.Value.Split(' ');
|
||||
return new Vector2(float.Parse(values[0]), float.Parse(values[1]));
|
||||
return new Vector2(ParseFloat(values[0]), ParseFloat(values[1]));
|
||||
}
|
||||
|
||||
private static object ReadSimpleType(XMLFragmentElement node, Type type, bool outer)
|
||||
@@ -1151,8 +1114,6 @@ namespace FarseerPhysics.Common
|
||||
return ReadSimpleType(node.Elements[1], Type.GetType(node.Elements[0].Value), outer);
|
||||
|
||||
XmlSerializer serializer = new XmlSerializer(type);
|
||||
XmlSerializerNamespaces xmlnsEmpty = new XmlSerializerNamespaces();
|
||||
xmlnsEmpty.Add("", "");
|
||||
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
@@ -1168,6 +1129,12 @@ namespace FarseerPhysics.Common
|
||||
return serializer.Deserialize(XmlReader.Create(stream, settings));
|
||||
}
|
||||
}
|
||||
|
||||
private static float ParseFloat(string value)
|
||||
{
|
||||
return float.Parse(value, System.Globalization.CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#region XMLFragment
|
||||
@@ -1252,13 +1219,7 @@ namespace FarseerPhysics.Common
|
||||
{
|
||||
Load(stream);
|
||||
}
|
||||
|
||||
public XMLFragmentParser(string fileName)
|
||||
{
|
||||
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
|
||||
Load(fs);
|
||||
}
|
||||
|
||||
|
||||
public XMLFragmentElement RootNode
|
||||
{
|
||||
get { return _rootNode; }
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
#if SILVERLIGHT
|
||||
using System;
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using FarseerPhysics.Collision;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using FarseerPhysics.Collision;
|
||||
using FarseerPhysics.Common.Decomposition;
|
||||
using FarseerPhysics.Common.PolygonManipulation;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using FarseerPhysics.Factories;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Common.TextureTools
|
||||
@@ -218,7 +222,7 @@ namespace FarseerPhysics.Common.TextureTools
|
||||
{
|
||||
for (int i = 0; i < _bodyMap[x, y].Count; i++)
|
||||
{
|
||||
World.RemoveBody(_bodyMap[x, y][i]);
|
||||
World.Remove(_bodyMap[x, y][i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +260,7 @@ namespace FarseerPhysics.Common.TextureTools
|
||||
foreach (Vertices poly in decompPolys)
|
||||
{
|
||||
if (poly.Count > 2)
|
||||
_bodyMap[gx, gy].Add(BodyFactory.CreatePolygon(World, poly, 1));
|
||||
_bodyMap[gx, gy].Add(World.CreatePolygon(poly, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
@@ -1,588 +0,0 @@
|
||||
#if !XNA && !WINDOWS_PHONE && !XBOX && !ANDROID
|
||||
|
||||
#region License
|
||||
|
||||
/*
|
||||
MIT License
|
||||
Copyright © 2006 The Mono.Xna Team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Authors
|
||||
* Alan McGovern
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#endregion License
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Xna.Framework
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Vector2 : IEquatable<Vector2>
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private static Vector2 zeroVector = new Vector2(0f, 0f);
|
||||
private static Vector2 unitVector = new Vector2(1f, 1f);
|
||||
private static Vector2 unitXVector = new Vector2(1f, 0f);
|
||||
private static Vector2 unitYVector = new Vector2(0f, 1f);
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Public Fields
|
||||
|
||||
public float X;
|
||||
public float Y;
|
||||
|
||||
#endregion Public Fields
|
||||
|
||||
#region Properties
|
||||
|
||||
public static Vector2 Zero
|
||||
{
|
||||
get { return zeroVector; }
|
||||
}
|
||||
|
||||
public static Vector2 One
|
||||
{
|
||||
get { return unitVector; }
|
||||
}
|
||||
|
||||
public static Vector2 UnitX
|
||||
{
|
||||
get { return unitXVector; }
|
||||
}
|
||||
|
||||
public static Vector2 UnitY
|
||||
{
|
||||
get { return unitYVector; }
|
||||
}
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructor foe standard 2D vector.
|
||||
/// </summary>
|
||||
/// <param name="x">
|
||||
/// A <see cref="System.Single"/>
|
||||
/// </param>
|
||||
/// <param name="y">
|
||||
/// A <see cref="System.Single"/>
|
||||
/// </param>
|
||||
public Vector2(float x, float y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for "square" vector.
|
||||
/// </summary>
|
||||
/// <param name="value">
|
||||
/// A <see cref="System.Single"/>
|
||||
/// </param>
|
||||
public Vector2(float value)
|
||||
{
|
||||
X = value;
|
||||
Y = value;
|
||||
}
|
||||
|
||||
#endregion Constructors
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public static void Reflect(ref Vector2 vector, ref Vector2 normal, out Vector2 result)
|
||||
{
|
||||
float dot = Dot(vector, normal);
|
||||
result.X = vector.X - ((2f*dot)*normal.X);
|
||||
result.Y = vector.Y - ((2f*dot)*normal.Y);
|
||||
}
|
||||
|
||||
public static Vector2 Reflect(Vector2 vector, Vector2 normal)
|
||||
{
|
||||
Vector2 result;
|
||||
Reflect(ref vector, ref normal, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Vector2 Add(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
value1.X += value2.X;
|
||||
value1.Y += value2.Y;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static void Add(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
|
||||
{
|
||||
result.X = value1.X + value2.X;
|
||||
result.Y = value1.Y + value2.Y;
|
||||
}
|
||||
|
||||
public static Vector2 Barycentric(Vector2 value1, Vector2 value2, Vector2 value3, float amount1, float amount2)
|
||||
{
|
||||
return new Vector2(
|
||||
MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
|
||||
MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2));
|
||||
}
|
||||
|
||||
public static void Barycentric(ref Vector2 value1, ref Vector2 value2, ref Vector2 value3, float amount1,
|
||||
float amount2, out Vector2 result)
|
||||
{
|
||||
result = new Vector2(
|
||||
MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
|
||||
MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2));
|
||||
}
|
||||
|
||||
public static Vector2 CatmullRom(Vector2 value1, Vector2 value2, Vector2 value3, Vector2 value4, float amount)
|
||||
{
|
||||
return new Vector2(
|
||||
MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
|
||||
MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount));
|
||||
}
|
||||
|
||||
public static void CatmullRom(ref Vector2 value1, ref Vector2 value2, ref Vector2 value3, ref Vector2 value4,
|
||||
float amount, out Vector2 result)
|
||||
{
|
||||
result = new Vector2(
|
||||
MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
|
||||
MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount));
|
||||
}
|
||||
|
||||
public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max)
|
||||
{
|
||||
return new Vector2(
|
||||
MathHelper.Clamp(value1.X, min.X, max.X),
|
||||
MathHelper.Clamp(value1.Y, min.Y, max.Y));
|
||||
}
|
||||
|
||||
public static void Clamp(ref Vector2 value1, ref Vector2 min, ref Vector2 max, out Vector2 result)
|
||||
{
|
||||
result = new Vector2(
|
||||
MathHelper.Clamp(value1.X, min.X, max.X),
|
||||
MathHelper.Clamp(value1.Y, min.Y, max.Y));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns float precison distanve between two vectors
|
||||
/// </summary>
|
||||
/// <param name="value1">
|
||||
/// A <see cref="Vector2"/>
|
||||
/// </param>
|
||||
/// <param name="value2">
|
||||
/// A <see cref="Vector2"/>
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="System.Single"/>
|
||||
/// </returns>
|
||||
public static float Distance(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
float result;
|
||||
DistanceSquared(ref value1, ref value2, out result);
|
||||
return (float) Math.Sqrt(result);
|
||||
}
|
||||
|
||||
|
||||
public static void Distance(ref Vector2 value1, ref Vector2 value2, out float result)
|
||||
{
|
||||
DistanceSquared(ref value1, ref value2, out result);
|
||||
result = (float) Math.Sqrt(result);
|
||||
}
|
||||
|
||||
public static float DistanceSquared(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
float result;
|
||||
DistanceSquared(ref value1, ref value2, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void DistanceSquared(ref Vector2 value1, ref Vector2 value2, out float result)
|
||||
{
|
||||
result = (value1.X - value2.X)*(value1.X - value2.X) + (value1.Y - value2.Y)*(value1.Y - value2.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devide first vector with the secund vector
|
||||
/// </summary>
|
||||
/// <param name="value1">
|
||||
/// A <see cref="Vector2"/>
|
||||
/// </param>
|
||||
/// <param name="value2">
|
||||
/// A <see cref="Vector2"/>
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Vector2"/>
|
||||
/// </returns>
|
||||
public static Vector2 Divide(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
value1.X /= value2.X;
|
||||
value1.Y /= value2.Y;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static void Divide(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
|
||||
{
|
||||
result.X = value1.X/value2.X;
|
||||
result.Y = value1.Y/value2.Y;
|
||||
}
|
||||
|
||||
public static Vector2 Divide(Vector2 value1, float divider)
|
||||
{
|
||||
float factor = 1/divider;
|
||||
value1.X *= factor;
|
||||
value1.Y *= factor;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static void Divide(ref Vector2 value1, float divider, out Vector2 result)
|
||||
{
|
||||
float factor = 1/divider;
|
||||
result.X = value1.X*factor;
|
||||
result.Y = value1.Y*factor;
|
||||
}
|
||||
|
||||
public static float Dot(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
return value1.X*value2.X + value1.Y*value2.Y;
|
||||
}
|
||||
|
||||
public static void Dot(ref Vector2 value1, ref Vector2 value2, out float result)
|
||||
{
|
||||
result = value1.X*value2.X + value1.Y*value2.Y;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj is Vector2) ? this == ((Vector2) obj) : false;
|
||||
}
|
||||
|
||||
public bool Equals(Vector2 other)
|
||||
{
|
||||
return this == other;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (int) (X + Y);
|
||||
}
|
||||
|
||||
public static Vector2 Hermite(Vector2 value1, Vector2 tangent1, Vector2 value2, Vector2 tangent2, float amount)
|
||||
{
|
||||
Vector2 result = new Vector2();
|
||||
Hermite(ref value1, ref tangent1, ref value2, ref tangent2, amount, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void Hermite(ref Vector2 value1, ref Vector2 tangent1, ref Vector2 value2, ref Vector2 tangent2,
|
||||
float amount, out Vector2 result)
|
||||
{
|
||||
result.X = MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount);
|
||||
result.Y = MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount);
|
||||
}
|
||||
|
||||
public float Length()
|
||||
{
|
||||
float result;
|
||||
DistanceSquared(ref this, ref zeroVector, out result);
|
||||
return (float) Math.Sqrt(result);
|
||||
}
|
||||
|
||||
public float LengthSquared()
|
||||
{
|
||||
float result;
|
||||
DistanceSquared(ref this, ref zeroVector, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Vector2 Lerp(Vector2 value1, Vector2 value2, float amount)
|
||||
{
|
||||
return new Vector2(
|
||||
MathHelper.Lerp(value1.X, value2.X, amount),
|
||||
MathHelper.Lerp(value1.Y, value2.Y, amount));
|
||||
}
|
||||
|
||||
public static void Lerp(ref Vector2 value1, ref Vector2 value2, float amount, out Vector2 result)
|
||||
{
|
||||
result = new Vector2(
|
||||
MathHelper.Lerp(value1.X, value2.X, amount),
|
||||
MathHelper.Lerp(value1.Y, value2.Y, amount));
|
||||
}
|
||||
|
||||
public static Vector2 Max(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
return new Vector2(
|
||||
MathHelper.Max(value1.X, value2.X),
|
||||
MathHelper.Max(value1.Y, value2.Y));
|
||||
}
|
||||
|
||||
public static void Max(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
|
||||
{
|
||||
result = new Vector2(
|
||||
MathHelper.Max(value1.X, value2.X),
|
||||
MathHelper.Max(value1.Y, value2.Y));
|
||||
}
|
||||
|
||||
public static Vector2 Min(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
return new Vector2(
|
||||
MathHelper.Min(value1.X, value2.X),
|
||||
MathHelper.Min(value1.Y, value2.Y));
|
||||
}
|
||||
|
||||
public static void Min(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
|
||||
{
|
||||
result = new Vector2(
|
||||
MathHelper.Min(value1.X, value2.X),
|
||||
MathHelper.Min(value1.Y, value2.Y));
|
||||
}
|
||||
|
||||
public static Vector2 Multiply(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
value1.X *= value2.X;
|
||||
value1.Y *= value2.Y;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static Vector2 Multiply(Vector2 value1, float scaleFactor)
|
||||
{
|
||||
value1.X *= scaleFactor;
|
||||
value1.Y *= scaleFactor;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static void Multiply(ref Vector2 value1, float scaleFactor, out Vector2 result)
|
||||
{
|
||||
result.X = value1.X*scaleFactor;
|
||||
result.Y = value1.Y*scaleFactor;
|
||||
}
|
||||
|
||||
public static void Multiply(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
|
||||
{
|
||||
result.X = value1.X*value2.X;
|
||||
result.Y = value1.Y*value2.Y;
|
||||
}
|
||||
|
||||
public static Vector2 Negate(Vector2 value)
|
||||
{
|
||||
value.X = -value.X;
|
||||
value.Y = -value.Y;
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void Negate(ref Vector2 value, out Vector2 result)
|
||||
{
|
||||
result.X = -value.X;
|
||||
result.Y = -value.Y;
|
||||
}
|
||||
|
||||
public void Normalize()
|
||||
{
|
||||
Normalize(ref this, out this);
|
||||
}
|
||||
|
||||
public static Vector2 Normalize(Vector2 value)
|
||||
{
|
||||
Normalize(ref value, out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void Normalize(ref Vector2 value, out Vector2 result)
|
||||
{
|
||||
float factor;
|
||||
DistanceSquared(ref value, ref zeroVector, out factor);
|
||||
factor = 1f/(float) Math.Sqrt(factor);
|
||||
result.X = value.X*factor;
|
||||
result.Y = value.Y*factor;
|
||||
}
|
||||
|
||||
public static Vector2 SmoothStep(Vector2 value1, Vector2 value2, float amount)
|
||||
{
|
||||
return new Vector2(
|
||||
MathHelper.SmoothStep(value1.X, value2.X, amount),
|
||||
MathHelper.SmoothStep(value1.Y, value2.Y, amount));
|
||||
}
|
||||
|
||||
public static void SmoothStep(ref Vector2 value1, ref Vector2 value2, float amount, out Vector2 result)
|
||||
{
|
||||
result = new Vector2(
|
||||
MathHelper.SmoothStep(value1.X, value2.X, amount),
|
||||
MathHelper.SmoothStep(value1.Y, value2.Y, amount));
|
||||
}
|
||||
|
||||
public static Vector2 Subtract(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
value1.X -= value2.X;
|
||||
value1.Y -= value2.Y;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static void Subtract(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
|
||||
{
|
||||
result.X = value1.X - value2.X;
|
||||
result.Y = value1.Y - value2.Y;
|
||||
}
|
||||
|
||||
public static Vector2 Transform(Vector2 position, Matrix matrix)
|
||||
{
|
||||
Transform(ref position, ref matrix, out position);
|
||||
return position;
|
||||
}
|
||||
|
||||
public static void Transform(ref Vector2 position, ref Matrix matrix, out Vector2 result)
|
||||
{
|
||||
result = new Vector2((position.X*matrix.M11) + (position.Y*matrix.M21) + matrix.M41,
|
||||
(position.X*matrix.M12) + (position.Y*matrix.M22) + matrix.M42);
|
||||
}
|
||||
|
||||
public static void Transform(Vector2[] sourceArray, ref Matrix matrix, Vector2[] destinationArray)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static void Transform(Vector2[] sourceArray, int sourceIndex, ref Matrix matrix,
|
||||
Vector2[] destinationArray, int destinationIndex, int length)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static Vector2 TransformNormal(Vector2 normal, Matrix matrix)
|
||||
{
|
||||
TransformNormal(ref normal, ref matrix, out normal);
|
||||
return normal;
|
||||
}
|
||||
|
||||
public static void TransformNormal(ref Vector2 normal, ref Matrix matrix, out Vector2 result)
|
||||
{
|
||||
result = new Vector2((normal.X*matrix.M11) + (normal.Y*matrix.M21),
|
||||
(normal.X*matrix.M12) + (normal.Y*matrix.M22));
|
||||
}
|
||||
|
||||
public static void TransformNormal(Vector2[] sourceArray, ref Matrix matrix, Vector2[] destinationArray)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static void TransformNormal(Vector2[] sourceArray, int sourceIndex, ref Matrix matrix,
|
||||
Vector2[] destinationArray, int destinationIndex, int length)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(24);
|
||||
sb.Append("{X:");
|
||||
sb.Append(X);
|
||||
sb.Append(" Y:");
|
||||
sb.Append(Y);
|
||||
sb.Append("}");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Operators
|
||||
|
||||
public static Vector2 operator -(Vector2 value)
|
||||
{
|
||||
value.X = -value.X;
|
||||
value.Y = -value.Y;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
public static bool operator ==(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
return value1.X == value2.X && value1.Y == value2.Y;
|
||||
}
|
||||
|
||||
|
||||
public static bool operator !=(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
return value1.X != value2.X || value1.Y != value2.Y;
|
||||
}
|
||||
|
||||
|
||||
public static Vector2 operator +(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
value1.X += value2.X;
|
||||
value1.Y += value2.Y;
|
||||
return value1;
|
||||
}
|
||||
|
||||
|
||||
public static Vector2 operator -(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
value1.X -= value2.X;
|
||||
value1.Y -= value2.Y;
|
||||
return value1;
|
||||
}
|
||||
|
||||
|
||||
public static Vector2 operator *(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
value1.X *= value2.X;
|
||||
value1.Y *= value2.Y;
|
||||
return value1;
|
||||
}
|
||||
|
||||
|
||||
public static Vector2 operator *(Vector2 value, float scaleFactor)
|
||||
{
|
||||
value.X *= scaleFactor;
|
||||
value.Y *= scaleFactor;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
public static Vector2 operator *(float scaleFactor, Vector2 value)
|
||||
{
|
||||
value.X *= scaleFactor;
|
||||
value.Y *= scaleFactor;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
public static Vector2 operator /(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
value1.X /= value2.X;
|
||||
value1.Y /= value2.Y;
|
||||
return value1;
|
||||
}
|
||||
|
||||
|
||||
public static Vector2 operator /(Vector2 value1, float divider)
|
||||
{
|
||||
float factor = 1/divider;
|
||||
value1.X *= factor;
|
||||
value1.Y *= factor;
|
||||
return value1;
|
||||
}
|
||||
|
||||
#endregion Operators
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,648 +0,0 @@
|
||||
#if !XNA && !WINDOWS_PHONE && !XBOX && !ANDROID
|
||||
|
||||
#region License
|
||||
|
||||
/*
|
||||
MIT License
|
||||
Copyright © 2006 The Mono.Xna Team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Authors:
|
||||
* Alan McGovern
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#endregion License
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Xna.Framework
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Vector3 : IEquatable<Vector3>
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private static Vector3 zero = new Vector3(0f, 0f, 0f);
|
||||
private static Vector3 one = new Vector3(1f, 1f, 1f);
|
||||
private static Vector3 unitX = new Vector3(1f, 0f, 0f);
|
||||
private static Vector3 unitY = new Vector3(0f, 1f, 0f);
|
||||
private static Vector3 unitZ = new Vector3(0f, 0f, 1f);
|
||||
private static Vector3 up = new Vector3(0f, 1f, 0f);
|
||||
private static Vector3 down = new Vector3(0f, -1f, 0f);
|
||||
private static Vector3 right = new Vector3(1f, 0f, 0f);
|
||||
private static Vector3 left = new Vector3(-1f, 0f, 0f);
|
||||
private static Vector3 forward = new Vector3(0f, 0f, -1f);
|
||||
private static Vector3 backward = new Vector3(0f, 0f, 1f);
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Public Fields
|
||||
|
||||
public float X;
|
||||
public float Y;
|
||||
public float Z;
|
||||
|
||||
#endregion Public Fields
|
||||
|
||||
#region Properties
|
||||
|
||||
public static Vector3 Zero
|
||||
{
|
||||
get { return zero; }
|
||||
}
|
||||
|
||||
public static Vector3 One
|
||||
{
|
||||
get { return one; }
|
||||
}
|
||||
|
||||
public static Vector3 UnitX
|
||||
{
|
||||
get { return unitX; }
|
||||
}
|
||||
|
||||
public static Vector3 UnitY
|
||||
{
|
||||
get { return unitY; }
|
||||
}
|
||||
|
||||
public static Vector3 UnitZ
|
||||
{
|
||||
get { return unitZ; }
|
||||
}
|
||||
|
||||
public static Vector3 Up
|
||||
{
|
||||
get { return up; }
|
||||
}
|
||||
|
||||
public static Vector3 Down
|
||||
{
|
||||
get { return down; }
|
||||
}
|
||||
|
||||
public static Vector3 Right
|
||||
{
|
||||
get { return right; }
|
||||
}
|
||||
|
||||
public static Vector3 Left
|
||||
{
|
||||
get { return left; }
|
||||
}
|
||||
|
||||
public static Vector3 Forward
|
||||
{
|
||||
get { return forward; }
|
||||
}
|
||||
|
||||
public static Vector3 Backward
|
||||
{
|
||||
get { return backward; }
|
||||
}
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Constructors
|
||||
|
||||
public Vector3(float x, float y, float z)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
|
||||
public Vector3(float value)
|
||||
{
|
||||
X = value;
|
||||
Y = value;
|
||||
Z = value;
|
||||
}
|
||||
|
||||
|
||||
public Vector3(Vector2 value, float z)
|
||||
{
|
||||
X = value.X;
|
||||
Y = value.Y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
#endregion Constructors
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public static Vector3 Add(Vector3 value1, Vector3 value2)
|
||||
{
|
||||
value1.X += value2.X;
|
||||
value1.Y += value2.Y;
|
||||
value1.Z += value2.Z;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static void Add(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
|
||||
{
|
||||
result.X = value1.X + value2.X;
|
||||
result.Y = value1.Y + value2.Y;
|
||||
result.Z = value1.Z + value2.Z;
|
||||
}
|
||||
|
||||
public static Vector3 Barycentric(Vector3 value1, Vector3 value2, Vector3 value3, float amount1, float amount2)
|
||||
{
|
||||
return new Vector3(
|
||||
MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
|
||||
MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2),
|
||||
MathHelper.Barycentric(value1.Z, value2.Z, value3.Z, amount1, amount2));
|
||||
}
|
||||
|
||||
public static void Barycentric(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, float amount1,
|
||||
float amount2, out Vector3 result)
|
||||
{
|
||||
result = new Vector3(
|
||||
MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
|
||||
MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2),
|
||||
MathHelper.Barycentric(value1.Z, value2.Z, value3.Z, amount1, amount2));
|
||||
}
|
||||
|
||||
public static Vector3 CatmullRom(Vector3 value1, Vector3 value2, Vector3 value3, Vector3 value4, float amount)
|
||||
{
|
||||
return new Vector3(
|
||||
MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
|
||||
MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount),
|
||||
MathHelper.CatmullRom(value1.Z, value2.Z, value3.Z, value4.Z, amount));
|
||||
}
|
||||
|
||||
public static void CatmullRom(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, ref Vector3 value4,
|
||||
float amount, out Vector3 result)
|
||||
{
|
||||
result = new Vector3(
|
||||
MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
|
||||
MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount),
|
||||
MathHelper.CatmullRom(value1.Z, value2.Z, value3.Z, value4.Z, amount));
|
||||
}
|
||||
|
||||
public static Vector3 Clamp(Vector3 value1, Vector3 min, Vector3 max)
|
||||
{
|
||||
return new Vector3(
|
||||
MathHelper.Clamp(value1.X, min.X, max.X),
|
||||
MathHelper.Clamp(value1.Y, min.Y, max.Y),
|
||||
MathHelper.Clamp(value1.Z, min.Z, max.Z));
|
||||
}
|
||||
|
||||
public static void Clamp(ref Vector3 value1, ref Vector3 min, ref Vector3 max, out Vector3 result)
|
||||
{
|
||||
result = new Vector3(
|
||||
MathHelper.Clamp(value1.X, min.X, max.X),
|
||||
MathHelper.Clamp(value1.Y, min.Y, max.Y),
|
||||
MathHelper.Clamp(value1.Z, min.Z, max.Z));
|
||||
}
|
||||
|
||||
public static Vector3 Cross(Vector3 vector1, Vector3 vector2)
|
||||
{
|
||||
Cross(ref vector1, ref vector2, out vector1);
|
||||
return vector1;
|
||||
}
|
||||
|
||||
public static void Cross(ref Vector3 vector1, ref Vector3 vector2, out Vector3 result)
|
||||
{
|
||||
result = new Vector3(vector1.Y*vector2.Z - vector2.Y*vector1.Z,
|
||||
-(vector1.X*vector2.Z - vector2.X*vector1.Z),
|
||||
vector1.X*vector2.Y - vector2.X*vector1.Y);
|
||||
}
|
||||
|
||||
public static float Distance(Vector3 vector1, Vector3 vector2)
|
||||
{
|
||||
float result;
|
||||
DistanceSquared(ref vector1, ref vector2, out result);
|
||||
return (float) Math.Sqrt(result);
|
||||
}
|
||||
|
||||
public static void Distance(ref Vector3 value1, ref Vector3 value2, out float result)
|
||||
{
|
||||
DistanceSquared(ref value1, ref value2, out result);
|
||||
result = (float) Math.Sqrt(result);
|
||||
}
|
||||
|
||||
public static float DistanceSquared(Vector3 value1, Vector3 value2)
|
||||
{
|
||||
float result;
|
||||
DistanceSquared(ref value1, ref value2, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void DistanceSquared(ref Vector3 value1, ref Vector3 value2, out float result)
|
||||
{
|
||||
result = (value1.X - value2.X)*(value1.X - value2.X) +
|
||||
(value1.Y - value2.Y)*(value1.Y - value2.Y) +
|
||||
(value1.Z - value2.Z)*(value1.Z - value2.Z);
|
||||
}
|
||||
|
||||
public static Vector3 Divide(Vector3 value1, Vector3 value2)
|
||||
{
|
||||
value1.X /= value2.X;
|
||||
value1.Y /= value2.Y;
|
||||
value1.Z /= value2.Z;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static Vector3 Divide(Vector3 value1, float value2)
|
||||
{
|
||||
float factor = 1/value2;
|
||||
value1.X *= factor;
|
||||
value1.Y *= factor;
|
||||
value1.Z *= factor;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static void Divide(ref Vector3 value1, float divisor, out Vector3 result)
|
||||
{
|
||||
float factor = 1/divisor;
|
||||
result.X = value1.X*factor;
|
||||
result.Y = value1.Y*factor;
|
||||
result.Z = value1.Z*factor;
|
||||
}
|
||||
|
||||
public static void Divide(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
|
||||
{
|
||||
result.X = value1.X/value2.X;
|
||||
result.Y = value1.Y/value2.Y;
|
||||
result.Z = value1.Z/value2.Z;
|
||||
}
|
||||
|
||||
public static float Dot(Vector3 vector1, Vector3 vector2)
|
||||
{
|
||||
return vector1.X*vector2.X + vector1.Y*vector2.Y + vector1.Z*vector2.Z;
|
||||
}
|
||||
|
||||
public static void Dot(ref Vector3 vector1, ref Vector3 vector2, out float result)
|
||||
{
|
||||
result = vector1.X*vector2.X + vector1.Y*vector2.Y + vector1.Z*vector2.Z;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj is Vector3) ? this == (Vector3) obj : false;
|
||||
}
|
||||
|
||||
public bool Equals(Vector3 other)
|
||||
{
|
||||
return this == other;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (int) (X + Y + Z);
|
||||
}
|
||||
|
||||
public static Vector3 Hermite(Vector3 value1, Vector3 tangent1, Vector3 value2, Vector3 tangent2, float amount)
|
||||
{
|
||||
Vector3 result = new Vector3();
|
||||
Hermite(ref value1, ref tangent1, ref value2, ref tangent2, amount, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void Hermite(ref Vector3 value1, ref Vector3 tangent1, ref Vector3 value2, ref Vector3 tangent2,
|
||||
float amount, out Vector3 result)
|
||||
{
|
||||
result.X = MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount);
|
||||
result.Y = MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount);
|
||||
result.Z = MathHelper.Hermite(value1.Z, tangent1.Z, value2.Z, tangent2.Z, amount);
|
||||
}
|
||||
|
||||
public float Length()
|
||||
{
|
||||
float result;
|
||||
DistanceSquared(ref this, ref zero, out result);
|
||||
return (float) Math.Sqrt(result);
|
||||
}
|
||||
|
||||
public float LengthSquared()
|
||||
{
|
||||
float result;
|
||||
DistanceSquared(ref this, ref zero, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Vector3 Lerp(Vector3 value1, Vector3 value2, float amount)
|
||||
{
|
||||
return new Vector3(
|
||||
MathHelper.Lerp(value1.X, value2.X, amount),
|
||||
MathHelper.Lerp(value1.Y, value2.Y, amount),
|
||||
MathHelper.Lerp(value1.Z, value2.Z, amount));
|
||||
}
|
||||
|
||||
public static void Lerp(ref Vector3 value1, ref Vector3 value2, float amount, out Vector3 result)
|
||||
{
|
||||
result = new Vector3(
|
||||
MathHelper.Lerp(value1.X, value2.X, amount),
|
||||
MathHelper.Lerp(value1.Y, value2.Y, amount),
|
||||
MathHelper.Lerp(value1.Z, value2.Z, amount));
|
||||
}
|
||||
|
||||
public static Vector3 Max(Vector3 value1, Vector3 value2)
|
||||
{
|
||||
return new Vector3(
|
||||
MathHelper.Max(value1.X, value2.X),
|
||||
MathHelper.Max(value1.Y, value2.Y),
|
||||
MathHelper.Max(value1.Z, value2.Z));
|
||||
}
|
||||
|
||||
public static void Max(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
|
||||
{
|
||||
result = new Vector3(
|
||||
MathHelper.Max(value1.X, value2.X),
|
||||
MathHelper.Max(value1.Y, value2.Y),
|
||||
MathHelper.Max(value1.Z, value2.Z));
|
||||
}
|
||||
|
||||
public static Vector3 Min(Vector3 value1, Vector3 value2)
|
||||
{
|
||||
return new Vector3(
|
||||
MathHelper.Min(value1.X, value2.X),
|
||||
MathHelper.Min(value1.Y, value2.Y),
|
||||
MathHelper.Min(value1.Z, value2.Z));
|
||||
}
|
||||
|
||||
public static void Min(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
|
||||
{
|
||||
result = new Vector3(
|
||||
MathHelper.Min(value1.X, value2.X),
|
||||
MathHelper.Min(value1.Y, value2.Y),
|
||||
MathHelper.Min(value1.Z, value2.Z));
|
||||
}
|
||||
|
||||
public static Vector3 Multiply(Vector3 value1, Vector3 value2)
|
||||
{
|
||||
value1.X *= value2.X;
|
||||
value1.Y *= value2.Y;
|
||||
value1.Z *= value2.Z;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static Vector3 Multiply(Vector3 value1, float scaleFactor)
|
||||
{
|
||||
value1.X *= scaleFactor;
|
||||
value1.Y *= scaleFactor;
|
||||
value1.Z *= scaleFactor;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static void Multiply(ref Vector3 value1, float scaleFactor, out Vector3 result)
|
||||
{
|
||||
result.X = value1.X*scaleFactor;
|
||||
result.Y = value1.Y*scaleFactor;
|
||||
result.Z = value1.Z*scaleFactor;
|
||||
}
|
||||
|
||||
public static void Multiply(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
|
||||
{
|
||||
result.X = value1.X*value2.X;
|
||||
result.Y = value1.Y*value2.Y;
|
||||
result.Z = value1.Z*value2.Z;
|
||||
}
|
||||
|
||||
public static Vector3 Negate(Vector3 value)
|
||||
{
|
||||
value = new Vector3(-value.X, -value.Y, -value.Z);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void Negate(ref Vector3 value, out Vector3 result)
|
||||
{
|
||||
result = new Vector3(-value.X, -value.Y, -value.Z);
|
||||
}
|
||||
|
||||
public void Normalize()
|
||||
{
|
||||
Normalize(ref this, out this);
|
||||
}
|
||||
|
||||
public static Vector3 Normalize(Vector3 vector)
|
||||
{
|
||||
Normalize(ref vector, out vector);
|
||||
return vector;
|
||||
}
|
||||
|
||||
public static void Normalize(ref Vector3 value, out Vector3 result)
|
||||
{
|
||||
float factor;
|
||||
Distance(ref value, ref zero, out factor);
|
||||
factor = 1f/factor;
|
||||
result.X = value.X*factor;
|
||||
result.Y = value.Y*factor;
|
||||
result.Z = value.Z*factor;
|
||||
}
|
||||
|
||||
public static Vector3 Reflect(Vector3 vector, Vector3 normal)
|
||||
{
|
||||
Vector3 result;
|
||||
Reflect(ref vector, ref normal, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void Reflect(ref Vector3 vector, ref Vector3 normal, out Vector3 result)
|
||||
{
|
||||
float dot = Dot(vector, normal);
|
||||
result.X = vector.X - ((2f*dot)*normal.X);
|
||||
result.Y = vector.Y - ((2f*dot)*normal.Y);
|
||||
result.Z = vector.Z - ((2f*dot)*normal.Z);
|
||||
}
|
||||
|
||||
public static Vector3 SmoothStep(Vector3 value1, Vector3 value2, float amount)
|
||||
{
|
||||
return new Vector3(
|
||||
MathHelper.SmoothStep(value1.X, value2.X, amount),
|
||||
MathHelper.SmoothStep(value1.Y, value2.Y, amount),
|
||||
MathHelper.SmoothStep(value1.Z, value2.Z, amount));
|
||||
}
|
||||
|
||||
public static void SmoothStep(ref Vector3 value1, ref Vector3 value2, float amount, out Vector3 result)
|
||||
{
|
||||
result = new Vector3(
|
||||
MathHelper.SmoothStep(value1.X, value2.X, amount),
|
||||
MathHelper.SmoothStep(value1.Y, value2.Y, amount),
|
||||
MathHelper.SmoothStep(value1.Z, value2.Z, amount));
|
||||
}
|
||||
|
||||
public static Vector3 Subtract(Vector3 value1, Vector3 value2)
|
||||
{
|
||||
value1.X -= value2.X;
|
||||
value1.Y -= value2.Y;
|
||||
value1.Z -= value2.Z;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static void Subtract(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
|
||||
{
|
||||
result.X = value1.X - value2.X;
|
||||
result.Y = value1.Y - value2.Y;
|
||||
result.Z = value1.Z - value2.Z;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(32);
|
||||
sb.Append("{X:");
|
||||
sb.Append(X);
|
||||
sb.Append(" Y:");
|
||||
sb.Append(Y);
|
||||
sb.Append(" Z:");
|
||||
sb.Append(Z);
|
||||
sb.Append("}");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static Vector3 Transform(Vector3 position, Matrix matrix)
|
||||
{
|
||||
Transform(ref position, ref matrix, out position);
|
||||
return position;
|
||||
}
|
||||
|
||||
public static void Transform(ref Vector3 position, ref Matrix matrix, out Vector3 result)
|
||||
{
|
||||
result =
|
||||
new Vector3((position.X*matrix.M11) + (position.Y*matrix.M21) + (position.Z*matrix.M31) + matrix.M41,
|
||||
(position.X*matrix.M12) + (position.Y*matrix.M22) + (position.Z*matrix.M32) + matrix.M42,
|
||||
(position.X*matrix.M13) + (position.Y*matrix.M23) + (position.Z*matrix.M33) + matrix.M43);
|
||||
}
|
||||
|
||||
public static void Transform(Vector3[] sourceArray, ref Matrix matrix, Vector3[] destinationArray)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static void Transform(Vector3[] sourceArray, int sourceIndex, ref Matrix matrix,
|
||||
Vector3[] destinationArray, int destinationIndex, int length)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static void TransformNormal(Vector3[] sourceArray, ref Matrix matrix, Vector3[] destinationArray)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static void TransformNormal(Vector3[] sourceArray, int sourceIndex, ref Matrix matrix,
|
||||
Vector3[] destinationArray, int destinationIndex, int length)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static Vector3 TransformNormal(Vector3 normal, Matrix matrix)
|
||||
{
|
||||
TransformNormal(ref normal, ref matrix, out normal);
|
||||
return normal;
|
||||
}
|
||||
|
||||
public static void TransformNormal(ref Vector3 normal, ref Matrix matrix, out Vector3 result)
|
||||
{
|
||||
result = new Vector3((normal.X*matrix.M11) + (normal.Y*matrix.M21) + (normal.Z*matrix.M31),
|
||||
(normal.X*matrix.M12) + (normal.Y*matrix.M22) + (normal.Z*matrix.M32),
|
||||
(normal.X*matrix.M13) + (normal.Y*matrix.M23) + (normal.Z*matrix.M33));
|
||||
}
|
||||
|
||||
#endregion Public methods
|
||||
|
||||
#region Operators
|
||||
|
||||
public static bool operator ==(Vector3 value1, Vector3 value2)
|
||||
{
|
||||
return value1.X == value2.X
|
||||
&& value1.Y == value2.Y
|
||||
&& value1.Z == value2.Z;
|
||||
}
|
||||
|
||||
public static bool operator !=(Vector3 value1, Vector3 value2)
|
||||
{
|
||||
return !(value1 == value2);
|
||||
}
|
||||
|
||||
public static Vector3 operator +(Vector3 value1, Vector3 value2)
|
||||
{
|
||||
value1.X += value2.X;
|
||||
value1.Y += value2.Y;
|
||||
value1.Z += value2.Z;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static Vector3 operator -(Vector3 value)
|
||||
{
|
||||
value = new Vector3(-value.X, -value.Y, -value.Z);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static Vector3 operator -(Vector3 value1, Vector3 value2)
|
||||
{
|
||||
value1.X -= value2.X;
|
||||
value1.Y -= value2.Y;
|
||||
value1.Z -= value2.Z;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static Vector3 operator *(Vector3 value1, Vector3 value2)
|
||||
{
|
||||
value1.X *= value2.X;
|
||||
value1.Y *= value2.Y;
|
||||
value1.Z *= value2.Z;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static Vector3 operator *(Vector3 value, float scaleFactor)
|
||||
{
|
||||
value.X *= scaleFactor;
|
||||
value.Y *= scaleFactor;
|
||||
value.Z *= scaleFactor;
|
||||
return value;
|
||||
}
|
||||
|
||||
public static Vector3 operator *(float scaleFactor, Vector3 value)
|
||||
{
|
||||
value.X *= scaleFactor;
|
||||
value.Y *= scaleFactor;
|
||||
value.Z *= scaleFactor;
|
||||
return value;
|
||||
}
|
||||
|
||||
public static Vector3 operator /(Vector3 value1, Vector3 value2)
|
||||
{
|
||||
value1.X /= value2.X;
|
||||
value1.Y /= value2.Y;
|
||||
value1.Z /= value2.Z;
|
||||
return value1;
|
||||
}
|
||||
|
||||
public static Vector3 operator /(Vector3 value, float divider)
|
||||
{
|
||||
float factor = 1/divider;
|
||||
value.X *= factor;
|
||||
value.Y *= factor;
|
||||
value.Z *= factor;
|
||||
return value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,9 @@
|
||||
/*
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
*/
|
||||
@@ -49,10 +54,8 @@ namespace FarseerPhysics.Common
|
||||
/// </summary>
|
||||
SideTooSmall
|
||||
}
|
||||
|
||||
#if !(XBOX360)
|
||||
|
||||
[DebuggerDisplay("Count = {Count} Vertices = {ToString()}")]
|
||||
#endif
|
||||
public class Vertices : List<Vector2>
|
||||
{
|
||||
public Vertices() { }
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using FarseerPhysics.Collision.Shapes;
|
||||
using FarseerPhysics.Dynamics;
|
||||
|
||||
namespace FarseerPhysics.Content
|
||||
{
|
||||
public class FixtureTemplate
|
||||
{
|
||||
public Shape Shape;
|
||||
public float Restitution;
|
||||
public float Friction;
|
||||
public string Name;
|
||||
}
|
||||
|
||||
public class BodyTemplate
|
||||
{
|
||||
public List<FixtureTemplate> Fixtures;
|
||||
public float Mass;
|
||||
public BodyType BodyType;
|
||||
|
||||
public BodyTemplate()
|
||||
{
|
||||
Fixtures = new List<FixtureTemplate>();
|
||||
}
|
||||
|
||||
public Body Create(World world)
|
||||
{
|
||||
Body body = world.CreateBody();
|
||||
body.BodyType = BodyType;
|
||||
|
||||
foreach (FixtureTemplate fixtureTemplate in Fixtures)
|
||||
{
|
||||
Fixture fixture = body.CreateFixture(fixtureTemplate.Shape);
|
||||
fixture.UserData = fixtureTemplate.Name;
|
||||
fixture.Restitution = fixtureTemplate.Restitution;
|
||||
fixture.Friction = fixtureTemplate.Friction;
|
||||
}
|
||||
|
||||
if (Mass > 0f)
|
||||
body.Mass = Mass;
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class BodyContainer : Dictionary<string, BodyTemplate> { }
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using FarseerPhysics.Common;
|
||||
using FarseerPhysics.Common.Decomposition;
|
||||
|
||||
/*namespace FarseerPhysics.Content
|
||||
{
|
||||
public struct Polygon
|
||||
{
|
||||
public Vertices Vertices;
|
||||
public bool Closed;
|
||||
|
||||
public Polygon(Vertices v, bool closed)
|
||||
{
|
||||
Vertices = v;
|
||||
Closed = closed;
|
||||
}
|
||||
}
|
||||
|
||||
public class PolygonContainer : Dictionary<string, Polygon>
|
||||
{
|
||||
public bool IsDecomposed
|
||||
{
|
||||
get { return _decomposed; }
|
||||
}
|
||||
|
||||
private bool _decomposed;
|
||||
|
||||
public void Decompose()
|
||||
{
|
||||
Dictionary<string, Polygon> containerCopy = new Dictionary<string, Polygon>(this);
|
||||
foreach (string key in containerCopy.Keys)
|
||||
{
|
||||
if (containerCopy[key].Closed)
|
||||
{
|
||||
List<Vertices> partition = Triangulate.ConvexPartition(containerCopy[key].Vertices, TriangulationAlgorithm.Bayazit);
|
||||
if (partition.Count > 1)
|
||||
{
|
||||
Remove(key);
|
||||
for (int i = 0; i < partition.Count; i++)
|
||||
{
|
||||
this[key + "_" + i.ToString()] = new Polygon(partition[i], true);
|
||||
}
|
||||
}
|
||||
_decomposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
@@ -0,0 +1,94 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using FarseerPhysics.Collision.Shapes;
|
||||
using FarseerPhysics.Common;
|
||||
using FarseerPhysics.Dynamics;
|
||||
//using Microsoft.Xna.Framework.Content;
|
||||
|
||||
/*namespace FarseerPhysics.Content
|
||||
{
|
||||
public class BodyContainerReader : ContentTypeReader<BodyContainer>
|
||||
{
|
||||
protected override BodyContainer Read(ContentReader input, BodyContainer existingInstance)
|
||||
{
|
||||
BodyContainer bodies = existingInstance ?? new BodyContainer();
|
||||
|
||||
int count = input.ReadInt32();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
string name = input.ReadString();
|
||||
BodyTemplate body = new BodyTemplate
|
||||
{
|
||||
Mass = input.ReadSingle(),
|
||||
BodyType = (BodyType)input.ReadInt32()
|
||||
};
|
||||
int fixtureCount = input.ReadInt32();
|
||||
for (int j = 0; j < fixtureCount; j++)
|
||||
{
|
||||
FixtureTemplate fixture = new FixtureTemplate
|
||||
{
|
||||
Name = input.ReadString(),
|
||||
Restitution = input.ReadSingle(),
|
||||
Friction = input.ReadSingle()
|
||||
};
|
||||
ShapeType type = (ShapeType)input.ReadInt32();
|
||||
switch (type)
|
||||
{
|
||||
case ShapeType.Circle:
|
||||
{
|
||||
float density = input.ReadSingle();
|
||||
float radius = input.ReadSingle();
|
||||
CircleShape circle = new CircleShape(radius, density);
|
||||
circle.Position = input.ReadVector2();
|
||||
fixture.Shape = circle;
|
||||
} break;
|
||||
case ShapeType.Polygon:
|
||||
{
|
||||
Vertices verts = new Vertices(Settings.MaxPolygonVertices);
|
||||
float density = input.ReadSingle();
|
||||
int verticeCount = input.ReadInt32();
|
||||
for (int k = 0; k < verticeCount; k++)
|
||||
{
|
||||
verts.Add(input.ReadVector2());
|
||||
}
|
||||
PolygonShape poly = new PolygonShape(verts, density);
|
||||
poly.MassData.Centroid = input.ReadVector2();
|
||||
fixture.Shape = poly;
|
||||
} break;
|
||||
case ShapeType.Edge:
|
||||
{
|
||||
EdgeShape edge = new EdgeShape(input.ReadVector2(), input.ReadVector2());
|
||||
edge.HasVertex0 = input.ReadBoolean();
|
||||
if (edge.HasVertex0)
|
||||
{
|
||||
edge.Vertex0 = input.ReadVector2();
|
||||
}
|
||||
edge.HasVertex3 = input.ReadBoolean();
|
||||
if (edge.HasVertex3)
|
||||
{
|
||||
edge.Vertex3 = input.ReadVector2();
|
||||
}
|
||||
fixture.Shape = edge;
|
||||
} break;
|
||||
case ShapeType.Chain:
|
||||
{
|
||||
Vertices verts = new Vertices();
|
||||
int verticeCount = input.ReadInt32();
|
||||
for (int k = 0; k < verticeCount; k++)
|
||||
{
|
||||
verts.Add(input.ReadVector2());
|
||||
}
|
||||
fixture.Shape = new ChainShape(verts);
|
||||
} break;
|
||||
}
|
||||
body.Fixtures.Add(fixture);
|
||||
}
|
||||
bodies[name] = body;
|
||||
}
|
||||
return bodies;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
@@ -0,0 +1,34 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using FarseerPhysics.Common;
|
||||
//using Microsoft.Xna.Framework.Content;
|
||||
|
||||
/*namespace FarseerPhysics.Content
|
||||
{
|
||||
public class PolygonContainerReader : ContentTypeReader<PolygonContainer>
|
||||
{
|
||||
protected override PolygonContainer Read(ContentReader input, PolygonContainer existingInstance)
|
||||
{
|
||||
PolygonContainer paths = existingInstance ?? new PolygonContainer();
|
||||
|
||||
int count = input.ReadInt32();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
string name = input.ReadString();
|
||||
bool closed = input.ReadBoolean();
|
||||
int vertsCount = input.ReadInt32();
|
||||
Vertices verts = new Vertices();
|
||||
for (int j = 0; j < vertsCount; j++)
|
||||
{
|
||||
verts.Add(input.ReadVector2());
|
||||
}
|
||||
paths[name] = new Polygon(verts, closed);
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
@@ -1,6 +1,12 @@
|
||||
using System;
|
||||
using FarseerPhysics.Dynamics;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using FarseerPhysics.Common.PhysicsLogic;
|
||||
using FarseerPhysics.Dynamics;
|
||||
|
||||
namespace FarseerPhysics.Controllers
|
||||
{
|
||||
@@ -85,10 +91,7 @@ namespace FarseerPhysics.Controllers
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public AbstractForceController()
|
||||
: base(ControllerType.AbstractForceController)
|
||||
{
|
||||
Enabled = true;
|
||||
|
||||
Strength = 1.0f;
|
||||
Position = new Vector2(0, 0);
|
||||
MaximumSpeed = 100.0f;
|
||||
@@ -115,7 +118,6 @@ namespace FarseerPhysics.Controllers
|
||||
/// </summary>
|
||||
/// <param name="mode"></param>
|
||||
public AbstractForceController(TimingModes mode)
|
||||
: base(ControllerType.AbstractForceController)
|
||||
{
|
||||
TimingMode = mode;
|
||||
switch (mode)
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using FarseerPhysics.Collision;
|
||||
using FarseerPhysics.Collision.Shapes;
|
||||
using FarseerPhysics.Common.PhysicsLogic;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Controllers
|
||||
{
|
||||
@@ -35,7 +41,7 @@ namespace FarseerPhysics.Controllers
|
||||
private Vector2 _gravity;
|
||||
private Vector2 _normal;
|
||||
private float _offset;
|
||||
private Dictionary<int, Body> _uniqueBodies = new Dictionary<int, Body>();
|
||||
private ICollection<Body> _uniqueBodies = new List<Body>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BuoyancyController"/> class.
|
||||
@@ -46,7 +52,6 @@ namespace FarseerPhysics.Controllers
|
||||
/// <param name="rotationalDragCoefficient">Rotational drag coefficient of the fluid</param>
|
||||
/// <param name="gravity">The direction gravity acts. Buoyancy force will act in opposite direction of gravity.</param>
|
||||
public BuoyancyController(AABB container, float density, float linearDragCoefficient, float rotationalDragCoefficient, Vector2 gravity)
|
||||
: base(ControllerType.BuoyancyController)
|
||||
{
|
||||
Container = container;
|
||||
_normal = new Vector2(0, 1);
|
||||
@@ -71,19 +76,17 @@ namespace FarseerPhysics.Controllers
|
||||
_uniqueBodies.Clear();
|
||||
World.QueryAABB(fixture =>
|
||||
{
|
||||
if (fixture.Body.IsStatic || !fixture.Body.Awake)
|
||||
if (fixture.Body.BodyType == BodyType.Static || !fixture.Body.Awake)
|
||||
return true;
|
||||
|
||||
if (!_uniqueBodies.ContainsKey(fixture.Body.BodyId))
|
||||
_uniqueBodies.Add(fixture.Body.BodyId, fixture.Body);
|
||||
if (!_uniqueBodies.Contains(fixture.Body))
|
||||
_uniqueBodies.Add(fixture.Body);
|
||||
|
||||
return true;
|
||||
}, ref _container);
|
||||
|
||||
foreach (KeyValuePair<int, Body> kv in _uniqueBodies)
|
||||
foreach (Body body in _uniqueBodies)
|
||||
{
|
||||
Body body = kv.Value;
|
||||
|
||||
Vector2 areac = Vector2.Zero;
|
||||
Vector2 massc = Vector2.Zero;
|
||||
float area = 0;
|
||||
|
||||
@@ -1,67 +1,28 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using FarseerPhysics.Common.PhysicsLogic;
|
||||
using FarseerPhysics.Dynamics;
|
||||
|
||||
namespace FarseerPhysics.Controllers
|
||||
{
|
||||
[Flags]
|
||||
public enum ControllerType
|
||||
{
|
||||
GravityController = (1 << 0),
|
||||
VelocityLimitController = (1 << 1),
|
||||
AbstractForceController = (1 << 2),
|
||||
BuoyancyController = (1 << 3),
|
||||
}
|
||||
|
||||
public struct ControllerFilter
|
||||
{
|
||||
public ControllerType ControllerFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Ignores the controller. The controller has no effect on this body.
|
||||
/// </summary>
|
||||
/// <param name="controller">The controller type.</param>
|
||||
public void IgnoreController(ControllerType controller)
|
||||
{
|
||||
ControllerFlags |= controller;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restore the controller. The controller affects this body.
|
||||
/// </summary>
|
||||
/// <param name="controller">The controller type.</param>
|
||||
public void RestoreController(ControllerType controller)
|
||||
{
|
||||
ControllerFlags &= ~controller;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this body ignores the the specified controller.
|
||||
/// </summary>
|
||||
/// <param name="controller">The controller type.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the body has the specified flag; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool IsControllerIgnored(ControllerType controller)
|
||||
{
|
||||
return (ControllerFlags & controller) == controller;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class Controller : FilterData
|
||||
{
|
||||
public bool Enabled;
|
||||
public World World;
|
||||
private ControllerType _type;
|
||||
public ControllerCategory ControllerCategory = ControllerCategory.Cat01;
|
||||
|
||||
public Controller(ControllerType controllerType)
|
||||
public bool Enabled = true;
|
||||
public World World { get; internal set; }
|
||||
|
||||
public Controller()
|
||||
{
|
||||
_type = controllerType;
|
||||
}
|
||||
|
||||
public override bool IsActiveOn(Body body)
|
||||
{
|
||||
if (body.ControllerFilter.IsControllerIgnored(_type))
|
||||
if (body.ControllerFilter.IsControllerIgnored(ControllerCategory))
|
||||
return false;
|
||||
|
||||
return base.IsActiveOn(body);
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using FarseerPhysics.Common.PhysicsLogic;
|
||||
using FarseerPhysics.Dynamics;
|
||||
|
||||
namespace FarseerPhysics.Controllers
|
||||
{
|
||||
@@ -14,7 +20,6 @@ namespace FarseerPhysics.Controllers
|
||||
public class GravityController : Controller
|
||||
{
|
||||
public GravityController(float strength)
|
||||
: base(ControllerType.GravityController)
|
||||
{
|
||||
Strength = strength;
|
||||
MaxRadius = float.MaxValue;
|
||||
@@ -24,7 +29,6 @@ namespace FarseerPhysics.Controllers
|
||||
}
|
||||
|
||||
public GravityController(float strength, float maxRadius, float minRadius)
|
||||
: base(ControllerType.GravityController)
|
||||
{
|
||||
MinRadius = minRadius;
|
||||
MaxRadius = maxRadius;
|
||||
@@ -52,7 +56,7 @@ namespace FarseerPhysics.Controllers
|
||||
|
||||
foreach (Body controllerBody in Bodies)
|
||||
{
|
||||
if (worldBody == controllerBody || (worldBody.IsStatic && controllerBody.IsStatic) || !controllerBody.Enabled)
|
||||
if (worldBody == controllerBody || (worldBody.BodyType == BodyType.Static && controllerBody.BodyType == BodyType.Static) || !controllerBody.Enabled)
|
||||
continue;
|
||||
|
||||
Vector2 d = controllerBody.Position - worldBody.Position;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
using FarseerPhysics.Dynamics;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Controllers
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FarseerPhysics.Common.PhysicsLogic;
|
||||
using FarseerPhysics.Dynamics;
|
||||
|
||||
namespace FarseerPhysics.Controllers
|
||||
@@ -24,7 +30,6 @@ namespace FarseerPhysics.Controllers
|
||||
/// Sets the max angular velocity to Settings.MaxRotation
|
||||
/// </summary>
|
||||
public VelocityLimitController()
|
||||
: base(ControllerType.VelocityLimitController)
|
||||
{
|
||||
MaxLinearVelocity = Settings.MaxTranslation;
|
||||
MaxAngularVelocity = Settings.MaxRotation;
|
||||
@@ -38,7 +43,6 @@ namespace FarseerPhysics.Controllers
|
||||
/// <param name="maxLinearVelocity">The max linear velocity.</param>
|
||||
/// <param name="maxAngularVelocity">The max angular velocity.</param>
|
||||
public VelocityLimitController(float maxLinearVelocity, float maxAngularVelocity)
|
||||
: base(ControllerType.VelocityLimitController)
|
||||
{
|
||||
if (maxLinearVelocity == 0 || maxLinearVelocity == float.MaxValue)
|
||||
LimitLinearVelocity = false;
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
*/
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
using FarseerPhysics.Common;
|
||||
using FarseerPhysics.Dynamics;
|
||||
|
||||
namespace FarseerPhysics.Diagnostics
|
||||
{
|
||||
/// Implement and register this class with a World to provide debug drawing of physics
|
||||
/// entities in your game.
|
||||
public abstract class DebugViewBase
|
||||
{
|
||||
protected DebugViewBase(World world)
|
||||
{
|
||||
World = world;
|
||||
}
|
||||
|
||||
protected World World { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the debug view flags.
|
||||
/// </summary>
|
||||
/// <value>The flags.</value>
|
||||
public DebugViewFlags Flags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Append flags to the current flags.
|
||||
/// </summary>
|
||||
/// <param name="flags">The flags.</param>
|
||||
public void AppendFlags(DebugViewFlags flags)
|
||||
{
|
||||
Flags |= flags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove flags from the current flags.
|
||||
/// </summary>
|
||||
/// <param name="flags">The flags.</param>
|
||||
public void RemoveFlags(DebugViewFlags flags)
|
||||
{
|
||||
Flags &= ~flags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw a closed polygon provided in CCW order.
|
||||
/// </summary>
|
||||
/// <param name="vertices">The vertices.</param>
|
||||
/// <param name="count">The vertex count.</param>
|
||||
/// <param name="color">The color value.</param>
|
||||
//public abstract void DrawPolygon(Vector2[] vertices, int count, Color color, bool closed = true);
|
||||
|
||||
/// <summary>
|
||||
/// Draw a solid closed polygon provided in CCW order.
|
||||
/// </summary>
|
||||
/// <param name="vertices">The vertices.</param>
|
||||
/// <param name="count">The vertex count.</param>
|
||||
/// <param name="color">The color value.</param>
|
||||
//public abstract void DrawSolidPolygon(Vector2[] vertices, int count, Color color);
|
||||
|
||||
/// <summary>
|
||||
/// Draw a circle.
|
||||
/// </summary>
|
||||
/// <param name="center">The center.</param>
|
||||
/// <param name="radius">The radius.</param>
|
||||
/// <param name="color">The color value.</param>
|
||||
//public abstract void DrawCircle(Vector2 center, float radius, Color color);
|
||||
|
||||
/// <summary>
|
||||
/// Draw a solid circle.
|
||||
/// </summary>
|
||||
/// <param name="center">The center.</param>
|
||||
/// <param name="radius">The radius.</param>
|
||||
/// <param name="axis">The axis.</param>
|
||||
/// <param name="color">The color value.</param>
|
||||
//public abstract void DrawSolidCircle(Vector2 center, float radius, Vector2 axis, Color color);
|
||||
|
||||
/// <summary>
|
||||
/// Draw a line segment.
|
||||
/// </summary>
|
||||
/// <param name="start">The start.</param>
|
||||
/// <param name="end">The end.</param>
|
||||
/// <param name="color">The color value.</param>
|
||||
//public abstract void DrawSegment(Vector2 start, Vector2 end, Color color);
|
||||
|
||||
/// <summary>
|
||||
/// Draw a transform. Choose your own length scale.
|
||||
/// </summary>
|
||||
/// <param name="transform">The transform.</param>
|
||||
//public abstract void DrawTransform(ref Transform transform);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace FarseerPhysics.Diagnostics
|
||||
{
|
||||
[Flags]
|
||||
public enum DebugViewFlags
|
||||
{
|
||||
/// <summary>
|
||||
/// Draw shapes.
|
||||
/// </summary>
|
||||
Shape = (1 << 0),
|
||||
|
||||
/// <summary>
|
||||
/// Draw joint connections.
|
||||
/// </summary>
|
||||
Joint = (1 << 1),
|
||||
|
||||
/// <summary>
|
||||
/// Draw axis aligned bounding boxes.
|
||||
/// </summary>
|
||||
AABB = (1 << 2),
|
||||
|
||||
/// <summary>
|
||||
/// Draw broad-phase pairs.
|
||||
/// </summary>
|
||||
//Pair = (1 << 3),
|
||||
|
||||
/// <summary>
|
||||
/// Draw center of mass frame.
|
||||
/// </summary>
|
||||
CenterOfMass = (1 << 4),
|
||||
|
||||
/// <summary>
|
||||
/// Draw useful debug data such as timings and number of bodies, joints, contacts and more.
|
||||
/// </summary>
|
||||
DebugPanel = (1 << 5),
|
||||
|
||||
/// <summary>
|
||||
/// Draw contact points between colliding bodies.
|
||||
/// </summary>
|
||||
ContactPoints = (1 << 6),
|
||||
|
||||
/// <summary>
|
||||
/// Draw contact normals. Need ContactPoints to be enabled first.
|
||||
/// </summary>
|
||||
ContactNormals = (1 << 7),
|
||||
|
||||
/// <summary>
|
||||
/// Draws the vertices of polygons.
|
||||
/// </summary>
|
||||
PolygonPoints = (1 << 8),
|
||||
|
||||
/// <summary>
|
||||
/// Draws the performance graph.
|
||||
/// </summary>
|
||||
PerformanceGraph = (1 << 9),
|
||||
|
||||
/// <summary>
|
||||
/// Draws controllers.
|
||||
/// </summary>
|
||||
Controllers = (1 << 10)
|
||||
}
|
||||
}
|
||||
+52
-35
@@ -1,4 +1,9 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FarseerPhysics.Collision.Shapes;
|
||||
using FarseerPhysics.Common;
|
||||
@@ -6,76 +11,92 @@ using FarseerPhysics.Common.Decomposition;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Factories
|
||||
namespace FarseerPhysics.Dynamics
|
||||
{
|
||||
/// <summary>
|
||||
/// An easy to use factory for creating bodies
|
||||
/// </summary>
|
||||
public static class FixtureFactory
|
||||
public partial class Body
|
||||
{
|
||||
public static Fixture AttachEdge(Vector2 start, Vector2 end, Body body, object userData = null)
|
||||
/// <summary>
|
||||
/// Creates a fixture and attach it to this body.
|
||||
/// If the density is non-zero, this function automatically updates the mass of the body.
|
||||
/// Contacts are not created until the next time step.
|
||||
/// Warning: This method is locked during callbacks.
|
||||
/// </summary>
|
||||
/// <param name="shape">The shape.</param>
|
||||
/// <param name="userData">Application specific data</param>
|
||||
/// <returns></returns>
|
||||
public virtual Fixture CreateFixture(Shape shape)
|
||||
{
|
||||
Fixture fixture = new Fixture(shape);
|
||||
Add(fixture);
|
||||
return fixture;
|
||||
}
|
||||
|
||||
public Fixture CreateEdge(Vector2 start, Vector2 end)
|
||||
{
|
||||
EdgeShape edgeShape = new EdgeShape(start, end);
|
||||
return body.CreateFixture(edgeShape, userData);
|
||||
return CreateFixture(edgeShape);
|
||||
}
|
||||
|
||||
public static Fixture AttachChainShape(Vertices vertices, Body body, object userData = null)
|
||||
public Fixture CreateChainShape(Vertices vertices)
|
||||
{
|
||||
ChainShape shape = new ChainShape(vertices);
|
||||
return body.CreateFixture(shape, userData);
|
||||
return CreateFixture(shape);
|
||||
}
|
||||
|
||||
public static Fixture AttachLoopShape(Vertices vertices, Body body, object userData = null)
|
||||
public Fixture CreateLoopShape(Vertices vertices)
|
||||
{
|
||||
ChainShape shape = new ChainShape(vertices, true);
|
||||
return body.CreateFixture(shape, userData);
|
||||
return CreateFixture(shape);
|
||||
}
|
||||
|
||||
public static Fixture AttachRectangle(float width, float height, float density, Vector2 offset, Body body, object userData = null)
|
||||
public Fixture CreateRectangle(float width, float height, float density, Vector2 offset)
|
||||
{
|
||||
Vertices rectangleVertices = PolygonTools.CreateRectangle(width / 2, height / 2);
|
||||
rectangleVertices.Translate(ref offset);
|
||||
PolygonShape rectangleShape = new PolygonShape(rectangleVertices, density);
|
||||
return body.CreateFixture(rectangleShape, userData);
|
||||
return CreateFixture(rectangleShape);
|
||||
}
|
||||
|
||||
public static Fixture AttachRectangle(float width, float height, float density, float angle, Vector2 offset, Body body, object userData = null)
|
||||
public Fixture CreateRectangle(float width, float height, float density, float rotation, Vector2 offset)
|
||||
{
|
||||
Vertices rectangleVertices = PolygonTools.CreateRectangle(width / 2, height / 2, Vector2.Zero, angle);
|
||||
Vertices rectangleVertices = PolygonTools.CreateRectangle(width / 2, height / 2, Vector2.Zero, rotation);
|
||||
rectangleVertices.Translate(ref offset);
|
||||
PolygonShape rectangleShape = new PolygonShape(rectangleVertices, density);
|
||||
return body.CreateFixture(rectangleShape, userData);
|
||||
return CreateFixture(rectangleShape);
|
||||
}
|
||||
|
||||
public static Fixture AttachCircle(float radius, float density, Body body, object userData = null)
|
||||
public Fixture CreateCircle(float radius, float density)
|
||||
{
|
||||
if (radius <= 0)
|
||||
throw new ArgumentOutOfRangeException("radius", "Radius must be more than 0 meters");
|
||||
|
||||
CircleShape circleShape = new CircleShape(radius, density);
|
||||
return body.CreateFixture(circleShape, userData);
|
||||
return CreateFixture(circleShape);
|
||||
}
|
||||
|
||||
public static Fixture AttachCircle(float radius, float density, Body body, Vector2 offset, object userData = null)
|
||||
public Fixture CreateCircle(float radius, float density, Vector2 offset)
|
||||
{
|
||||
if (radius <= 0)
|
||||
throw new ArgumentOutOfRangeException("radius", "Radius must be more than 0 meters");
|
||||
|
||||
CircleShape circleShape = new CircleShape(radius, density);
|
||||
circleShape.Position = offset;
|
||||
return body.CreateFixture(circleShape, userData);
|
||||
return CreateFixture(circleShape);
|
||||
}
|
||||
|
||||
public static Fixture AttachPolygon(Vertices vertices, float density, Body body, object userData = null)
|
||||
public Fixture CreatePolygon(Vertices vertices, float density)
|
||||
{
|
||||
if (vertices.Count <= 1)
|
||||
throw new ArgumentOutOfRangeException("vertices", "Too few points to be a polygon");
|
||||
|
||||
PolygonShape polygon = new PolygonShape(vertices, density);
|
||||
return body.CreateFixture(polygon, userData);
|
||||
return CreateFixture(polygon);
|
||||
}
|
||||
|
||||
public static Fixture AttachEllipse(float xRadius, float yRadius, int edges, float density, Body body, object userData = null)
|
||||
public Fixture CreateEllipse(float xRadius, float yRadius, int edges, float density)
|
||||
{
|
||||
if (xRadius <= 0)
|
||||
throw new ArgumentOutOfRangeException("xRadius", "X-radius must be more than 0");
|
||||
@@ -85,10 +106,10 @@ namespace FarseerPhysics.Factories
|
||||
|
||||
Vertices ellipseVertices = PolygonTools.CreateEllipse(xRadius, yRadius, edges);
|
||||
PolygonShape polygonShape = new PolygonShape(ellipseVertices, density);
|
||||
return body.CreateFixture(polygonShape, userData);
|
||||
return CreateFixture(polygonShape);
|
||||
}
|
||||
|
||||
public static List<Fixture> AttachCompoundPolygon(List<Vertices> list, float density, Body body, object userData = null)
|
||||
public List<Fixture> CreateCompoundPolygon(List<Vertices> list, float density)
|
||||
{
|
||||
List<Fixture> res = new List<Fixture>(list.Count);
|
||||
|
||||
@@ -98,40 +119,36 @@ namespace FarseerPhysics.Factories
|
||||
if (vertices.Count == 2)
|
||||
{
|
||||
EdgeShape shape = new EdgeShape(vertices[0], vertices[1]);
|
||||
res.Add(body.CreateFixture(shape, userData));
|
||||
res.Add(CreateFixture(shape));
|
||||
}
|
||||
else
|
||||
{
|
||||
PolygonShape shape = new PolygonShape(vertices, density);
|
||||
res.Add(body.CreateFixture(shape, userData));
|
||||
res.Add(CreateFixture(shape));
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static Fixture AttachLineArc(float radians, int sides, float radius, Vector2 position, float angle, bool closed, Body body)
|
||||
public Fixture CreateLineArc(float radians, int sides, float radius, bool closed)
|
||||
{
|
||||
Vertices arc = PolygonTools.CreateArc(radians, sides, radius);
|
||||
arc.Rotate((MathHelper.Pi - radians) / 2 + angle);
|
||||
arc.Translate(ref position);
|
||||
|
||||
return closed ? AttachLoopShape(arc, body) : AttachChainShape(arc, body);
|
||||
arc.Rotate((MathHelper.Pi - radians) / 2);
|
||||
return closed ? CreateLoopShape(arc) : CreateChainShape(arc);
|
||||
}
|
||||
|
||||
public static List<Fixture> AttachSolidArc(float density, float radians, int sides, float radius, Vector2 position, float angle, Body body)
|
||||
public List<Fixture> CreateSolidArc(float density, float radians, int sides, float radius)
|
||||
{
|
||||
Vertices arc = PolygonTools.CreateArc(radians, sides, radius);
|
||||
arc.Rotate((MathHelper.Pi - radians) / 2 + angle);
|
||||
|
||||
arc.Translate(ref position);
|
||||
arc.Rotate((MathHelper.Pi - radians) / 2);
|
||||
|
||||
//Close the arc
|
||||
arc.Add(arc[0]);
|
||||
|
||||
List<Vertices> triangles = Triangulate.ConvexPartition(arc, TriangulationAlgorithm.Earclip);
|
||||
|
||||
return AttachCompoundPolygon(triangles, density, body);
|
||||
return CreateCompoundPolygon(triangles, density);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,49 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
/*
|
||||
* Farseer Physics Engine:
|
||||
* Copyright (c) 2012 Ian Qvist
|
||||
*
|
||||
* Original source Box2D:
|
||||
* Copyright (c) 2006-2011 Erin Catto http://www.box2d.org
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
namespace FarseerPhysics
|
||||
{
|
||||
/// <summary>
|
||||
/// The body type.
|
||||
/// </summary>
|
||||
public enum BodyType
|
||||
{
|
||||
/// <summary>
|
||||
/// Zero velocity, may be manually moved. Note: even static bodies have mass.
|
||||
/// </summary>
|
||||
Static,
|
||||
/// <summary>
|
||||
/// Zero mass, non-zero velocity set by user, moved by solver
|
||||
/// </summary>
|
||||
Kinematic,
|
||||
/// <summary>
|
||||
/// Positive mass, non-zero velocity determined by forces, moved by solver
|
||||
/// </summary>
|
||||
Dynamic,
|
||||
}
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FarseerPhysics.Collision.Shapes;
|
||||
using FarseerPhysics.Common;
|
||||
using FarseerPhysics.Dynamics.Contacts;
|
||||
using FarseerPhysics.Factories;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Dynamics
|
||||
{
|
||||
/// <summary>
|
||||
/// A type of body that supports multiple fixtures that can break apart.
|
||||
/// </summary>
|
||||
public class BreakableBody
|
||||
{
|
||||
private float[] _angularVelocitiesCache = new float[8];
|
||||
private bool _break;
|
||||
private Vector2[] _velocitiesCache = new Vector2[8];
|
||||
private World _world;
|
||||
|
||||
public BreakableBody(IEnumerable<Vertices> vertices, World world, float density)
|
||||
{
|
||||
_world = world;
|
||||
_world.ContactManager.PostSolve += PostSolve;
|
||||
MainBody = new Body(_world);
|
||||
MainBody.BodyType = BodyType.Dynamic;
|
||||
|
||||
foreach (Vertices part in vertices)
|
||||
{
|
||||
PolygonShape polygonShape = new PolygonShape(part, density);
|
||||
Fixture fixture = MainBody.CreateFixture(polygonShape);
|
||||
Parts.Add(fixture);
|
||||
}
|
||||
}
|
||||
|
||||
public BreakableBody(IEnumerable<Shape> shapes, World world)
|
||||
{
|
||||
_world = world;
|
||||
_world.ContactManager.PostSolve += PostSolve;
|
||||
MainBody = new Body(_world);
|
||||
MainBody.BodyType = BodyType.Dynamic;
|
||||
|
||||
foreach (Shape part in shapes)
|
||||
{
|
||||
Fixture fixture = MainBody.CreateFixture(part);
|
||||
Parts.Add(fixture);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Broken;
|
||||
public Body MainBody;
|
||||
public List<Fixture> Parts = new List<Fixture>(8);
|
||||
|
||||
/// <summary>
|
||||
/// The force needed to break the body apart.
|
||||
/// Default: 500
|
||||
/// </summary>
|
||||
public float Strength = 500.0f;
|
||||
|
||||
private void PostSolve(Contact contact, ContactVelocityConstraint impulse)
|
||||
{
|
||||
if (!Broken)
|
||||
{
|
||||
if (Parts.Contains(contact.FixtureA) || Parts.Contains(contact.FixtureB))
|
||||
{
|
||||
float maxImpulse = 0.0f;
|
||||
int count = contact.Manifold.PointCount;
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
maxImpulse = Math.Max(maxImpulse, impulse.points[i].normalImpulse);
|
||||
}
|
||||
|
||||
if (maxImpulse > Strength)
|
||||
{
|
||||
// Flag the body for breaking.
|
||||
_break = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (_break)
|
||||
{
|
||||
Decompose();
|
||||
Broken = true;
|
||||
_break = false;
|
||||
}
|
||||
|
||||
// Cache velocities to improve movement on breakage.
|
||||
if (Broken == false)
|
||||
{
|
||||
//Enlarge the cache if needed
|
||||
if (Parts.Count > _angularVelocitiesCache.Length)
|
||||
{
|
||||
_velocitiesCache = new Vector2[Parts.Count];
|
||||
_angularVelocitiesCache = new float[Parts.Count];
|
||||
}
|
||||
|
||||
//Cache the linear and angular velocities.
|
||||
for (int i = 0; i < Parts.Count; i++)
|
||||
{
|
||||
_velocitiesCache[i] = Parts[i].Body.LinearVelocity;
|
||||
_angularVelocitiesCache[i] = Parts[i].Body.AngularVelocity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Decompose()
|
||||
{
|
||||
//Unsubsribe from the PostSolve delegate
|
||||
_world.ContactManager.PostSolve -= PostSolve;
|
||||
|
||||
for (int i = 0; i < Parts.Count; i++)
|
||||
{
|
||||
Fixture oldFixture = Parts[i];
|
||||
|
||||
Shape shape = oldFixture.Shape.Clone();
|
||||
object userData = oldFixture.UserData;
|
||||
|
||||
MainBody.DestroyFixture(oldFixture);
|
||||
|
||||
Body body = BodyFactory.CreateBody(_world);
|
||||
body.BodyType = BodyType.Dynamic;
|
||||
body.Position = MainBody.Position;
|
||||
body.Rotation = MainBody.Rotation;
|
||||
body.UserData = MainBody.UserData;
|
||||
|
||||
Fixture newFixture = body.CreateFixture(shape);
|
||||
newFixture.UserData = userData;
|
||||
Parts[i] = newFixture;
|
||||
|
||||
body.AngularVelocity = _angularVelocitiesCache[i];
|
||||
body.LinearVelocity = _velocitiesCache[i];
|
||||
}
|
||||
|
||||
_world.RemoveBody(MainBody);
|
||||
_world.RemoveBreakableBody(this);
|
||||
}
|
||||
|
||||
public void Break()
|
||||
{
|
||||
_break = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user