(61d00a474) v0.9.7.1

This commit is contained in:
Regalis
2020-03-04 13:04:10 +01:00
parent 3c50efa5c9
commit 3c09ebe02f
5086 changed files with 786063 additions and 295871 deletions
@@ -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;
@@ -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/
*
@@ -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);
@@ -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/
*
@@ -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/
*
@@ -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/
*
@@ -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/
*
@@ -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 @@
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
@@ -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
{
@@ -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;
@@ -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() { }