diff options
Diffstat (limited to 'libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision')
17 files changed, 3346 insertions, 3346 deletions
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ContinuousConvexCollision.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ContinuousConvexCollision.cs index 497f220..d011ef2 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ContinuousConvexCollision.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ContinuousConvexCollision.cs | |||
@@ -1,199 +1,199 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | /// <summary> | 29 | /// <summary> |
30 | /// ContinuousConvexCollision implements angular and linear time of impact for convex objects. | 30 | /// ContinuousConvexCollision implements angular and linear time of impact for convex objects. |
31 | /// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis). | 31 | /// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis). |
32 | /// Algorithm operates in worldspace, in order to keep inbetween motion globally consistent. | 32 | /// Algorithm operates in worldspace, in order to keep inbetween motion globally consistent. |
33 | /// It uses GJK at the moment. Future improvement would use minkowski sum / supporting vertex, merging innerloops | 33 | /// It uses GJK at the moment. Future improvement would use minkowski sum / supporting vertex, merging innerloops |
34 | /// </summary> | 34 | /// </summary> |
35 | public class ContinuousConvexCollision : IConvexCast | 35 | public class ContinuousConvexCollision : IConvexCast |
36 | { | 36 | { |
37 | /// <summary> | 37 | /// <summary> |
38 | /// This maximum should not be necessary. It allows for untested/degenerate cases in production code. | 38 | /// This maximum should not be necessary. It allows for untested/degenerate cases in production code. |
39 | /// You don't want your game ever to lock-up. | 39 | /// You don't want your game ever to lock-up. |
40 | /// </summary> | 40 | /// </summary> |
41 | private const int MaxIterations = 1000; | 41 | private const int MaxIterations = 1000; |
42 | 42 | ||
43 | private ISimplexSolver _simplexSolver; | 43 | private ISimplexSolver _simplexSolver; |
44 | private IConvexPenetrationDepthSolver _penetrationDepthSolver; | 44 | private IConvexPenetrationDepthSolver _penetrationDepthSolver; |
45 | private ConvexShape _convexA; | 45 | private ConvexShape _convexA; |
46 | private ConvexShape _convexB; | 46 | private ConvexShape _convexB; |
47 | 47 | ||
48 | public ContinuousConvexCollision(ConvexShape convexA, ConvexShape convexB, | 48 | public ContinuousConvexCollision(ConvexShape convexA, ConvexShape convexB, |
49 | ISimplexSolver simplexSolver, IConvexPenetrationDepthSolver penetrationDepthSolver) | 49 | ISimplexSolver simplexSolver, IConvexPenetrationDepthSolver penetrationDepthSolver) |
50 | { | 50 | { |
51 | _simplexSolver = simplexSolver; | 51 | _simplexSolver = simplexSolver; |
52 | _penetrationDepthSolver = penetrationDepthSolver; | 52 | _penetrationDepthSolver = penetrationDepthSolver; |
53 | _convexA = convexA; | 53 | _convexA = convexA; |
54 | _convexB = convexB; | 54 | _convexB = convexB; |
55 | } | 55 | } |
56 | 56 | ||
57 | public bool CalcTimeOfImpact(Matrix fromA, Matrix toA, Matrix fromB, Matrix toB, CastResult result) | 57 | public bool CalcTimeOfImpact(Matrix fromA, Matrix toA, Matrix fromB, Matrix toB, CastResult result) |
58 | { | 58 | { |
59 | _simplexSolver.Reset(); | 59 | _simplexSolver.Reset(); |
60 | 60 | ||
61 | // compute linear and angular velocity for this interval, to interpolate | 61 | // compute linear and angular velocity for this interval, to interpolate |
62 | Vector3 linVelA = new Vector3(), angVelA = new Vector3(), linVelB = new Vector3(), angVelB = new Vector3(); | 62 | Vector3 linVelA = new Vector3(), angVelA = new Vector3(), linVelB = new Vector3(), angVelB = new Vector3(); |
63 | TransformUtil.CalculateVelocity(fromA, toA, 1f, ref linVelA, ref angVelA); | 63 | TransformUtil.CalculateVelocity(fromA, toA, 1f, ref linVelA, ref angVelA); |
64 | TransformUtil.CalculateVelocity(fromB, toB, 1f, ref linVelB, ref angVelB); | 64 | TransformUtil.CalculateVelocity(fromB, toB, 1f, ref linVelB, ref angVelB); |
65 | 65 | ||
66 | float boundingRadiusA = _convexA.GetAngularMotionDisc(); | 66 | float boundingRadiusA = _convexA.GetAngularMotionDisc(); |
67 | float boundingRadiusB = _convexB.GetAngularMotionDisc(); | 67 | float boundingRadiusB = _convexB.GetAngularMotionDisc(); |
68 | 68 | ||
69 | float maxAngularProjectedVelocity = angVelA.Length() * boundingRadiusA + | 69 | float maxAngularProjectedVelocity = angVelA.Length() * boundingRadiusA + |
70 | angVelB.Length() * boundingRadiusB; | 70 | angVelB.Length() * boundingRadiusB; |
71 | 71 | ||
72 | float radius = 0.001f; | 72 | float radius = 0.001f; |
73 | 73 | ||
74 | float lambda = 0f; | 74 | float lambda = 0f; |
75 | Vector3 v = new Vector3(1f, 0f, 0f); | 75 | Vector3 v = new Vector3(1f, 0f, 0f); |
76 | 76 | ||
77 | int maxIter = MaxIterations; | 77 | int maxIter = MaxIterations; |
78 | 78 | ||
79 | Vector3 n = new Vector3(); | 79 | Vector3 n = new Vector3(); |
80 | bool hasResult = false; | 80 | bool hasResult = false; |
81 | Vector3 c; | 81 | Vector3 c; |
82 | 82 | ||
83 | float lastLambda = lambda; | 83 | float lastLambda = lambda; |
84 | //float epsilon = 0.001f; | 84 | //float epsilon = 0.001f; |
85 | 85 | ||
86 | int numIter = 0; | 86 | int numIter = 0; |
87 | //first solution, using GJK | 87 | //first solution, using GJK |
88 | 88 | ||
89 | 89 | ||
90 | Matrix identityTrans = Matrix.Identity; | 90 | Matrix identityTrans = Matrix.Identity; |
91 | 91 | ||
92 | SphereShape raySphere = new SphereShape(0f); | 92 | SphereShape raySphere = new SphereShape(0f); |
93 | raySphere.Margin=0f; | 93 | raySphere.Margin=0f; |
94 | 94 | ||
95 | 95 | ||
96 | //result.drawCoordSystem(sphereTr); | 96 | //result.drawCoordSystem(sphereTr); |
97 | 97 | ||
98 | PointCollector pointCollector1 = new PointCollector(); | 98 | PointCollector pointCollector1 = new PointCollector(); |
99 | 99 | ||
100 | GjkPairDetector gjk = new GjkPairDetector(_convexA, _convexB, (VoronoiSimplexSolver)_simplexSolver, _penetrationDepthSolver); | 100 | GjkPairDetector gjk = new GjkPairDetector(_convexA, _convexB, (VoronoiSimplexSolver)_simplexSolver, _penetrationDepthSolver); |
101 | GjkPairDetector.ClosestPointInput input = new DiscreteCollisionDetectorInterface.ClosestPointInput(); | 101 | GjkPairDetector.ClosestPointInput input = new DiscreteCollisionDetectorInterface.ClosestPointInput(); |
102 | 102 | ||
103 | //we don't use margins during CCD | 103 | //we don't use margins during CCD |
104 | gjk.setIgnoreMargin(true); | 104 | gjk.setIgnoreMargin(true); |
105 | 105 | ||
106 | input.TransformA = fromA; | 106 | input.TransformA = fromA; |
107 | input.TransformB = fromB; | 107 | input.TransformB = fromB; |
108 | 108 | ||
109 | DiscreteCollisionDetectorInterface.Result r = (DiscreteCollisionDetectorInterface.Result)pointCollector1; | 109 | DiscreteCollisionDetectorInterface.Result r = (DiscreteCollisionDetectorInterface.Result)pointCollector1; |
110 | gjk.GetClosestPoints(input, r, null); | 110 | gjk.GetClosestPoints(input, r, null); |
111 | 111 | ||
112 | hasResult = pointCollector1.HasResult; | 112 | hasResult = pointCollector1.HasResult; |
113 | c = pointCollector1.PointInWorld; | 113 | c = pointCollector1.PointInWorld; |
114 | 114 | ||
115 | if (hasResult) | 115 | if (hasResult) |
116 | { | 116 | { |
117 | float dist; | 117 | float dist; |
118 | dist = pointCollector1.Distance; | 118 | dist = pointCollector1.Distance; |
119 | n = pointCollector1.NormalOnBInWorld; | 119 | n = pointCollector1.NormalOnBInWorld; |
120 | 120 | ||
121 | //not close enough | 121 | //not close enough |
122 | while (dist > radius) | 122 | while (dist > radius) |
123 | { | 123 | { |
124 | numIter++; | 124 | numIter++; |
125 | if (numIter > maxIter) | 125 | if (numIter > maxIter) |
126 | return false; //todo: report a failure | 126 | return false; //todo: report a failure |
127 | 127 | ||
128 | float dLambda = 0f; | 128 | float dLambda = 0f; |
129 | 129 | ||
130 | //calculate safe moving fraction from distance / (linear+rotational velocity) | 130 | //calculate safe moving fraction from distance / (linear+rotational velocity) |
131 | 131 | ||
132 | //float clippedDist = GEN_min(angularConservativeRadius,dist); | 132 | //float clippedDist = GEN_min(angularConservativeRadius,dist); |
133 | //float clippedDist = dist; | 133 | //float clippedDist = dist; |
134 | 134 | ||
135 | float projectedLinearVelocity = Vector3.Dot(linVelB - linVelA, n); | 135 | float projectedLinearVelocity = Vector3.Dot(linVelB - linVelA, n); |
136 | 136 | ||
137 | dLambda = dist / (projectedLinearVelocity + maxAngularProjectedVelocity); | 137 | dLambda = dist / (projectedLinearVelocity + maxAngularProjectedVelocity); |
138 | 138 | ||
139 | lambda = lambda + dLambda; | 139 | lambda = lambda + dLambda; |
140 | 140 | ||
141 | if (lambda > 1f) return false; | 141 | if (lambda > 1f) return false; |
142 | if (lambda < 0f) return false; | 142 | if (lambda < 0f) return false; |
143 | 143 | ||
144 | //todo: next check with relative epsilon | 144 | //todo: next check with relative epsilon |
145 | if (lambda <= lastLambda) | 145 | if (lambda <= lastLambda) |
146 | break; | 146 | break; |
147 | lastLambda = lambda; | 147 | lastLambda = lambda; |
148 | 148 | ||
149 | 149 | ||
150 | //interpolate to next lambda | 150 | //interpolate to next lambda |
151 | Matrix interpolatedTransA = new Matrix(), interpolatedTransB = new Matrix(), relativeTrans; | 151 | Matrix interpolatedTransA = new Matrix(), interpolatedTransB = new Matrix(), relativeTrans; |
152 | 152 | ||
153 | TransformUtil.IntegrateTransform(fromA, linVelA, angVelA, lambda, ref interpolatedTransA); | 153 | TransformUtil.IntegrateTransform(fromA, linVelA, angVelA, lambda, ref interpolatedTransA); |
154 | TransformUtil.IntegrateTransform(fromB, linVelB, angVelB, lambda, ref interpolatedTransB); | 154 | TransformUtil.IntegrateTransform(fromB, linVelB, angVelB, lambda, ref interpolatedTransB); |
155 | 155 | ||
156 | relativeTrans = MathHelper.InverseTimes(interpolatedTransB, interpolatedTransA); | 156 | relativeTrans = MathHelper.InverseTimes(interpolatedTransB, interpolatedTransA); |
157 | 157 | ||
158 | result.DebugDraw(lambda); | 158 | result.DebugDraw(lambda); |
159 | 159 | ||
160 | PointCollector pointCollector = new PointCollector(); | 160 | PointCollector pointCollector = new PointCollector(); |
161 | gjk = new GjkPairDetector(_convexA, _convexB, (VoronoiSimplexSolver)_simplexSolver, _penetrationDepthSolver); | 161 | gjk = new GjkPairDetector(_convexA, _convexB, (VoronoiSimplexSolver)_simplexSolver, _penetrationDepthSolver); |
162 | input = new DiscreteCollisionDetectorInterface.ClosestPointInput(); | 162 | input = new DiscreteCollisionDetectorInterface.ClosestPointInput(); |
163 | input.TransformA = interpolatedTransA; | 163 | input.TransformA = interpolatedTransA; |
164 | input.TransformB = interpolatedTransB; | 164 | input.TransformB = interpolatedTransB; |
165 | 165 | ||
166 | // !!!!!!!!!! | 166 | // !!!!!!!!!! |
167 | r = (DiscreteCollisionDetectorInterface.Result)pointCollector1; | 167 | r = (DiscreteCollisionDetectorInterface.Result)pointCollector1; |
168 | gjk.GetClosestPoints(input, r, null); | 168 | gjk.GetClosestPoints(input, r, null); |
169 | 169 | ||
170 | if (pointCollector.HasResult) | 170 | if (pointCollector.HasResult) |
171 | { | 171 | { |
172 | if (pointCollector.Distance < 0f) | 172 | if (pointCollector.Distance < 0f) |
173 | { | 173 | { |
174 | //degenerate ?! | 174 | //degenerate ?! |
175 | result.Fraction = lastLambda; | 175 | result.Fraction = lastLambda; |
176 | result.Normal = n; | 176 | result.Normal = n; |
177 | return true; | 177 | return true; |
178 | } | 178 | } |
179 | c = pointCollector.PointInWorld; | 179 | c = pointCollector.PointInWorld; |
180 | 180 | ||
181 | dist = pointCollector.Distance; | 181 | dist = pointCollector.Distance; |
182 | } | 182 | } |
183 | else | 183 | else |
184 | { | 184 | { |
185 | //?? | 185 | //?? |
186 | return false; | 186 | return false; |
187 | } | 187 | } |
188 | 188 | ||
189 | } | 189 | } |
190 | 190 | ||
191 | result.Fraction = lambda; | 191 | result.Fraction = lambda; |
192 | result.Normal = n; | 192 | result.Normal = n; |
193 | return true; | 193 | return true; |
194 | } | 194 | } |
195 | 195 | ||
196 | return false; | 196 | return false; |
197 | } | 197 | } |
198 | } | 198 | } |
199 | } | 199 | } |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ConvexCast.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ConvexCast.cs index 9e88a7e..93501ed 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ConvexCast.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ConvexCast.cs | |||
@@ -1,73 +1,73 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | 29 | ||
30 | /// <summary> | 30 | /// <summary> |
31 | /// CastResult stores the closest result | 31 | /// CastResult stores the closest result |
32 | /// alternatively, add a callback method to decide about closest/all results | 32 | /// alternatively, add a callback method to decide about closest/all results |
33 | /// </summary> | 33 | /// </summary> |
34 | public class CastResult | 34 | public class CastResult |
35 | { | 35 | { |
36 | private Vector3 _normal; | 36 | private Vector3 _normal; |
37 | private float _fraction; | 37 | private float _fraction; |
38 | private Matrix _hitTransformA; | 38 | private Matrix _hitTransformA; |
39 | private Matrix _hitTransformB; | 39 | private Matrix _hitTransformB; |
40 | private IDebugDraw _debugDrawer; | 40 | private IDebugDraw _debugDrawer; |
41 | 41 | ||
42 | public CastResult() | 42 | public CastResult() |
43 | { | 43 | { |
44 | _fraction = 1e30f; | 44 | _fraction = 1e30f; |
45 | } | 45 | } |
46 | 46 | ||
47 | public Vector3 Normal { get { return _normal; } set { _normal = value; } } | 47 | public Vector3 Normal { get { return _normal; } set { _normal = value; } } |
48 | public float Fraction { get { return _fraction; } set { _fraction = value; } } | 48 | public float Fraction { get { return _fraction; } set { _fraction = value; } } |
49 | public Matrix HitTransformA { get { return _hitTransformA; } set { _hitTransformA = value; } } | 49 | public Matrix HitTransformA { get { return _hitTransformA; } set { _hitTransformA = value; } } |
50 | public Matrix HitTransformB { get { return _hitTransformB; } set { _hitTransformB = value; } } | 50 | public Matrix HitTransformB { get { return _hitTransformB; } set { _hitTransformB = value; } } |
51 | public IDebugDraw DebugDrawer { get { return _debugDrawer; } set { _debugDrawer = value; } } | 51 | public IDebugDraw DebugDrawer { get { return _debugDrawer; } set { _debugDrawer = value; } } |
52 | 52 | ||
53 | public virtual void DebugDraw(float fraction) { } | 53 | public virtual void DebugDraw(float fraction) { } |
54 | public virtual void DrawCoordSystem(Matrix trans) { } | 54 | public virtual void DrawCoordSystem(Matrix trans) { } |
55 | } | 55 | } |
56 | 56 | ||
57 | /// <summary> | 57 | /// <summary> |
58 | /// ConvexCast is an interface for Casting | 58 | /// ConvexCast is an interface for Casting |
59 | /// </summary> | 59 | /// </summary> |
60 | public interface IConvexCast | 60 | public interface IConvexCast |
61 | { | 61 | { |
62 | /// <summary> | 62 | /// <summary> |
63 | /// cast a convex against another convex object | 63 | /// cast a convex against another convex object |
64 | /// </summary> | 64 | /// </summary> |
65 | /// <param name="fromA"></param> | 65 | /// <param name="fromA"></param> |
66 | /// <param name="toA"></param> | 66 | /// <param name="toA"></param> |
67 | /// <param name="fromB"></param> | 67 | /// <param name="fromB"></param> |
68 | /// <param name="toB"></param> | 68 | /// <param name="toB"></param> |
69 | /// <param name="result"></param> | 69 | /// <param name="result"></param> |
70 | /// <returns></returns> | 70 | /// <returns></returns> |
71 | bool CalcTimeOfImpact(Matrix fromA, Matrix toA, Matrix fromB, Matrix toB, CastResult result); | 71 | bool CalcTimeOfImpact(Matrix fromA, Matrix toA, Matrix fromB, Matrix toB, CastResult result); |
72 | } | 72 | } |
73 | } | 73 | } |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/DiscreteCollisionDetectorInterface.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/DiscreteCollisionDetectorInterface.cs index fae2557..5b07d9b 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/DiscreteCollisionDetectorInterface.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/DiscreteCollisionDetectorInterface.cs | |||
@@ -1,117 +1,117 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | public abstract class DiscreteCollisionDetectorInterface | 29 | public abstract class DiscreteCollisionDetectorInterface |
30 | { | 30 | { |
31 | public abstract class Result | 31 | public abstract class Result |
32 | { | 32 | { |
33 | public abstract void SetShapeIdentifiers(int partIdA, int indexA, int partIdB, int indexB); | 33 | public abstract void SetShapeIdentifiers(int partIdA, int indexA, int partIdB, int indexB); |
34 | public abstract void AddContactPoint(Vector3 normalOnBInWorld, Vector3 pointInWorld, float depth); | 34 | public abstract void AddContactPoint(Vector3 normalOnBInWorld, Vector3 pointInWorld, float depth); |
35 | } | 35 | } |
36 | 36 | ||
37 | public class ClosestPointInput | 37 | public class ClosestPointInput |
38 | { | 38 | { |
39 | private float _maximumDistanceSquared; | 39 | private float _maximumDistanceSquared; |
40 | private Matrix _transformA, _transformB; | 40 | private Matrix _transformA, _transformB; |
41 | 41 | ||
42 | #region Properties | 42 | #region Properties |
43 | public Matrix TransformB | 43 | public Matrix TransformB |
44 | { | 44 | { |
45 | get { return _transformB; } | 45 | get { return _transformB; } |
46 | set { _transformB = value; } | 46 | set { _transformB = value; } |
47 | } | 47 | } |
48 | 48 | ||
49 | public Matrix TransformA | 49 | public Matrix TransformA |
50 | { | 50 | { |
51 | get { return _transformA; } | 51 | get { return _transformA; } |
52 | set { _transformA = value; } | 52 | set { _transformA = value; } |
53 | } | 53 | } |
54 | 54 | ||
55 | public float MaximumDistanceSquared | 55 | public float MaximumDistanceSquared |
56 | { | 56 | { |
57 | get { return _maximumDistanceSquared; } | 57 | get { return _maximumDistanceSquared; } |
58 | set { _maximumDistanceSquared = value; } | 58 | set { _maximumDistanceSquared = value; } |
59 | } | 59 | } |
60 | #endregion | 60 | #endregion |
61 | 61 | ||
62 | public ClosestPointInput() | 62 | public ClosestPointInput() |
63 | { | 63 | { |
64 | _maximumDistanceSquared = 1e30f; | 64 | _maximumDistanceSquared = 1e30f; |
65 | } | 65 | } |
66 | } | 66 | } |
67 | 67 | ||
68 | public abstract void GetClosestPoints(ClosestPointInput input, Result output, IDebugDraw debugDraw); | 68 | public abstract void GetClosestPoints(ClosestPointInput input, Result output, IDebugDraw debugDraw); |
69 | } | 69 | } |
70 | 70 | ||
71 | public class StorageResult : DiscreteCollisionDetectorInterface.Result | 71 | public class StorageResult : DiscreteCollisionDetectorInterface.Result |
72 | { | 72 | { |
73 | private Vector3 _closestPointInB; | 73 | private Vector3 _closestPointInB; |
74 | private Vector3 _normalOnSurfaceB; | 74 | private Vector3 _normalOnSurfaceB; |
75 | private float _distance; //negative means penetration ! | 75 | private float _distance; //negative means penetration ! |
76 | 76 | ||
77 | #region Properties | 77 | #region Properties |
78 | 78 | ||
79 | public float Distance | 79 | public float Distance |
80 | { | 80 | { |
81 | get { return _distance; } | 81 | get { return _distance; } |
82 | set { _distance = value; } | 82 | set { _distance = value; } |
83 | } | 83 | } |
84 | public Vector3 NormalOnSurfaceB | 84 | public Vector3 NormalOnSurfaceB |
85 | { | 85 | { |
86 | get { return _normalOnSurfaceB; } | 86 | get { return _normalOnSurfaceB; } |
87 | set { _normalOnSurfaceB = value; } | 87 | set { _normalOnSurfaceB = value; } |
88 | } | 88 | } |
89 | public Vector3 ClosestPointInB | 89 | public Vector3 ClosestPointInB |
90 | { | 90 | { |
91 | get { return _closestPointInB; } | 91 | get { return _closestPointInB; } |
92 | set { _closestPointInB = value; } | 92 | set { _closestPointInB = value; } |
93 | } | 93 | } |
94 | 94 | ||
95 | #endregion | 95 | #endregion |
96 | 96 | ||
97 | public StorageResult() | 97 | public StorageResult() |
98 | { | 98 | { |
99 | _distance = 1e30f; | 99 | _distance = 1e30f; |
100 | } | 100 | } |
101 | 101 | ||
102 | public override void AddContactPoint(Vector3 normalOnBInWorld, Vector3 pointInWorld, float depth) | 102 | public override void AddContactPoint(Vector3 normalOnBInWorld, Vector3 pointInWorld, float depth) |
103 | { | 103 | { |
104 | if (depth < _distance) | 104 | if (depth < _distance) |
105 | { | 105 | { |
106 | _normalOnSurfaceB = normalOnBInWorld; | 106 | _normalOnSurfaceB = normalOnBInWorld; |
107 | _closestPointInB = pointInWorld; | 107 | _closestPointInB = pointInWorld; |
108 | _distance = depth; | 108 | _distance = depth; |
109 | } | 109 | } |
110 | } | 110 | } |
111 | 111 | ||
112 | public override void SetShapeIdentifiers(int partId0, int index0, int partId1, int index1) | 112 | public override void SetShapeIdentifiers(int partId0, int index0, int partId1, int index1) |
113 | { | 113 | { |
114 | throw new Exception("The method or operation is not implemented."); | 114 | throw new Exception("The method or operation is not implemented."); |
115 | } | 115 | } |
116 | } | 116 | } |
117 | } | 117 | } |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkConvexCast.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkConvexCast.cs index 4ee9599..ea7d335 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkConvexCast.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkConvexCast.cs | |||
@@ -1,176 +1,176 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | /// <summary> | 29 | /// <summary> |
30 | /// GjkConvexCast performs a raycast on a convex object using support mapping. | 30 | /// GjkConvexCast performs a raycast on a convex object using support mapping. |
31 | /// </summary> | 31 | /// </summary> |
32 | public class GjkConvexCast : IConvexCast | 32 | public class GjkConvexCast : IConvexCast |
33 | { | 33 | { |
34 | private VoronoiSimplexSolver _simplexSolver; | 34 | private VoronoiSimplexSolver _simplexSolver; |
35 | private ConvexShape _convexA, _convexB; | 35 | private ConvexShape _convexA, _convexB; |
36 | 36 | ||
37 | public GjkConvexCast(ConvexShape convexShapeA, ConvexShape convexShapeB, VoronoiSimplexSolver solver) | 37 | public GjkConvexCast(ConvexShape convexShapeA, ConvexShape convexShapeB, VoronoiSimplexSolver solver) |
38 | { | 38 | { |
39 | _simplexSolver = solver; | 39 | _simplexSolver = solver; |
40 | 40 | ||
41 | _convexA = convexShapeA; | 41 | _convexA = convexShapeA; |
42 | _convexB = convexShapeB; | 42 | _convexB = convexShapeB; |
43 | } | 43 | } |
44 | 44 | ||
45 | #region IConvexCast Members | 45 | #region IConvexCast Members |
46 | 46 | ||
47 | /// <summary> | 47 | /// <summary> |
48 | /// cast a convex against another convex object | 48 | /// cast a convex against another convex object |
49 | /// </summary> | 49 | /// </summary> |
50 | /// <param name="fromA"></param> | 50 | /// <param name="fromA"></param> |
51 | /// <param name="toA"></param> | 51 | /// <param name="toA"></param> |
52 | /// <param name="fromB"></param> | 52 | /// <param name="fromB"></param> |
53 | /// <param name="toB"></param> | 53 | /// <param name="toB"></param> |
54 | /// <param name="result"></param> | 54 | /// <param name="result"></param> |
55 | /// <returns></returns> | 55 | /// <returns></returns> |
56 | public bool CalcTimeOfImpact(Matrix fromA, Matrix toA, Matrix fromB, Matrix toB, CastResult result) | 56 | public bool CalcTimeOfImpact(Matrix fromA, Matrix toA, Matrix fromB, Matrix toB, CastResult result) |
57 | { | 57 | { |
58 | MinkowskiSumShape combined = new MinkowskiSumShape(_convexA, _convexB); | 58 | MinkowskiSumShape combined = new MinkowskiSumShape(_convexA, _convexB); |
59 | 59 | ||
60 | Matrix rayFromLocalA = MathHelper.InvertMatrix(fromA) * fromB; | 60 | Matrix rayFromLocalA = MathHelper.InvertMatrix(fromA) * fromB; |
61 | Matrix rayToLocalA = MathHelper.InvertMatrix(toA) * toB; | 61 | Matrix rayToLocalA = MathHelper.InvertMatrix(toA) * toB; |
62 | 62 | ||
63 | Matrix transformA = fromA; | 63 | Matrix transformA = fromA; |
64 | Matrix transformB = fromB; | 64 | Matrix transformB = fromB; |
65 | 65 | ||
66 | transformA.Translation = new Vector3(0, 0, 0); | 66 | transformA.Translation = new Vector3(0, 0, 0); |
67 | transformB.Translation = new Vector3(0, 0, 0); | 67 | transformB.Translation = new Vector3(0, 0, 0); |
68 | 68 | ||
69 | combined.TransformA = transformA; | 69 | combined.TransformA = transformA; |
70 | combined.TransformB = transformB; | 70 | combined.TransformB = transformB; |
71 | 71 | ||
72 | float radius = 0.01f; | 72 | float radius = 0.01f; |
73 | float lambda = 0; | 73 | float lambda = 0; |
74 | 74 | ||
75 | Vector3 s = rayFromLocalA.Translation; | 75 | Vector3 s = rayFromLocalA.Translation; |
76 | Vector3 r = rayToLocalA.Translation - rayFromLocalA.Translation; | 76 | Vector3 r = rayToLocalA.Translation - rayFromLocalA.Translation; |
77 | Vector3 x = s; | 77 | Vector3 x = s; |
78 | Vector3 n = new Vector3(); | 78 | Vector3 n = new Vector3(); |
79 | Vector3 c = new Vector3(); | 79 | Vector3 c = new Vector3(); |
80 | 80 | ||
81 | bool hasResult = false; | 81 | bool hasResult = false; |
82 | float lastLambda = lambda; | 82 | float lastLambda = lambda; |
83 | 83 | ||
84 | IConvexPenetrationDepthSolver penSolver = null; | 84 | IConvexPenetrationDepthSolver penSolver = null; |
85 | Matrix identityTransform = Matrix.Identity; | 85 | Matrix identityTransform = Matrix.Identity; |
86 | 86 | ||
87 | SphereShape raySphere = new SphereShape(0.0f); | 87 | SphereShape raySphere = new SphereShape(0.0f); |
88 | raySphere.Margin=0.0f; | 88 | raySphere.Margin=0.0f; |
89 | 89 | ||
90 | Matrix sphereTransform = Matrix.Identity; | 90 | Matrix sphereTransform = Matrix.Identity; |
91 | sphereTransform.Translation = rayFromLocalA.Translation; | 91 | sphereTransform.Translation = rayFromLocalA.Translation; |
92 | 92 | ||
93 | result.DrawCoordSystem(sphereTransform); | 93 | result.DrawCoordSystem(sphereTransform); |
94 | 94 | ||
95 | { | 95 | { |
96 | PointCollector pointCollector = new PointCollector(); | 96 | PointCollector pointCollector = new PointCollector(); |
97 | GjkPairDetector gjk = new GjkPairDetector(raySphere, combined, _simplexSolver, penSolver); | 97 | GjkPairDetector gjk = new GjkPairDetector(raySphere, combined, _simplexSolver, penSolver); |
98 | 98 | ||
99 | GjkPairDetector.ClosestPointInput input = new DiscreteCollisionDetectorInterface.ClosestPointInput(); | 99 | GjkPairDetector.ClosestPointInput input = new DiscreteCollisionDetectorInterface.ClosestPointInput(); |
100 | input.TransformA = sphereTransform; | 100 | input.TransformA = sphereTransform; |
101 | input.TransformB = identityTransform; | 101 | input.TransformB = identityTransform; |
102 | 102 | ||
103 | gjk.GetClosestPoints(input, pointCollector, null); | 103 | gjk.GetClosestPoints(input, pointCollector, null); |
104 | 104 | ||
105 | hasResult = pointCollector.HasResult; | 105 | hasResult = pointCollector.HasResult; |
106 | 106 | ||
107 | c = pointCollector.PointInWorld; | 107 | c = pointCollector.PointInWorld; |
108 | n = pointCollector.NormalOnBInWorld; | 108 | n = pointCollector.NormalOnBInWorld; |
109 | } | 109 | } |
110 | 110 | ||
111 | if (hasResult) | 111 | if (hasResult) |
112 | { | 112 | { |
113 | float dist = (c - x).Length(); | 113 | float dist = (c - x).Length(); |
114 | 114 | ||
115 | if (dist < radius) | 115 | if (dist < radius) |
116 | { | 116 | { |
117 | lastLambda = 1.0f; | 117 | lastLambda = 1.0f; |
118 | } | 118 | } |
119 | 119 | ||
120 | while (dist > radius) | 120 | while (dist > radius) |
121 | { | 121 | { |
122 | n = x - c; | 122 | n = x - c; |
123 | float dot = Vector3.Dot(n, r); | 123 | float dot = Vector3.Dot(n, r); |
124 | 124 | ||
125 | if (dot >= -(MathHelper.Epsilon * MathHelper.Epsilon)) return false; | 125 | if (dot >= -(MathHelper.Epsilon * MathHelper.Epsilon)) return false; |
126 | 126 | ||
127 | lambda = lambda - Vector3.Distance(n, n) / dot; | 127 | lambda = lambda - Vector3.Distance(n, n) / dot; |
128 | if (lambda <= lastLambda) break; | 128 | if (lambda <= lastLambda) break; |
129 | 129 | ||
130 | lastLambda = lambda; | 130 | lastLambda = lambda; |
131 | 131 | ||
132 | x = s + lambda * r; | 132 | x = s + lambda * r; |
133 | 133 | ||
134 | sphereTransform.Translation = x; | 134 | sphereTransform.Translation = x; |
135 | result.DrawCoordSystem(sphereTransform); | 135 | result.DrawCoordSystem(sphereTransform); |
136 | PointCollector pointCollector = new PointCollector(); | 136 | PointCollector pointCollector = new PointCollector(); |
137 | 137 | ||
138 | GjkPairDetector gjk = new GjkPairDetector(raySphere, combined, _simplexSolver, penSolver); | 138 | GjkPairDetector gjk = new GjkPairDetector(raySphere, combined, _simplexSolver, penSolver); |
139 | GjkPairDetector.ClosestPointInput input = new DiscreteCollisionDetectorInterface.ClosestPointInput(); | 139 | GjkPairDetector.ClosestPointInput input = new DiscreteCollisionDetectorInterface.ClosestPointInput(); |
140 | input.TransformA = sphereTransform; | 140 | input.TransformA = sphereTransform; |
141 | input.TransformB = identityTransform; | 141 | input.TransformB = identityTransform; |
142 | 142 | ||
143 | gjk.GetClosestPoints(input, pointCollector, null); | 143 | gjk.GetClosestPoints(input, pointCollector, null); |
144 | 144 | ||
145 | if (pointCollector.HasResult) | 145 | if (pointCollector.HasResult) |
146 | { | 146 | { |
147 | if (pointCollector.Distance < 0.0f) | 147 | if (pointCollector.Distance < 0.0f) |
148 | { | 148 | { |
149 | result.Fraction = lastLambda; | 149 | result.Fraction = lastLambda; |
150 | result.Normal = n; | 150 | result.Normal = n; |
151 | return true; | 151 | return true; |
152 | } | 152 | } |
153 | 153 | ||
154 | c = pointCollector.PointInWorld; | 154 | c = pointCollector.PointInWorld; |
155 | dist = (c - x).Length(); | 155 | dist = (c - x).Length(); |
156 | } | 156 | } |
157 | else | 157 | else |
158 | { | 158 | { |
159 | return false; | 159 | return false; |
160 | } | 160 | } |
161 | } | 161 | } |
162 | 162 | ||
163 | if (lastLambda < 1.0f) | 163 | if (lastLambda < 1.0f) |
164 | { | 164 | { |
165 | result.Fraction = lastLambda; | 165 | result.Fraction = lastLambda; |
166 | result.Normal = n; | 166 | result.Normal = n; |
167 | return true; | 167 | return true; |
168 | } | 168 | } |
169 | } | 169 | } |
170 | 170 | ||
171 | return false; | 171 | return false; |
172 | } | 172 | } |
173 | 173 | ||
174 | #endregion | 174 | #endregion |
175 | } | 175 | } |
176 | } | 176 | } |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpa.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpa.cs index 50ae7ab..a3064db 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpa.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpa.cs | |||
@@ -1,633 +1,633 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | /// <summary> | 29 | /// <summary> |
30 | /// GJK-EPA collision solver by Nathanael Presson | 30 | /// GJK-EPA collision solver by Nathanael Presson |
31 | /// Nov.2006 | 31 | /// Nov.2006 |
32 | /// </summary> | 32 | /// </summary> |
33 | public class GjkEpa | 33 | public class GjkEpa |
34 | { | 34 | { |
35 | //private static readonly int _precision = 1 /* U(sizeof(F) == 4)*/; | 35 | //private static readonly int _precision = 1 /* U(sizeof(F) == 4)*/; |
36 | 36 | ||
37 | private static readonly float _infinity = MathHelper.Infinity; | 37 | private static readonly float _infinity = MathHelper.Infinity; |
38 | //private static readonly float _pi = (float)Math.PI; | 38 | //private static readonly float _pi = (float)Math.PI; |
39 | private static readonly float _twoPi = (float)(Math.PI * 2); | 39 | private static readonly float _twoPi = (float)(Math.PI * 2); |
40 | 40 | ||
41 | private static readonly int _gjkMaxIterations = 128; | 41 | private static readonly int _gjkMaxIterations = 128; |
42 | private static readonly int _gjkHashSize = 1 << 6; | 42 | private static readonly int _gjkHashSize = 1 << 6; |
43 | private static readonly int _gjkHashMask = _gjkHashSize - 1; | 43 | private static readonly int _gjkHashMask = _gjkHashSize - 1; |
44 | private static readonly float _gjkInSimplexEpsilon = 0.0001f; | 44 | private static readonly float _gjkInSimplexEpsilon = 0.0001f; |
45 | private static readonly float _gjkSquareInSimplexEpsilon = _gjkInSimplexEpsilon * _gjkInSimplexEpsilon; | 45 | private static readonly float _gjkSquareInSimplexEpsilon = _gjkInSimplexEpsilon * _gjkInSimplexEpsilon; |
46 | 46 | ||
47 | private static readonly int _epaMaxIterations = 256; | 47 | private static readonly int _epaMaxIterations = 256; |
48 | private static readonly float _epaInFaceEpsilon = 0.01f; | 48 | private static readonly float _epaInFaceEpsilon = 0.01f; |
49 | private static readonly float _epaAccuracy = 0.001f; | 49 | private static readonly float _epaAccuracy = 0.001f; |
50 | 50 | ||
51 | public static float EpaAccuracy { get { return _epaAccuracy; } } | 51 | public static float EpaAccuracy { get { return _epaAccuracy; } } |
52 | 52 | ||
53 | private static float Abs(float v) { return (v < 0 ? -v : v); } | 53 | private static float Abs(float v) { return (v < 0 ? -v : v); } |
54 | private static float Sign(float v) { return (v < 0 ? -1 : 1); } | 54 | private static float Sign(float v) { return (v < 0 ? -1 : 1); } |
55 | 55 | ||
56 | static void Swap<T>(ref T a, ref T b) | 56 | static void Swap<T>(ref T a, ref T b) |
57 | { | 57 | { |
58 | T t = a; | 58 | T t = a; |
59 | a = b; | 59 | a = b; |
60 | b = t; | 60 | b = t; |
61 | } | 61 | } |
62 | 62 | ||
63 | public class Gjk | 63 | public class Gjk |
64 | { | 64 | { |
65 | public class MinkowskiVertice | 65 | public class MinkowskiVertice |
66 | { | 66 | { |
67 | private Vector3 _vertice; /* Minkowski vertice */ | 67 | private Vector3 _vertice; /* Minkowski vertice */ |
68 | private Vector3 _ray; /* Ray */ | 68 | private Vector3 _ray; /* Ray */ |
69 | 69 | ||
70 | public Vector3 Vertice { get { return _vertice; } set { _vertice = value; } } | 70 | public Vector3 Vertice { get { return _vertice; } set { _vertice = value; } } |
71 | public Vector3 Ray { get { return _ray; } set { _ray = value; } } | 71 | public Vector3 Ray { get { return _ray; } set { _ray = value; } } |
72 | } | 72 | } |
73 | public class He | 73 | public class He |
74 | { | 74 | { |
75 | private Vector3 _ray; | 75 | private Vector3 _ray; |
76 | private He _next; | 76 | private He _next; |
77 | 77 | ||
78 | public He Next { get { return _next; } set { _next = value; } } | 78 | public He Next { get { return _next; } set { _next = value; } } |
79 | public Vector3 Ray { get { return _ray; } set { _ray = value; } } | 79 | public Vector3 Ray { get { return _ray; } set { _ray = value; } } |
80 | } | 80 | } |
81 | 81 | ||
82 | private He[] _table = new He[_gjkHashSize]; | 82 | private He[] _table = new He[_gjkHashSize]; |
83 | private Matrix[] _wrotations = new Matrix[2]; | 83 | private Matrix[] _wrotations = new Matrix[2]; |
84 | private Vector3[] _positions = new Vector3[2]; | 84 | private Vector3[] _positions = new Vector3[2]; |
85 | private ConvexShape[] _shapes = new ConvexShape[2]; | 85 | private ConvexShape[] _shapes = new ConvexShape[2]; |
86 | private MinkowskiVertice[] _simplex = new MinkowskiVertice[5]; | 86 | private MinkowskiVertice[] _simplex = new MinkowskiVertice[5]; |
87 | private Vector3 _ray; | 87 | private Vector3 _ray; |
88 | private int _order; | 88 | private int _order; |
89 | private int _iterations; | 89 | private int _iterations; |
90 | private float _margin; | 90 | private float _margin; |
91 | private bool _failed; | 91 | private bool _failed; |
92 | 92 | ||
93 | public Gjk(Matrix wrotationA, Vector3 positionA, ConvexShape shapeA, | 93 | public Gjk(Matrix wrotationA, Vector3 positionA, ConvexShape shapeA, |
94 | Matrix wrotationB, Vector3 positionB, ConvexShape shapeB) | 94 | Matrix wrotationB, Vector3 positionB, ConvexShape shapeB) |
95 | : this(wrotationA, positionA, shapeA, wrotationB, positionB, shapeB, 0) { } | 95 | : this(wrotationA, positionA, shapeA, wrotationB, positionB, shapeB, 0) { } |
96 | 96 | ||
97 | public Gjk(Matrix wrotationA, Vector3 positionA, ConvexShape shapeA, | 97 | public Gjk(Matrix wrotationA, Vector3 positionA, ConvexShape shapeA, |
98 | Matrix wrotationB, Vector3 positionB, ConvexShape shapeB, | 98 | Matrix wrotationB, Vector3 positionB, ConvexShape shapeB, |
99 | float pmargin) | 99 | float pmargin) |
100 | { | 100 | { |
101 | for (int i = 0; i < _simplex.Length; i++) | 101 | for (int i = 0; i < _simplex.Length; i++) |
102 | _simplex[i] = new MinkowskiVertice(); | 102 | _simplex[i] = new MinkowskiVertice(); |
103 | 103 | ||
104 | for (int i = 0; i < _wrotations.Length; i++) | 104 | for (int i = 0; i < _wrotations.Length; i++) |
105 | _wrotations[i] = new Matrix(); | 105 | _wrotations[i] = new Matrix(); |
106 | 106 | ||
107 | for (int i = 0; i < _positions.Length; i++) | 107 | for (int i = 0; i < _positions.Length; i++) |
108 | _positions[i] = new Vector3(); | 108 | _positions[i] = new Vector3(); |
109 | 109 | ||
110 | _wrotations[0] = wrotationA; _positions[0] = positionA; | 110 | _wrotations[0] = wrotationA; _positions[0] = positionA; |
111 | _shapes[0] = shapeA; | 111 | _shapes[0] = shapeA; |
112 | _wrotations[0].Translation = Vector3.Zero; | 112 | _wrotations[0].Translation = Vector3.Zero; |
113 | _wrotations[1] = wrotationB; _positions[1] = positionB; | 113 | _wrotations[1] = wrotationB; _positions[1] = positionB; |
114 | _shapes[1] = shapeB; | 114 | _shapes[1] = shapeB; |
115 | _wrotations[1].Translation = Vector3.Zero; | 115 | _wrotations[1].Translation = Vector3.Zero; |
116 | //sablock = sa->BeginBlock(); | 116 | //sablock = sa->BeginBlock(); |
117 | _margin = pmargin; | 117 | _margin = pmargin; |
118 | _failed = false; | 118 | _failed = false; |
119 | } | 119 | } |
120 | 120 | ||
121 | public bool Failed { get { return _failed; } } | 121 | public bool Failed { get { return _failed; } } |
122 | public int Iterations { get { return _iterations; } } | 122 | public int Iterations { get { return _iterations; } } |
123 | public int Order { get { return _order; } } | 123 | public int Order { get { return _order; } } |
124 | public MinkowskiVertice[] Simplex { get { return _simplex; } } | 124 | public MinkowskiVertice[] Simplex { get { return _simplex; } } |
125 | 125 | ||
126 | public int Hash(Vector3 v) | 126 | public int Hash(Vector3 v) |
127 | { | 127 | { |
128 | int h = ((int)(v.X * 15461) ^ (int)(v.Y * 83003) ^ (int)(v.Z * 15473)); | 128 | int h = ((int)(v.X * 15461) ^ (int)(v.Y * 83003) ^ (int)(v.Z * 15473)); |
129 | return (h * 169639) & _gjkHashMask; | 129 | return (h * 169639) & _gjkHashMask; |
130 | } | 130 | } |
131 | 131 | ||
132 | public bool FetchSupport() | 132 | public bool FetchSupport() |
133 | { | 133 | { |
134 | int h = Hash(_ray); | 134 | int h = Hash(_ray); |
135 | He e = _table[h]; | 135 | He e = _table[h]; |
136 | while (e != null) | 136 | while (e != null) |
137 | { | 137 | { |
138 | if (e.Ray == _ray) | 138 | if (e.Ray == _ray) |
139 | { | 139 | { |
140 | --_order; | 140 | --_order; |
141 | return (false); | 141 | return (false); |
142 | } | 142 | } |
143 | else e = e.Next; | 143 | else e = e.Next; |
144 | } | 144 | } |
145 | e = new He(); | 145 | e = new He(); |
146 | e.Ray = _ray; | 146 | e.Ray = _ray; |
147 | e.Next = _table[h]; | 147 | e.Next = _table[h]; |
148 | _table[h] = e; | 148 | _table[h] = e; |
149 | Support(_ray, ref _simplex[++_order]); | 149 | Support(_ray, ref _simplex[++_order]); |
150 | return (Vector3.Dot(_ray, _simplex[_order].Vertice) > 0); | 150 | return (Vector3.Dot(_ray, _simplex[_order].Vertice) > 0); |
151 | } | 151 | } |
152 | 152 | ||
153 | public Vector3 LocalSupport(Vector3 d, int i) | 153 | public Vector3 LocalSupport(Vector3 d, int i) |
154 | { | 154 | { |
155 | Matrix m = _wrotations[i]; | 155 | Matrix m = _wrotations[i]; |
156 | m.Translation = Vector3.Zero; | 156 | m.Translation = Vector3.Zero; |
157 | Vector3 vtx = Vector3.TransformNormal(d, m); | 157 | Vector3 vtx = Vector3.TransformNormal(d, m); |
158 | Vector3 result = MathHelper.MatrixToVector(_wrotations[i], _shapes[i].LocalGetSupportingVertex(vtx)); | 158 | Vector3 result = MathHelper.MatrixToVector(_wrotations[i], _shapes[i].LocalGetSupportingVertex(vtx)); |
159 | return (result + _positions[i]); | 159 | return (result + _positions[i]); |
160 | } | 160 | } |
161 | 161 | ||
162 | public void Support(Vector3 d, ref MinkowskiVertice v) | 162 | public void Support(Vector3 d, ref MinkowskiVertice v) |
163 | { | 163 | { |
164 | v.Ray = d; | 164 | v.Ray = d; |
165 | v.Vertice = LocalSupport(d, 0) - LocalSupport(-d, 1) + d * _margin; | 165 | v.Vertice = LocalSupport(d, 0) - LocalSupport(-d, 1) + d * _margin; |
166 | } | 166 | } |
167 | 167 | ||
168 | public bool SolveSimplex2(Vector3 ao, Vector3 ab) | 168 | public bool SolveSimplex2(Vector3 ao, Vector3 ab) |
169 | { | 169 | { |
170 | if (Vector3.Dot(ab, ao) >= 0) | 170 | if (Vector3.Dot(ab, ao) >= 0) |
171 | { | 171 | { |
172 | Vector3 cabo = Vector3.Cross(ab, ao); | 172 | Vector3 cabo = Vector3.Cross(ab, ao); |
173 | if (cabo.LengthSquared() > _gjkSquareInSimplexEpsilon) | 173 | if (cabo.LengthSquared() > _gjkSquareInSimplexEpsilon) |
174 | { _ray = Vector3.Cross(cabo, ab); } | 174 | { _ray = Vector3.Cross(cabo, ab); } |
175 | else | 175 | else |
176 | { return true; } | 176 | { return true; } |
177 | } | 177 | } |
178 | else | 178 | else |
179 | { | 179 | { |
180 | _order = 0; | 180 | _order = 0; |
181 | _simplex[0].Ray = _simplex[1].Ray; | 181 | _simplex[0].Ray = _simplex[1].Ray; |
182 | _simplex[0].Vertice = _simplex[1].Vertice; | 182 | _simplex[0].Vertice = _simplex[1].Vertice; |
183 | 183 | ||
184 | _ray = ao; | 184 | _ray = ao; |
185 | } | 185 | } |
186 | return false; | 186 | return false; |
187 | } | 187 | } |
188 | 188 | ||
189 | public bool SolveSimplex3(Vector3 ao, Vector3 ab, Vector3 ac) | 189 | public bool SolveSimplex3(Vector3 ao, Vector3 ab, Vector3 ac) |
190 | { | 190 | { |
191 | return (SolveSimplex3a(ao, ab, ac, Vector3.Cross(ab, ac))); | 191 | return (SolveSimplex3a(ao, ab, ac, Vector3.Cross(ab, ac))); |
192 | } | 192 | } |
193 | 193 | ||
194 | public bool SolveSimplex3a(Vector3 ao, Vector3 ab, Vector3 ac, Vector3 cabc) | 194 | public bool SolveSimplex3a(Vector3 ao, Vector3 ab, Vector3 ac, Vector3 cabc) |
195 | { | 195 | { |
196 | if ((Vector3.Dot(Vector3.Cross(cabc, ab), ao)) < -_gjkInSimplexEpsilon) | 196 | if ((Vector3.Dot(Vector3.Cross(cabc, ab), ao)) < -_gjkInSimplexEpsilon) |
197 | { | 197 | { |
198 | _order = 1; | 198 | _order = 1; |
199 | _simplex[0].Vertice = _simplex[1].Vertice; | 199 | _simplex[0].Vertice = _simplex[1].Vertice; |
200 | _simplex[0].Ray = _simplex[1].Ray; | 200 | _simplex[0].Ray = _simplex[1].Ray; |
201 | 201 | ||
202 | _simplex[1].Vertice = _simplex[2].Vertice; | 202 | _simplex[1].Vertice = _simplex[2].Vertice; |
203 | _simplex[1].Ray = _simplex[2].Ray; | 203 | _simplex[1].Ray = _simplex[2].Ray; |
204 | 204 | ||
205 | return (SolveSimplex2(ao, ab)); | 205 | return (SolveSimplex2(ao, ab)); |
206 | } | 206 | } |
207 | else if (Vector3.Dot(Vector3.Cross(cabc, ac), ao) > +_gjkInSimplexEpsilon) | 207 | else if (Vector3.Dot(Vector3.Cross(cabc, ac), ao) > +_gjkInSimplexEpsilon) |
208 | { | 208 | { |
209 | _order = 1; | 209 | _order = 1; |
210 | _simplex[1].Vertice = _simplex[2].Vertice; | 210 | _simplex[1].Vertice = _simplex[2].Vertice; |
211 | _simplex[1].Ray = _simplex[2].Ray; | 211 | _simplex[1].Ray = _simplex[2].Ray; |
212 | 212 | ||
213 | return (SolveSimplex2(ao, ac)); | 213 | return (SolveSimplex2(ao, ac)); |
214 | } | 214 | } |
215 | else | 215 | else |
216 | { | 216 | { |
217 | float d = Vector3.Dot(cabc, ao); | 217 | float d = Vector3.Dot(cabc, ao); |
218 | if (Abs(d) > _gjkInSimplexEpsilon) | 218 | if (Abs(d) > _gjkInSimplexEpsilon) |
219 | { | 219 | { |
220 | if (d > 0) | 220 | if (d > 0) |
221 | { _ray = cabc; } | 221 | { _ray = cabc; } |
222 | else | 222 | else |
223 | { _ray = -cabc; Swap<MinkowskiVertice>(ref _simplex[0], ref _simplex[1]); } | 223 | { _ray = -cabc; Swap<MinkowskiVertice>(ref _simplex[0], ref _simplex[1]); } |
224 | return (false); | 224 | return (false); |
225 | } | 225 | } |
226 | else return (true); | 226 | else return (true); |
227 | } | 227 | } |
228 | } | 228 | } |
229 | 229 | ||
230 | public bool SolveSimplex4(Vector3 ao, Vector3 ab, Vector3 ac, Vector3 ad) | 230 | public bool SolveSimplex4(Vector3 ao, Vector3 ab, Vector3 ac, Vector3 ad) |
231 | { | 231 | { |
232 | Vector3 crs; | 232 | Vector3 crs; |
233 | if (Vector3.Dot((crs = Vector3.Cross(ab, ac)), ao) > _gjkInSimplexEpsilon) | 233 | if (Vector3.Dot((crs = Vector3.Cross(ab, ac)), ao) > _gjkInSimplexEpsilon) |
234 | { | 234 | { |
235 | _order = 2; | 235 | _order = 2; |
236 | _simplex[0].Vertice = _simplex[1].Vertice; | 236 | _simplex[0].Vertice = _simplex[1].Vertice; |
237 | _simplex[0].Ray = _simplex[1].Ray; | 237 | _simplex[0].Ray = _simplex[1].Ray; |
238 | 238 | ||
239 | _simplex[1].Vertice = _simplex[2].Vertice; | 239 | _simplex[1].Vertice = _simplex[2].Vertice; |
240 | _simplex[1].Ray = _simplex[2].Ray; | 240 | _simplex[1].Ray = _simplex[2].Ray; |
241 | 241 | ||
242 | _simplex[2].Vertice = _simplex[3].Vertice; | 242 | _simplex[2].Vertice = _simplex[3].Vertice; |
243 | _simplex[2].Ray = _simplex[3].Ray; | 243 | _simplex[2].Ray = _simplex[3].Ray; |
244 | 244 | ||
245 | return (SolveSimplex3a(ao, ab, ac, crs)); | 245 | return (SolveSimplex3a(ao, ab, ac, crs)); |
246 | } | 246 | } |
247 | else if (Vector3.Dot((crs = Vector3.Cross(ac, ad)), ao) > _gjkInSimplexEpsilon) | 247 | else if (Vector3.Dot((crs = Vector3.Cross(ac, ad)), ao) > _gjkInSimplexEpsilon) |
248 | { | 248 | { |
249 | _order = 2; | 249 | _order = 2; |
250 | _simplex[2].Vertice = _simplex[3].Vertice; | 250 | _simplex[2].Vertice = _simplex[3].Vertice; |
251 | _simplex[2].Ray = _simplex[3].Ray; | 251 | _simplex[2].Ray = _simplex[3].Ray; |
252 | 252 | ||
253 | return (SolveSimplex3a(ao, ac, ad, crs)); | 253 | return (SolveSimplex3a(ao, ac, ad, crs)); |
254 | } | 254 | } |
255 | else if (Vector3.Dot((crs = Vector3.Cross(ad, ab)), ao) > _gjkInSimplexEpsilon) | 255 | else if (Vector3.Dot((crs = Vector3.Cross(ad, ab)), ao) > _gjkInSimplexEpsilon) |
256 | { | 256 | { |
257 | _order = 2; | 257 | _order = 2; |
258 | 258 | ||
259 | _simplex[1].Vertice = _simplex[0].Vertice; | 259 | _simplex[1].Vertice = _simplex[0].Vertice; |
260 | _simplex[1].Ray = _simplex[0].Ray; | 260 | _simplex[1].Ray = _simplex[0].Ray; |
261 | 261 | ||
262 | _simplex[0].Vertice = _simplex[2].Vertice; | 262 | _simplex[0].Vertice = _simplex[2].Vertice; |
263 | _simplex[0].Ray = _simplex[2].Ray; | 263 | _simplex[0].Ray = _simplex[2].Ray; |
264 | 264 | ||
265 | _simplex[2].Vertice = _simplex[3].Vertice; | 265 | _simplex[2].Vertice = _simplex[3].Vertice; |
266 | _simplex[2].Ray = _simplex[3].Ray; | 266 | _simplex[2].Ray = _simplex[3].Ray; |
267 | 267 | ||
268 | return (SolveSimplex3a(ao, ad, ab, crs)); | 268 | return (SolveSimplex3a(ao, ad, ab, crs)); |
269 | } | 269 | } |
270 | else return (true); | 270 | else return (true); |
271 | } | 271 | } |
272 | 272 | ||
273 | public bool SearchOrigin() | 273 | public bool SearchOrigin() |
274 | { | 274 | { |
275 | return SearchOrigin(new Vector3(1, 0, 0)); | 275 | return SearchOrigin(new Vector3(1, 0, 0)); |
276 | } | 276 | } |
277 | 277 | ||
278 | public bool SearchOrigin(Vector3 initray) | 278 | public bool SearchOrigin(Vector3 initray) |
279 | { | 279 | { |
280 | _iterations = 0; | 280 | _iterations = 0; |
281 | unchecked | 281 | unchecked |
282 | { | 282 | { |
283 | _order = (int)(-1); | 283 | _order = (int)(-1); |
284 | } | 284 | } |
285 | _failed = false; | 285 | _failed = false; |
286 | _ray = Vector3.Normalize(initray); | 286 | _ray = Vector3.Normalize(initray); |
287 | 287 | ||
288 | //ClearMemory(table, sizeof(void*) * GJK_hashsize); | 288 | //ClearMemory(table, sizeof(void*) * GJK_hashsize); |
289 | for (int i = 0; i < _table.Length; i++) | 289 | for (int i = 0; i < _table.Length; i++) |
290 | _table[i] = null; | 290 | _table[i] = null; |
291 | FetchSupport(); | 291 | FetchSupport(); |
292 | _ray = -_simplex[0].Vertice; | 292 | _ray = -_simplex[0].Vertice; |
293 | for (; _iterations < _gjkMaxIterations; ++_iterations) | 293 | for (; _iterations < _gjkMaxIterations; ++_iterations) |
294 | { | 294 | { |
295 | float rl = _ray.Length(); | 295 | float rl = _ray.Length(); |
296 | _ray /= rl > 0 ? rl : 1; | 296 | _ray /= rl > 0 ? rl : 1; |
297 | if (FetchSupport()) | 297 | if (FetchSupport()) |
298 | { | 298 | { |
299 | bool found = (false); | 299 | bool found = (false); |
300 | switch (_order) | 300 | switch (_order) |
301 | { | 301 | { |
302 | case 1: found = SolveSimplex2(-_simplex[1].Vertice, _simplex[0].Vertice - _simplex[1].Vertice); break; | 302 | case 1: found = SolveSimplex2(-_simplex[1].Vertice, _simplex[0].Vertice - _simplex[1].Vertice); break; |
303 | case 2: found = SolveSimplex3(-_simplex[2].Vertice, _simplex[1].Vertice - _simplex[2].Vertice, _simplex[0].Vertice - _simplex[2].Vertice); break; | 303 | case 2: found = SolveSimplex3(-_simplex[2].Vertice, _simplex[1].Vertice - _simplex[2].Vertice, _simplex[0].Vertice - _simplex[2].Vertice); break; |
304 | case 3: found = SolveSimplex4(-_simplex[3].Vertice, _simplex[2].Vertice - _simplex[3].Vertice, _simplex[1].Vertice - _simplex[3].Vertice, _simplex[0].Vertice - _simplex[3].Vertice); break; | 304 | case 3: found = SolveSimplex4(-_simplex[3].Vertice, _simplex[2].Vertice - _simplex[3].Vertice, _simplex[1].Vertice - _simplex[3].Vertice, _simplex[0].Vertice - _simplex[3].Vertice); break; |
305 | } | 305 | } |
306 | if (found) return (true); | 306 | if (found) return (true); |
307 | } | 307 | } |
308 | else return (false); | 308 | else return (false); |
309 | } | 309 | } |
310 | _failed = true; | 310 | _failed = true; |
311 | return (false); | 311 | return (false); |
312 | } | 312 | } |
313 | 313 | ||
314 | public bool EncloseOrigin() | 314 | public bool EncloseOrigin() |
315 | { | 315 | { |
316 | switch (_order) | 316 | switch (_order) |
317 | { | 317 | { |
318 | /* Point */ | 318 | /* Point */ |
319 | case 0: break; | 319 | case 0: break; |
320 | /* Line */ | 320 | /* Line */ |
321 | case 1: | 321 | case 1: |
322 | Vector3 ab = _simplex[1].Vertice - _simplex[0].Vertice; | 322 | Vector3 ab = _simplex[1].Vertice - _simplex[0].Vertice; |
323 | Vector3[] b ={ Vector3.Cross(ab, new Vector3(1, 0, 0)), | 323 | Vector3[] b ={ Vector3.Cross(ab, new Vector3(1, 0, 0)), |
324 | Vector3.Cross(ab, new Vector3(0, 1, 0)), | 324 | Vector3.Cross(ab, new Vector3(0, 1, 0)), |
325 | Vector3.Cross(ab, new Vector3(0, 0, 1)) }; | 325 | Vector3.Cross(ab, new Vector3(0, 0, 1)) }; |
326 | float[] m ={ b[0].LengthSquared(), b[1].LengthSquared(), b[2].LengthSquared() }; | 326 | float[] m ={ b[0].LengthSquared(), b[1].LengthSquared(), b[2].LengthSquared() }; |
327 | Matrix r = Matrix.CreateFromQuaternion(new Quaternion(Vector3.Normalize(ab), _twoPi / 3)); | 327 | Matrix r = Matrix.CreateFromQuaternion(new Quaternion(Vector3.Normalize(ab), _twoPi / 3)); |
328 | Vector3 w = b[m[0] > m[1] ? m[0] > m[2] ? 0 : 2 : m[1] > m[2] ? 1 : 2]; | 328 | Vector3 w = b[m[0] > m[1] ? m[0] > m[2] ? 0 : 2 : m[1] > m[2] ? 1 : 2]; |
329 | Support(Vector3.Normalize(w), ref _simplex[4]); w = Vector3.TransformNormal(w, r); | 329 | Support(Vector3.Normalize(w), ref _simplex[4]); w = Vector3.TransformNormal(w, r); |
330 | Support(Vector3.Normalize(w), ref _simplex[2]); w = Vector3.TransformNormal(w, r); | 330 | Support(Vector3.Normalize(w), ref _simplex[2]); w = Vector3.TransformNormal(w, r); |
331 | Support(Vector3.Normalize(w), ref _simplex[3]); w = Vector3.TransformNormal(w, r); | 331 | Support(Vector3.Normalize(w), ref _simplex[3]); w = Vector3.TransformNormal(w, r); |
332 | _order = 4; | 332 | _order = 4; |
333 | return true; | 333 | return true; |
334 | /* Triangle */ | 334 | /* Triangle */ |
335 | case 2: | 335 | case 2: |
336 | Vector3 n = Vector3.Normalize(Vector3.Cross(_simplex[1].Vertice - _simplex[0].Vertice, _simplex[2].Vertice - _simplex[0].Vertice)); | 336 | Vector3 n = Vector3.Normalize(Vector3.Cross(_simplex[1].Vertice - _simplex[0].Vertice, _simplex[2].Vertice - _simplex[0].Vertice)); |
337 | Support(n, ref _simplex[3]); | 337 | Support(n, ref _simplex[3]); |
338 | Support(-n, ref _simplex[4]); | 338 | Support(-n, ref _simplex[4]); |
339 | _order = 4; | 339 | _order = 4; |
340 | return true; | 340 | return true; |
341 | /* Tetrahedron */ | 341 | /* Tetrahedron */ |
342 | case 3: return (true); | 342 | case 3: return (true); |
343 | /* Hexahedron */ | 343 | /* Hexahedron */ |
344 | case 4: return (true); | 344 | case 4: return (true); |
345 | } | 345 | } |
346 | return (false); | 346 | return (false); |
347 | } | 347 | } |
348 | } | 348 | } |
349 | 349 | ||
350 | public class Epa | 350 | public class Epa |
351 | { | 351 | { |
352 | public class Face | 352 | public class Face |
353 | { | 353 | { |
354 | public Gjk.MinkowskiVertice[] _vertices = new Gjk.MinkowskiVertice[3]; | 354 | public Gjk.MinkowskiVertice[] _vertices = new Gjk.MinkowskiVertice[3]; |
355 | public Face[] _faces = new Face[3]; | 355 | public Face[] _faces = new Face[3]; |
356 | public int[] _e = new int[3]; | 356 | public int[] _e = new int[3]; |
357 | public Vector3 _n; | 357 | public Vector3 _n; |
358 | public float _d; | 358 | public float _d; |
359 | public int _mark; | 359 | public int _mark; |
360 | public Face _prev; | 360 | public Face _prev; |
361 | public Face _next; | 361 | public Face _next; |
362 | } | 362 | } |
363 | 363 | ||
364 | private Gjk _gjk; | 364 | private Gjk _gjk; |
365 | private Face _root; | 365 | private Face _root; |
366 | private int _nfaces; | 366 | private int _nfaces; |
367 | private int _iterations; | 367 | private int _iterations; |
368 | private Vector3[,] _features = new Vector3[2, 3]; | 368 | private Vector3[,] _features = new Vector3[2, 3]; |
369 | private Vector3[] _nearest = new Vector3[2]; | 369 | private Vector3[] _nearest = new Vector3[2]; |
370 | private Vector3 _normal; | 370 | private Vector3 _normal; |
371 | private float _depth; | 371 | private float _depth; |
372 | private bool _failed; | 372 | private bool _failed; |
373 | 373 | ||
374 | public Epa(Gjk gjk) | 374 | public Epa(Gjk gjk) |
375 | { | 375 | { |
376 | this._gjk = gjk; | 376 | this._gjk = gjk; |
377 | } | 377 | } |
378 | 378 | ||
379 | public bool Failed { get { return _failed; } } | 379 | public bool Failed { get { return _failed; } } |
380 | public int Iterations { get { return _iterations; } } | 380 | public int Iterations { get { return _iterations; } } |
381 | public Vector3 Normal { get { return _normal; } } | 381 | public Vector3 Normal { get { return _normal; } } |
382 | public Vector3[] Nearest { get { return _nearest; } } | 382 | public Vector3[] Nearest { get { return _nearest; } } |
383 | 383 | ||
384 | public Vector3 GetCoordinates(Face face) | 384 | public Vector3 GetCoordinates(Face face) |
385 | { | 385 | { |
386 | Vector3 o = face._n * -face._d; | 386 | Vector3 o = face._n * -face._d; |
387 | float[] a ={ Vector3.Cross(face._vertices[0].Vertice - o, face._vertices[1].Vertice - o).Length(), | 387 | float[] a ={ Vector3.Cross(face._vertices[0].Vertice - o, face._vertices[1].Vertice - o).Length(), |
388 | Vector3.Cross(face._vertices[1].Vertice - o, face._vertices[2].Vertice - o).Length(), | 388 | Vector3.Cross(face._vertices[1].Vertice - o, face._vertices[2].Vertice - o).Length(), |
389 | Vector3.Cross(face._vertices[2].Vertice - o, face._vertices[0].Vertice - o).Length()}; | 389 | Vector3.Cross(face._vertices[2].Vertice - o, face._vertices[0].Vertice - o).Length()}; |
390 | float sm = a[0] + a[1] + a[2]; | 390 | float sm = a[0] + a[1] + a[2]; |
391 | return (new Vector3(a[1], a[2], a[0]) / (sm > 0 ? sm : 1)); | 391 | return (new Vector3(a[1], a[2], a[0]) / (sm > 0 ? sm : 1)); |
392 | } | 392 | } |
393 | 393 | ||
394 | public Face FindBest() | 394 | public Face FindBest() |
395 | { | 395 | { |
396 | Face bf = null; | 396 | Face bf = null; |
397 | if (_root != null) | 397 | if (_root != null) |
398 | { | 398 | { |
399 | Face cf = _root; | 399 | Face cf = _root; |
400 | float bd = _infinity; | 400 | float bd = _infinity; |
401 | do | 401 | do |
402 | { | 402 | { |
403 | if (cf._d < bd) { bd = cf._d; bf = cf; } | 403 | if (cf._d < bd) { bd = cf._d; bf = cf; } |
404 | } while (null != (cf = cf._next)); | 404 | } while (null != (cf = cf._next)); |
405 | } | 405 | } |
406 | return bf; | 406 | return bf; |
407 | } | 407 | } |
408 | 408 | ||
409 | public bool Set(ref Face f, Gjk.MinkowskiVertice a, Gjk.MinkowskiVertice b, Gjk.MinkowskiVertice c) | 409 | public bool Set(ref Face f, Gjk.MinkowskiVertice a, Gjk.MinkowskiVertice b, Gjk.MinkowskiVertice c) |
410 | { | 410 | { |
411 | Vector3 nrm = Vector3.Cross(b.Vertice - a.Vertice, c.Vertice - a.Vertice); | 411 | Vector3 nrm = Vector3.Cross(b.Vertice - a.Vertice, c.Vertice - a.Vertice); |
412 | float len = nrm.Length(); | 412 | float len = nrm.Length(); |
413 | bool valid = (Vector3.Dot(Vector3.Cross(a.Vertice, b.Vertice), nrm) >= -_epaInFaceEpsilon && | 413 | bool valid = (Vector3.Dot(Vector3.Cross(a.Vertice, b.Vertice), nrm) >= -_epaInFaceEpsilon && |
414 | Vector3.Dot(Vector3.Cross(b.Vertice, c.Vertice), nrm) >= -_epaInFaceEpsilon && | 414 | Vector3.Dot(Vector3.Cross(b.Vertice, c.Vertice), nrm) >= -_epaInFaceEpsilon && |
415 | Vector3.Dot(Vector3.Cross(c.Vertice, a.Vertice), nrm) >= -_epaInFaceEpsilon); | 415 | Vector3.Dot(Vector3.Cross(c.Vertice, a.Vertice), nrm) >= -_epaInFaceEpsilon); |
416 | f._vertices[0] = a; | 416 | f._vertices[0] = a; |
417 | f._vertices[1] = b; | 417 | f._vertices[1] = b; |
418 | f._vertices[2] = c; | 418 | f._vertices[2] = c; |
419 | f._mark = 0; | 419 | f._mark = 0; |
420 | f._n = nrm / (len > 0 ? len : _infinity); | 420 | f._n = nrm / (len > 0 ? len : _infinity); |
421 | f._d = Max(0, -Vector3.Dot(f._n, a.Vertice)); | 421 | f._d = Max(0, -Vector3.Dot(f._n, a.Vertice)); |
422 | return valid; | 422 | return valid; |
423 | } | 423 | } |
424 | 424 | ||
425 | public Face NewFace(Gjk.MinkowskiVertice a, Gjk.MinkowskiVertice b, Gjk.MinkowskiVertice c) | 425 | public Face NewFace(Gjk.MinkowskiVertice a, Gjk.MinkowskiVertice b, Gjk.MinkowskiVertice c) |
426 | { | 426 | { |
427 | Face pf = new Face(); | 427 | Face pf = new Face(); |
428 | if (Set(ref pf, a, b, c)) | 428 | if (Set(ref pf, a, b, c)) |
429 | { | 429 | { |
430 | if (_root != null) _root._prev = pf; | 430 | if (_root != null) _root._prev = pf; |
431 | pf._prev = null; | 431 | pf._prev = null; |
432 | pf._next = _root; | 432 | pf._next = _root; |
433 | _root = pf; | 433 | _root = pf; |
434 | ++_nfaces; | 434 | ++_nfaces; |
435 | } | 435 | } |
436 | else | 436 | else |
437 | { | 437 | { |
438 | pf._prev = pf._next = null; | 438 | pf._prev = pf._next = null; |
439 | } | 439 | } |
440 | return (pf); | 440 | return (pf); |
441 | } | 441 | } |
442 | 442 | ||
443 | public void Detach(ref Face face) | 443 | public void Detach(ref Face face) |
444 | { | 444 | { |
445 | if (face._prev != null || face._next != null) | 445 | if (face._prev != null || face._next != null) |
446 | { | 446 | { |
447 | --_nfaces; | 447 | --_nfaces; |
448 | if (face == _root) | 448 | if (face == _root) |
449 | { | 449 | { |
450 | _root = face._next; | 450 | _root = face._next; |
451 | _root._prev = null; | 451 | _root._prev = null; |
452 | } | 452 | } |
453 | else | 453 | else |
454 | { | 454 | { |
455 | if (face._next == null) | 455 | if (face._next == null) |
456 | { | 456 | { |
457 | face._prev._next = null; | 457 | face._prev._next = null; |
458 | } | 458 | } |
459 | else | 459 | else |
460 | { | 460 | { |
461 | face._prev._next = face._next; | 461 | face._prev._next = face._next; |
462 | face._next._prev = face._prev; | 462 | face._next._prev = face._prev; |
463 | } | 463 | } |
464 | } | 464 | } |
465 | face._prev = face._next = null; | 465 | face._prev = face._next = null; |
466 | } | 466 | } |
467 | } | 467 | } |
468 | 468 | ||
469 | public void Link(ref Face f0, int e0, ref Face f1, int e1) | 469 | public void Link(ref Face f0, int e0, ref Face f1, int e1) |
470 | { | 470 | { |
471 | f0._faces[e0] = f1; f1._e[e1] = e0; | 471 | f0._faces[e0] = f1; f1._e[e1] = e0; |
472 | f1._faces[e1] = f0; f0._e[e0] = e1; | 472 | f1._faces[e1] = f0; f0._e[e0] = e1; |
473 | } | 473 | } |
474 | 474 | ||
475 | public Gjk.MinkowskiVertice Support(Vector3 w) | 475 | public Gjk.MinkowskiVertice Support(Vector3 w) |
476 | { | 476 | { |
477 | Gjk.MinkowskiVertice v = new Gjk.MinkowskiVertice(); | 477 | Gjk.MinkowskiVertice v = new Gjk.MinkowskiVertice(); |
478 | _gjk.Support(w, ref v); | 478 | _gjk.Support(w, ref v); |
479 | return v; | 479 | return v; |
480 | } | 480 | } |
481 | 481 | ||
482 | private static int[] mod3 ={ 0, 1, 2, 0, 1 }; | 482 | private static int[] mod3 ={ 0, 1, 2, 0, 1 }; |
483 | 483 | ||
484 | public int BuildHorizon(int markid, Gjk.MinkowskiVertice w, ref Face f, int e, ref Face cf, ref Face ff) | 484 | public int BuildHorizon(int markid, Gjk.MinkowskiVertice w, ref Face f, int e, ref Face cf, ref Face ff) |
485 | { | 485 | { |
486 | int ne = (0); | 486 | int ne = (0); |
487 | if (f._mark != markid) | 487 | if (f._mark != markid) |
488 | { | 488 | { |
489 | int e1 = (mod3[e + 1]); | 489 | int e1 = (mod3[e + 1]); |
490 | if ((Vector3.Dot(f._n, w.Vertice) + f._d) > 0) | 490 | if ((Vector3.Dot(f._n, w.Vertice) + f._d) > 0) |
491 | { | 491 | { |
492 | Face nf = NewFace(f._vertices[e1], f._vertices[e], w); | 492 | Face nf = NewFace(f._vertices[e1], f._vertices[e], w); |
493 | Link(ref nf, 0, ref f, e); | 493 | Link(ref nf, 0, ref f, e); |
494 | if (cf != null) Link(ref cf, 1, ref nf, 2); else ff = nf; | 494 | if (cf != null) Link(ref cf, 1, ref nf, 2); else ff = nf; |
495 | cf = nf; ne = 1; | 495 | cf = nf; ne = 1; |
496 | } | 496 | } |
497 | else | 497 | else |
498 | { | 498 | { |
499 | int e2 = (mod3[e + 2]); | 499 | int e2 = (mod3[e + 2]); |
500 | Detach(ref f); | 500 | Detach(ref f); |
501 | f._mark = markid; | 501 | f._mark = markid; |
502 | ne += BuildHorizon(markid, w, ref f._faces[e1], f._e[e1], ref cf, ref ff); | 502 | ne += BuildHorizon(markid, w, ref f._faces[e1], f._e[e1], ref cf, ref ff); |
503 | ne += BuildHorizon(markid, w, ref f._faces[e2], f._e[e2], ref cf, ref ff); | 503 | ne += BuildHorizon(markid, w, ref f._faces[e2], f._e[e2], ref cf, ref ff); |
504 | } | 504 | } |
505 | } | 505 | } |
506 | return (ne); | 506 | return (ne); |
507 | } | 507 | } |
508 | 508 | ||
509 | public float EvaluatePD() | 509 | public float EvaluatePD() |
510 | { | 510 | { |
511 | return EvaluatePD(_epaAccuracy); | 511 | return EvaluatePD(_epaAccuracy); |
512 | } | 512 | } |
513 | 513 | ||
514 | private int[,] fidx; | 514 | private int[,] fidx; |
515 | private int[,] eidx; | 515 | private int[,] eidx; |
516 | 516 | ||
517 | public float EvaluatePD(float accuracy) | 517 | public float EvaluatePD(float accuracy) |
518 | { | 518 | { |
519 | //Block* sablock = sa->BeginBlock(); | 519 | //Block* sablock = sa->BeginBlock(); |
520 | Face bestface = null; | 520 | Face bestface = null; |
521 | int markid = 1; | 521 | int markid = 1; |
522 | _depth = -_infinity; | 522 | _depth = -_infinity; |
523 | _normal = new Vector3(); | 523 | _normal = new Vector3(); |
524 | _root = null; | 524 | _root = null; |
525 | _nfaces = 0; | 525 | _nfaces = 0; |
526 | _iterations = 0; | 526 | _iterations = 0; |
527 | _failed = false; | 527 | _failed = false; |
528 | /* Prepare hull */ | 528 | /* Prepare hull */ |
529 | if (_gjk.EncloseOrigin()) | 529 | if (_gjk.EncloseOrigin()) |
530 | { | 530 | { |
531 | int nfidx = 0; | 531 | int nfidx = 0; |
532 | int neidx = 0; | 532 | int neidx = 0; |
533 | Gjk.MinkowskiVertice[] basemkv = new Gjk.MinkowskiVertice[5]; | 533 | Gjk.MinkowskiVertice[] basemkv = new Gjk.MinkowskiVertice[5]; |
534 | Face[] basefaces = new Face[6]; | 534 | Face[] basefaces = new Face[6]; |
535 | switch (_gjk.Order) | 535 | switch (_gjk.Order) |
536 | { | 536 | { |
537 | /* Tetrahedron */ | 537 | /* Tetrahedron */ |
538 | case 3: | 538 | case 3: |
539 | { | 539 | { |
540 | fidx = new int[,] { { 2, 1, 0 }, { 3, 0, 1 }, { 3, 1, 2 }, { 3, 2, 0 } }; | 540 | fidx = new int[,] { { 2, 1, 0 }, { 3, 0, 1 }, { 3, 1, 2 }, { 3, 2, 0 } }; |
541 | eidx = new int[,] { { 0, 0, 2, 1 }, { 0, 1, 1, 1 }, { 0, 2, 3, 1 }, { 1, 0, 3, 2 }, { 2, 0, 1, 2 }, { 3, 0, 2, 2 } }; | 541 | eidx = new int[,] { { 0, 0, 2, 1 }, { 0, 1, 1, 1 }, { 0, 2, 3, 1 }, { 1, 0, 3, 2 }, { 2, 0, 1, 2 }, { 3, 0, 2, 2 } }; |
542 | nfidx = 4; neidx = 6; | 542 | nfidx = 4; neidx = 6; |
543 | } break; | 543 | } break; |
544 | /* Hexahedron */ | 544 | /* Hexahedron */ |
545 | case 4: | 545 | case 4: |
546 | { | 546 | { |
547 | fidx = new int[,] { { 2, 0, 4 }, { 4, 1, 2 }, { 1, 4, 0 }, { 0, 3, 1 }, { 0, 2, 3 }, { 1, 3, 2 } }; | 547 | fidx = new int[,] { { 2, 0, 4 }, { 4, 1, 2 }, { 1, 4, 0 }, { 0, 3, 1 }, { 0, 2, 3 }, { 1, 3, 2 } }; |
548 | eidx = new int[,] { { 0, 0, 4, 0 }, { 0, 1, 2, 1 }, { 0, 2, 1, 2 }, { 1, 1, 5, 2 }, { 1, 0, 2, 0 }, { 2, 2, 3, 2 }, { 3, 1, 5, 0 }, { 3, 0, 4, 2 }, { 5, 1, 4, 1 } }; | 548 | eidx = new int[,] { { 0, 0, 4, 0 }, { 0, 1, 2, 1 }, { 0, 2, 1, 2 }, { 1, 1, 5, 2 }, { 1, 0, 2, 0 }, { 2, 2, 3, 2 }, { 3, 1, 5, 0 }, { 3, 0, 4, 2 }, { 5, 1, 4, 1 } }; |
549 | nfidx = 6; neidx = 9; | 549 | nfidx = 6; neidx = 9; |
550 | } break; | 550 | } break; |
551 | } | 551 | } |
552 | int i; | 552 | int i; |
553 | 553 | ||
554 | for (i = 0; i <= _gjk.Order; ++i) | 554 | for (i = 0; i <= _gjk.Order; ++i) |
555 | { | 555 | { |
556 | //basemkv[i] = (GJK::Mkv*)sa->Allocate(sizeof(GJK::Mkv)); | 556 | //basemkv[i] = (GJK::Mkv*)sa->Allocate(sizeof(GJK::Mkv)); |
557 | basemkv[i] = new Gjk.MinkowskiVertice(); | 557 | basemkv[i] = new Gjk.MinkowskiVertice(); |
558 | basemkv[i].Vertice = _gjk.Simplex[i].Vertice; | 558 | basemkv[i].Vertice = _gjk.Simplex[i].Vertice; |
559 | basemkv[i].Ray = _gjk.Simplex[i].Ray; | 559 | basemkv[i].Ray = _gjk.Simplex[i].Ray; |
560 | } | 560 | } |
561 | for (i = 0; i < nfidx; ++i) | 561 | for (i = 0; i < nfidx; ++i) |
562 | { | 562 | { |
563 | basefaces[i] = NewFace(basemkv[fidx[i, 0]], basemkv[fidx[i, 1]], basemkv[fidx[i, 2]]); | 563 | basefaces[i] = NewFace(basemkv[fidx[i, 0]], basemkv[fidx[i, 1]], basemkv[fidx[i, 2]]); |
564 | } | 564 | } |
565 | for (i = 0; i < neidx; ++i) | 565 | for (i = 0; i < neidx; ++i) |
566 | { | 566 | { |
567 | Link(ref basefaces[eidx[i, 0]], eidx[i, 1], ref basefaces[eidx[i, 2]], eidx[i, 3]); | 567 | Link(ref basefaces[eidx[i, 0]], eidx[i, 1], ref basefaces[eidx[i, 2]], eidx[i, 3]); |
568 | } | 568 | } |
569 | } | 569 | } |
570 | if (0 == _nfaces) | 570 | if (0 == _nfaces) |
571 | { | 571 | { |
572 | return _depth; | 572 | return _depth; |
573 | } | 573 | } |
574 | /* Expand hull */ | 574 | /* Expand hull */ |
575 | for (; _iterations < _epaMaxIterations; ++_iterations) | 575 | for (; _iterations < _epaMaxIterations; ++_iterations) |
576 | { | 576 | { |
577 | Face bf = FindBest(); | 577 | Face bf = FindBest(); |
578 | if (bf != null) | 578 | if (bf != null) |
579 | { | 579 | { |
580 | Gjk.MinkowskiVertice w = Support(-bf._n); | 580 | Gjk.MinkowskiVertice w = Support(-bf._n); |
581 | float d = Vector3.Dot(bf._n, w.Vertice) + bf._d; | 581 | float d = Vector3.Dot(bf._n, w.Vertice) + bf._d; |
582 | bestface = bf; | 582 | bestface = bf; |
583 | if (d < -accuracy) | 583 | if (d < -accuracy) |
584 | { | 584 | { |
585 | Face cf = null; | 585 | Face cf = null; |
586 | Face ff = null; | 586 | Face ff = null; |
587 | int nf = 0; | 587 | int nf = 0; |
588 | Detach(ref bf); | 588 | Detach(ref bf); |
589 | bf._mark = ++markid; | 589 | bf._mark = ++markid; |
590 | for (int i = 0; i < 3; ++i) | 590 | for (int i = 0; i < 3; ++i) |
591 | { | 591 | { |
592 | nf += BuildHorizon(markid, w, ref bf._faces[i], bf._e[i], ref cf, ref ff); | 592 | nf += BuildHorizon(markid, w, ref bf._faces[i], bf._e[i], ref cf, ref ff); |
593 | } | 593 | } |
594 | if (nf <= 2) { break; } | 594 | if (nf <= 2) { break; } |
595 | Link(ref cf, 1, ref ff, 2); | 595 | Link(ref cf, 1, ref ff, 2); |
596 | } | 596 | } |
597 | else break; | 597 | else break; |
598 | } | 598 | } |
599 | else break; | 599 | else break; |
600 | } | 600 | } |
601 | /* Extract contact */ | 601 | /* Extract contact */ |
602 | if (bestface != null) | 602 | if (bestface != null) |
603 | { | 603 | { |
604 | Vector3 b = GetCoordinates(bestface); | 604 | Vector3 b = GetCoordinates(bestface); |
605 | _normal = bestface._n; | 605 | _normal = bestface._n; |
606 | _depth = Max(0, bestface._d); | 606 | _depth = Max(0, bestface._d); |
607 | for (int i = 0; i < 2; ++i) | 607 | for (int i = 0; i < 2; ++i) |
608 | { | 608 | { |
609 | float s = i != 0 ? -1 : 1; | 609 | float s = i != 0 ? -1 : 1; |
610 | for (int j = 0; j < 3; ++j) | 610 | for (int j = 0; j < 3; ++j) |
611 | { | 611 | { |
612 | _features[i, j] = _gjk.LocalSupport(s * bestface._vertices[j].Ray, i); | 612 | _features[i, j] = _gjk.LocalSupport(s * bestface._vertices[j].Ray, i); |
613 | } | 613 | } |
614 | } | 614 | } |
615 | _nearest[0] = _features[0, 0] * b.X + _features[0, 1] * b.Y + _features[0, 2] * b.Z; | 615 | _nearest[0] = _features[0, 0] * b.X + _features[0, 1] * b.Y + _features[0, 2] * b.Z; |
616 | _nearest[1] = _features[1, 0] * b.X + _features[1, 1] * b.Y + _features[1, 2] * b.Z; | 616 | _nearest[1] = _features[1, 0] * b.X + _features[1, 1] * b.Y + _features[1, 2] * b.Z; |
617 | } | 617 | } |
618 | else _failed = true; | 618 | else _failed = true; |
619 | return _depth; | 619 | return _depth; |
620 | } | 620 | } |
621 | 621 | ||
622 | private float Max(float a, float b) | 622 | private float Max(float a, float b) |
623 | { | 623 | { |
624 | return (a > b ? a : b); | 624 | return (a > b ? a : b); |
625 | } | 625 | } |
626 | 626 | ||
627 | private float Min(float a, float b) | 627 | private float Min(float a, float b) |
628 | { | 628 | { |
629 | return (a < b ? a : b); | 629 | return (a < b ? a : b); |
630 | } | 630 | } |
631 | } | 631 | } |
632 | } | 632 | } |
633 | } | 633 | } |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpaPenetrationDepthSolver.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpaPenetrationDepthSolver.cs index 739b4fc..551449f 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpaPenetrationDepthSolver.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpaPenetrationDepthSolver.cs | |||
@@ -1,56 +1,56 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | /// <summary> | 29 | /// <summary> |
30 | /// EpaPenetrationDepthSolver uses the Expanding Polytope Algorithm to | 30 | /// EpaPenetrationDepthSolver uses the Expanding Polytope Algorithm to |
31 | /// calculate the penetration depth between two convex shapes. | 31 | /// calculate the penetration depth between two convex shapes. |
32 | /// </summary> | 32 | /// </summary> |
33 | public class GjkEpaPenetrationDepthSolver : IConvexPenetrationDepthSolver | 33 | public class GjkEpaPenetrationDepthSolver : IConvexPenetrationDepthSolver |
34 | { | 34 | { |
35 | public bool CalculatePenetrationDepth(ISimplexSolver simplexSolver, ConvexShape convexA, ConvexShape convexB, Matrix transformA, Matrix transformB, Vector3 vector, out Vector3 ptrA, out Vector3 ptrB, IDebugDraw debugDraw) | 35 | public bool CalculatePenetrationDepth(ISimplexSolver simplexSolver, ConvexShape convexA, ConvexShape convexB, Matrix transformA, Matrix transformB, Vector3 vector, out Vector3 ptrA, out Vector3 ptrB, IDebugDraw debugDraw) |
36 | { | 36 | { |
37 | float radialmargin = 0; | 37 | float radialmargin = 0; |
38 | 38 | ||
39 | GjkEpaSolver.Results results; | 39 | GjkEpaSolver.Results results; |
40 | if (GjkEpaSolver.Collide(convexA, transformA, | 40 | if (GjkEpaSolver.Collide(convexA, transformA, |
41 | convexB, transformB, | 41 | convexB, transformB, |
42 | radialmargin, out results)) | 42 | radialmargin, out results)) |
43 | { | 43 | { |
44 | // debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0)); | 44 | // debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0)); |
45 | //resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth); | 45 | //resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth); |
46 | ptrA = results.Witnesses[0]; | 46 | ptrA = results.Witnesses[0]; |
47 | ptrB = results.Witnesses[1]; | 47 | ptrB = results.Witnesses[1]; |
48 | return true; | 48 | return true; |
49 | } | 49 | } |
50 | ptrA = new Vector3(); | 50 | ptrA = new Vector3(); |
51 | ptrB = new Vector3(); | 51 | ptrB = new Vector3(); |
52 | 52 | ||
53 | return false; | 53 | return false; |
54 | } | 54 | } |
55 | } | 55 | } |
56 | } | 56 | } |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpaSolver.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpaSolver.cs index aa9d61e..20af192 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpaSolver.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpaSolver.cs | |||
@@ -1,101 +1,101 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | /// <summary> | 29 | /// <summary> |
30 | /// GjkEpaSolver contributed under zlib by Nathanael Presson | 30 | /// GjkEpaSolver contributed under zlib by Nathanael Presson |
31 | /// </summary> | 31 | /// </summary> |
32 | public class GjkEpaSolver | 32 | public class GjkEpaSolver |
33 | { | 33 | { |
34 | public struct Results | 34 | public struct Results |
35 | { | 35 | { |
36 | public enum Status | 36 | public enum Status |
37 | { | 37 | { |
38 | Separated, /* Shapes doesnt penetrate */ | 38 | Separated, /* Shapes doesnt penetrate */ |
39 | Penetrating, /* Shapes are penetrating */ | 39 | Penetrating, /* Shapes are penetrating */ |
40 | GjkFailed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */ | 40 | GjkFailed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */ |
41 | EpaFailed, /* EPA phase fail, bigger problem, need to save parameters, and debug */ | 41 | EpaFailed, /* EPA phase fail, bigger problem, need to save parameters, and debug */ |
42 | } | 42 | } |
43 | 43 | ||
44 | private Vector3[] _witnesses; | 44 | private Vector3[] _witnesses; |
45 | private Vector3 _normal; | 45 | private Vector3 _normal; |
46 | private float _depth; | 46 | private float _depth; |
47 | private int _epaIterations; | 47 | private int _epaIterations; |
48 | private int _gjkIterations; | 48 | private int _gjkIterations; |
49 | private Status _status; | 49 | private Status _status; |
50 | 50 | ||
51 | public Vector3[] Witnesses { get { return _witnesses; } set { _witnesses = value; } } | 51 | public Vector3[] Witnesses { get { return _witnesses; } set { _witnesses = value; } } |
52 | public Vector3 Normal { get { return _normal; } set { _normal = value; } } | 52 | public Vector3 Normal { get { return _normal; } set { _normal = value; } } |
53 | public float Depth { get { return _depth; } set { _depth = value; } } | 53 | public float Depth { get { return _depth; } set { _depth = value; } } |
54 | public int EpaIterations { get { return _epaIterations; } set { _epaIterations = value; } } | 54 | public int EpaIterations { get { return _epaIterations; } set { _epaIterations = value; } } |
55 | public int GjkIterations { get { return _gjkIterations; } set { _gjkIterations = value; } } | 55 | public int GjkIterations { get { return _gjkIterations; } set { _gjkIterations = value; } } |
56 | public Status ResultStatus { get { return _status; } set { _status = value; } } | 56 | public Status ResultStatus { get { return _status; } set { _status = value; } } |
57 | } | 57 | } |
58 | 58 | ||
59 | public static bool Collide(ConvexShape shapeA, Matrix wtrsA, | 59 | public static bool Collide(ConvexShape shapeA, Matrix wtrsA, |
60 | ConvexShape shapeB, Matrix wtrsB, | 60 | ConvexShape shapeB, Matrix wtrsB, |
61 | float radialmargin, | 61 | float radialmargin, |
62 | out Results results) | 62 | out Results results) |
63 | { | 63 | { |
64 | /* Initialize */ | 64 | /* Initialize */ |
65 | results = new Results(); | 65 | results = new Results(); |
66 | results.Witnesses = new Vector3[2]; | 66 | results.Witnesses = new Vector3[2]; |
67 | results.Witnesses[0] = | 67 | results.Witnesses[0] = |
68 | results.Witnesses[1] = | 68 | results.Witnesses[1] = |
69 | results.Normal = new Vector3(); | 69 | results.Normal = new Vector3(); |
70 | results.Depth = 0; | 70 | results.Depth = 0; |
71 | results.ResultStatus = Results.Status.Separated; | 71 | results.ResultStatus = Results.Status.Separated; |
72 | results.EpaIterations = 0; | 72 | results.EpaIterations = 0; |
73 | results.GjkIterations = 0; | 73 | results.GjkIterations = 0; |
74 | /* Use GJK to locate origin */ | 74 | /* Use GJK to locate origin */ |
75 | GjkEpa.Gjk gjk = new GjkEpa.Gjk(wtrsA, wtrsA.Translation, shapeA, | 75 | GjkEpa.Gjk gjk = new GjkEpa.Gjk(wtrsA, wtrsA.Translation, shapeA, |
76 | wtrsB, wtrsB.Translation, shapeB, | 76 | wtrsB, wtrsB.Translation, shapeB, |
77 | radialmargin + GjkEpa.EpaAccuracy); | 77 | radialmargin + GjkEpa.EpaAccuracy); |
78 | bool collide = gjk.SearchOrigin(); | 78 | bool collide = gjk.SearchOrigin(); |
79 | results.GjkIterations = gjk.Iterations + 1; | 79 | results.GjkIterations = gjk.Iterations + 1; |
80 | if (collide) | 80 | if (collide) |
81 | { | 81 | { |
82 | /* Then EPA for penetration depth */ | 82 | /* Then EPA for penetration depth */ |
83 | GjkEpa.Epa epa = new GjkEpa.Epa(gjk); | 83 | GjkEpa.Epa epa = new GjkEpa.Epa(gjk); |
84 | float pd = epa.EvaluatePD(); | 84 | float pd = epa.EvaluatePD(); |
85 | results.EpaIterations = epa.Iterations + 1; | 85 | results.EpaIterations = epa.Iterations + 1; |
86 | if (pd > 0) | 86 | if (pd > 0) |
87 | { | 87 | { |
88 | results.ResultStatus = Results.Status.Penetrating; | 88 | results.ResultStatus = Results.Status.Penetrating; |
89 | results.Normal = epa.Normal; | 89 | results.Normal = epa.Normal; |
90 | results.Depth = pd; | 90 | results.Depth = pd; |
91 | results.Witnesses[0] = epa.Nearest[0]; | 91 | results.Witnesses[0] = epa.Nearest[0]; |
92 | results.Witnesses[1] = epa.Nearest[1]; | 92 | results.Witnesses[1] = epa.Nearest[1]; |
93 | return true; | 93 | return true; |
94 | } | 94 | } |
95 | else { if (epa.Failed) results.ResultStatus = Results.Status.EpaFailed; } | 95 | else { if (epa.Failed) results.ResultStatus = Results.Status.EpaFailed; } |
96 | } | 96 | } |
97 | else { if (gjk.Failed) results.ResultStatus = Results.Status.GjkFailed; } | 97 | else { if (gjk.Failed) results.ResultStatus = Results.Status.GjkFailed; } |
98 | return false; | 98 | return false; |
99 | } | 99 | } |
100 | } | 100 | } |
101 | } | 101 | } |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkPairDetector.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkPairDetector.cs index 0831ff5..7557ed9 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkPairDetector.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkPairDetector.cs | |||
@@ -1,343 +1,343 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | public class GjkPairDetector : DiscreteCollisionDetectorInterface | 29 | public class GjkPairDetector : DiscreteCollisionDetectorInterface |
30 | { | 30 | { |
31 | private Vector3 _cachedSeparatingAxis; | 31 | private Vector3 _cachedSeparatingAxis; |
32 | private IConvexPenetrationDepthSolver _penetrationDepthSolver; | 32 | private IConvexPenetrationDepthSolver _penetrationDepthSolver; |
33 | private ISimplexSolver _simplexSolver; | 33 | private ISimplexSolver _simplexSolver; |
34 | private ConvexShape _minkowskiA, _minkowskiB; | 34 | private ConvexShape _minkowskiA, _minkowskiB; |
35 | private bool _ignoreMargin; | 35 | private bool _ignoreMargin; |
36 | 36 | ||
37 | private int _lastUsedMethod; | 37 | private int _lastUsedMethod; |
38 | private int _currentIteration; | 38 | private int _currentIteration; |
39 | private int _degenerateSimplex; | 39 | private int _degenerateSimplex; |
40 | private int _catchDegeneracies; | 40 | private int _catchDegeneracies; |
41 | 41 | ||
42 | private static int _numDeepPenetrationChecks = 0; | 42 | private static int _numDeepPenetrationChecks = 0; |
43 | private static int _numGjkChecks = 0; | 43 | private static int _numGjkChecks = 0; |
44 | 44 | ||
45 | private const float RelativeError2 = 1.0e-6f; | 45 | private const float RelativeError2 = 1.0e-6f; |
46 | 46 | ||
47 | #region Properties | 47 | #region Properties |
48 | public int LastUsedMethod | 48 | public int LastUsedMethod |
49 | { | 49 | { |
50 | get { return _lastUsedMethod; } | 50 | get { return _lastUsedMethod; } |
51 | set { _lastUsedMethod = value; } | 51 | set { _lastUsedMethod = value; } |
52 | } | 52 | } |
53 | 53 | ||
54 | public int CurrentIteration | 54 | public int CurrentIteration |
55 | { | 55 | { |
56 | get { return _currentIteration; } | 56 | get { return _currentIteration; } |
57 | set { _currentIteration = value; } | 57 | set { _currentIteration = value; } |
58 | } | 58 | } |
59 | 59 | ||
60 | public int DegenerateSimplex | 60 | public int DegenerateSimplex |
61 | { | 61 | { |
62 | get { return _degenerateSimplex; } | 62 | get { return _degenerateSimplex; } |
63 | set { _degenerateSimplex = value; } | 63 | set { _degenerateSimplex = value; } |
64 | } | 64 | } |
65 | 65 | ||
66 | public int CatchDegeneracies | 66 | public int CatchDegeneracies |
67 | { | 67 | { |
68 | get { return _catchDegeneracies; } | 68 | get { return _catchDegeneracies; } |
69 | set { _catchDegeneracies = value; } | 69 | set { _catchDegeneracies = value; } |
70 | } | 70 | } |
71 | 71 | ||
72 | public static int DeepPenetrationChecksCount { get { return _numDeepPenetrationChecks; } } | 72 | public static int DeepPenetrationChecksCount { get { return _numDeepPenetrationChecks; } } |
73 | public static int GjkChecksCount { get { return _numGjkChecks; } } | 73 | public static int GjkChecksCount { get { return _numGjkChecks; } } |
74 | #endregion | 74 | #endregion |
75 | 75 | ||
76 | public GjkPairDetector(ConvexShape objectA, ConvexShape objectB, | 76 | public GjkPairDetector(ConvexShape objectA, ConvexShape objectB, |
77 | ISimplexSolver simplexSolver, | 77 | ISimplexSolver simplexSolver, |
78 | IConvexPenetrationDepthSolver penetrationDepthSolver) | 78 | IConvexPenetrationDepthSolver penetrationDepthSolver) |
79 | { | 79 | { |
80 | _cachedSeparatingAxis = new Vector3(0, 0, 1); | 80 | _cachedSeparatingAxis = new Vector3(0, 0, 1); |
81 | 81 | ||
82 | _penetrationDepthSolver = penetrationDepthSolver; | 82 | _penetrationDepthSolver = penetrationDepthSolver; |
83 | _simplexSolver = simplexSolver; | 83 | _simplexSolver = simplexSolver; |
84 | _minkowskiA = objectA; | 84 | _minkowskiA = objectA; |
85 | _minkowskiB = objectB; | 85 | _minkowskiB = objectB; |
86 | _ignoreMargin = false; | 86 | _ignoreMargin = false; |
87 | _lastUsedMethod = -1; | 87 | _lastUsedMethod = -1; |
88 | _catchDegeneracies = 1; | 88 | _catchDegeneracies = 1; |
89 | } | 89 | } |
90 | 90 | ||
91 | public void setMinkowskiA(ConvexShape minkA) | 91 | public void setMinkowskiA(ConvexShape minkA) |
92 | { | 92 | { |
93 | _minkowskiA = minkA; | 93 | _minkowskiA = minkA; |
94 | } | 94 | } |
95 | 95 | ||
96 | public void setMinkowskiB(ConvexShape minkB) | 96 | public void setMinkowskiB(ConvexShape minkB) |
97 | { | 97 | { |
98 | _minkowskiB = minkB; | 98 | _minkowskiB = minkB; |
99 | } | 99 | } |
100 | public void setCachedSeperatingAxis(Vector3 seperatingAxis) | 100 | public void setCachedSeperatingAxis(Vector3 seperatingAxis) |
101 | { | 101 | { |
102 | _cachedSeparatingAxis = seperatingAxis; | 102 | _cachedSeparatingAxis = seperatingAxis; |
103 | } | 103 | } |
104 | 104 | ||
105 | public void setPenetrationDepthSolver(IConvexPenetrationDepthSolver penetrationDepthSolver) | 105 | public void setPenetrationDepthSolver(IConvexPenetrationDepthSolver penetrationDepthSolver) |
106 | { | 106 | { |
107 | this._penetrationDepthSolver = penetrationDepthSolver; | 107 | this._penetrationDepthSolver = penetrationDepthSolver; |
108 | } | 108 | } |
109 | 109 | ||
110 | public void setIgnoreMargin(bool ignoreMargin) | 110 | public void setIgnoreMargin(bool ignoreMargin) |
111 | { | 111 | { |
112 | this._ignoreMargin = ignoreMargin; | 112 | this._ignoreMargin = ignoreMargin; |
113 | } | 113 | } |
114 | 114 | ||
115 | public override void GetClosestPoints(DiscreteCollisionDetectorInterface.ClosestPointInput input, DiscreteCollisionDetectorInterface.Result output, IDebugDraw debugDraw) | 115 | public override void GetClosestPoints(DiscreteCollisionDetectorInterface.ClosestPointInput input, DiscreteCollisionDetectorInterface.Result output, IDebugDraw debugDraw) |
116 | { | 116 | { |
117 | float distance = 0; | 117 | float distance = 0; |
118 | 118 | ||
119 | Vector3 normalInB = new Vector3(); | 119 | Vector3 normalInB = new Vector3(); |
120 | Vector3 pointOnA = new Vector3(), pointOnB = new Vector3(); | 120 | Vector3 pointOnA = new Vector3(), pointOnB = new Vector3(); |
121 | 121 | ||
122 | Matrix localTransA = input.TransformA; | 122 | Matrix localTransA = input.TransformA; |
123 | Matrix localTransB = input.TransformB; | 123 | Matrix localTransB = input.TransformB; |
124 | 124 | ||
125 | Vector3 positionOffset = (localTransA.Translation + localTransB.Translation) * 0.5f; | 125 | Vector3 positionOffset = (localTransA.Translation + localTransB.Translation) * 0.5f; |
126 | localTransA.Translation -= positionOffset; | 126 | localTransA.Translation -= positionOffset; |
127 | localTransB.Translation -= positionOffset; | 127 | localTransB.Translation -= positionOffset; |
128 | 128 | ||
129 | float marginA = _minkowskiA.Margin; | 129 | float marginA = _minkowskiA.Margin; |
130 | float marginB = _minkowskiB.Margin; | 130 | float marginB = _minkowskiB.Margin; |
131 | 131 | ||
132 | _numGjkChecks++; | 132 | _numGjkChecks++; |
133 | 133 | ||
134 | if (_ignoreMargin) | 134 | if (_ignoreMargin) |
135 | { | 135 | { |
136 | marginA = 0; | 136 | marginA = 0; |
137 | marginB = 0; | 137 | marginB = 0; |
138 | } | 138 | } |
139 | 139 | ||
140 | _currentIteration = 0; | 140 | _currentIteration = 0; |
141 | 141 | ||
142 | int gjkMaxIter = 1000; | 142 | int gjkMaxIter = 1000; |
143 | _cachedSeparatingAxis = new Vector3(0, 1, 0); | 143 | _cachedSeparatingAxis = new Vector3(0, 1, 0); |
144 | 144 | ||
145 | bool isValid = false; | 145 | bool isValid = false; |
146 | bool checkSimplex = false; | 146 | bool checkSimplex = false; |
147 | bool checkPenetration = true; | 147 | bool checkPenetration = true; |
148 | _degenerateSimplex = 0; | 148 | _degenerateSimplex = 0; |
149 | 149 | ||
150 | _lastUsedMethod = -1; | 150 | _lastUsedMethod = -1; |
151 | 151 | ||
152 | { | 152 | { |
153 | float squaredDistance = MathHelper.Infinity; | 153 | float squaredDistance = MathHelper.Infinity; |
154 | float delta = 0; | 154 | float delta = 0; |
155 | 155 | ||
156 | float margin = marginA + marginB; | 156 | float margin = marginA + marginB; |
157 | 157 | ||
158 | _simplexSolver.Reset(); | 158 | _simplexSolver.Reset(); |
159 | 159 | ||
160 | while (true) | 160 | while (true) |
161 | { | 161 | { |
162 | Matrix transABasis = input.TransformA; | 162 | Matrix transABasis = input.TransformA; |
163 | transABasis.Translation = Vector3.Zero; | 163 | transABasis.Translation = Vector3.Zero; |
164 | 164 | ||
165 | Matrix transBBasis = input.TransformB; | 165 | Matrix transBBasis = input.TransformB; |
166 | transBBasis.Translation = Vector3.Zero; | 166 | transBBasis.Translation = Vector3.Zero; |
167 | 167 | ||
168 | Vector3 seperatingAxisInA = Vector3.TransformNormal(-_cachedSeparatingAxis, transABasis); | 168 | Vector3 seperatingAxisInA = Vector3.TransformNormal(-_cachedSeparatingAxis, transABasis); |
169 | Vector3 seperatingAxisInB = Vector3.TransformNormal(_cachedSeparatingAxis, transBBasis); | 169 | Vector3 seperatingAxisInB = Vector3.TransformNormal(_cachedSeparatingAxis, transBBasis); |
170 | 170 | ||
171 | Vector3 pInA = _minkowskiA.LocalGetSupportingVertexWithoutMargin(seperatingAxisInA); | 171 | Vector3 pInA = _minkowskiA.LocalGetSupportingVertexWithoutMargin(seperatingAxisInA); |
172 | Vector3 qInB = _minkowskiB.LocalGetSupportingVertexWithoutMargin(seperatingAxisInB); | 172 | Vector3 qInB = _minkowskiB.LocalGetSupportingVertexWithoutMargin(seperatingAxisInB); |
173 | Vector3 pWorld = MathHelper.MatrixToVector(localTransA, pInA); | 173 | Vector3 pWorld = MathHelper.MatrixToVector(localTransA, pInA); |
174 | Vector3 qWorld = MathHelper.MatrixToVector(localTransB, qInB); | 174 | Vector3 qWorld = MathHelper.MatrixToVector(localTransB, qInB); |
175 | 175 | ||
176 | Vector3 w = pWorld - qWorld; | 176 | Vector3 w = pWorld - qWorld; |
177 | delta = Vector3.Dot(_cachedSeparatingAxis, w); | 177 | delta = Vector3.Dot(_cachedSeparatingAxis, w); |
178 | 178 | ||
179 | if ((delta > 0.0) && (delta * delta > squaredDistance * input.MaximumDistanceSquared)) | 179 | if ((delta > 0.0) && (delta * delta > squaredDistance * input.MaximumDistanceSquared)) |
180 | { | 180 | { |
181 | checkPenetration = false; | 181 | checkPenetration = false; |
182 | break; | 182 | break; |
183 | } | 183 | } |
184 | 184 | ||
185 | if (_simplexSolver.InSimplex(w)) | 185 | if (_simplexSolver.InSimplex(w)) |
186 | { | 186 | { |
187 | _degenerateSimplex = 1; | 187 | _degenerateSimplex = 1; |
188 | checkSimplex = true; | 188 | checkSimplex = true; |
189 | break; | 189 | break; |
190 | } | 190 | } |
191 | 191 | ||
192 | float f0 = squaredDistance - delta; | 192 | float f0 = squaredDistance - delta; |
193 | float f1 = squaredDistance * RelativeError2; | 193 | float f1 = squaredDistance * RelativeError2; |
194 | 194 | ||
195 | if (f0 <= f1) | 195 | if (f0 <= f1) |
196 | { | 196 | { |
197 | if (f0 <= 0.0f) | 197 | if (f0 <= 0.0f) |
198 | { | 198 | { |
199 | _degenerateSimplex = 2; | 199 | _degenerateSimplex = 2; |
200 | } | 200 | } |
201 | 201 | ||
202 | checkSimplex = true; | 202 | checkSimplex = true; |
203 | break; | 203 | break; |
204 | } | 204 | } |
205 | 205 | ||
206 | _simplexSolver.AddVertex(w, pWorld, qWorld); | 206 | _simplexSolver.AddVertex(w, pWorld, qWorld); |
207 | 207 | ||
208 | if (!_simplexSolver.Closest(out _cachedSeparatingAxis)) | 208 | if (!_simplexSolver.Closest(out _cachedSeparatingAxis)) |
209 | { | 209 | { |
210 | _degenerateSimplex = 3; | 210 | _degenerateSimplex = 3; |
211 | checkSimplex = true; | 211 | checkSimplex = true; |
212 | break; | 212 | break; |
213 | } | 213 | } |
214 | 214 | ||
215 | float previouseSquaredDistance = squaredDistance; | 215 | float previouseSquaredDistance = squaredDistance; |
216 | squaredDistance = _cachedSeparatingAxis.LengthSquared(); | 216 | squaredDistance = _cachedSeparatingAxis.LengthSquared(); |
217 | 217 | ||
218 | if (previouseSquaredDistance - squaredDistance <= MathHelper.Epsilon * previouseSquaredDistance) | 218 | if (previouseSquaredDistance - squaredDistance <= MathHelper.Epsilon * previouseSquaredDistance) |
219 | { | 219 | { |
220 | _simplexSolver.BackupClosest(out _cachedSeparatingAxis); | 220 | _simplexSolver.BackupClosest(out _cachedSeparatingAxis); |
221 | checkSimplex = true; | 221 | checkSimplex = true; |
222 | break; | 222 | break; |
223 | } | 223 | } |
224 | 224 | ||
225 | if (_currentIteration++ > gjkMaxIter) | 225 | if (_currentIteration++ > gjkMaxIter) |
226 | { | 226 | { |
227 | #if DEBUG | 227 | #if DEBUG |
228 | Console.WriteLine("GjkPairDetector maxIter exceeded: {0}", _currentIteration); | 228 | Console.WriteLine("GjkPairDetector maxIter exceeded: {0}", _currentIteration); |
229 | Console.WriteLine("sepAxis=({0},{1},{2}), squaredDistance = {3}, shapeTypeA={4}, shapeTypeB={5}", | 229 | Console.WriteLine("sepAxis=({0},{1},{2}), squaredDistance = {3}, shapeTypeA={4}, shapeTypeB={5}", |
230 | _cachedSeparatingAxis.X, | 230 | _cachedSeparatingAxis.X, |
231 | _cachedSeparatingAxis.Y, | 231 | _cachedSeparatingAxis.Y, |
232 | _cachedSeparatingAxis.Z, | 232 | _cachedSeparatingAxis.Z, |
233 | squaredDistance, | 233 | squaredDistance, |
234 | _minkowskiA.ShapeType, | 234 | _minkowskiA.ShapeType, |
235 | _minkowskiB.ShapeType | 235 | _minkowskiB.ShapeType |
236 | ); | 236 | ); |
237 | #endif | 237 | #endif |
238 | break; | 238 | break; |
239 | } | 239 | } |
240 | 240 | ||
241 | bool check = (!_simplexSolver.FullSimplex); | 241 | bool check = (!_simplexSolver.FullSimplex); |
242 | 242 | ||
243 | if (!check) | 243 | if (!check) |
244 | { | 244 | { |
245 | _simplexSolver.BackupClosest(out _cachedSeparatingAxis); | 245 | _simplexSolver.BackupClosest(out _cachedSeparatingAxis); |
246 | break; | 246 | break; |
247 | } | 247 | } |
248 | } | 248 | } |
249 | 249 | ||
250 | if (checkSimplex) | 250 | if (checkSimplex) |
251 | { | 251 | { |
252 | _simplexSolver.ComputePoints(out pointOnA, out pointOnB); | 252 | _simplexSolver.ComputePoints(out pointOnA, out pointOnB); |
253 | normalInB = pointOnA - pointOnB; | 253 | normalInB = pointOnA - pointOnB; |
254 | float lenSqr = _cachedSeparatingAxis.LengthSquared(); | 254 | float lenSqr = _cachedSeparatingAxis.LengthSquared(); |
255 | 255 | ||
256 | if (lenSqr < 0.0001f) | 256 | if (lenSqr < 0.0001f) |
257 | { | 257 | { |
258 | _degenerateSimplex = 5; | 258 | _degenerateSimplex = 5; |
259 | } | 259 | } |
260 | 260 | ||
261 | if (lenSqr > MathHelper.Epsilon * MathHelper.Epsilon) | 261 | if (lenSqr > MathHelper.Epsilon * MathHelper.Epsilon) |
262 | { | 262 | { |
263 | float rlen = 1.0f / (float)Math.Sqrt((float)lenSqr); | 263 | float rlen = 1.0f / (float)Math.Sqrt((float)lenSqr); |
264 | normalInB *= rlen; | 264 | normalInB *= rlen; |
265 | float s = (float)Math.Sqrt((float)squaredDistance); | 265 | float s = (float)Math.Sqrt((float)squaredDistance); |
266 | 266 | ||
267 | BulletDebug.Assert(s > 0); | 267 | BulletDebug.Assert(s > 0); |
268 | pointOnA -= _cachedSeparatingAxis * (marginA / s); | 268 | pointOnA -= _cachedSeparatingAxis * (marginA / s); |
269 | pointOnB += _cachedSeparatingAxis * (marginB / s); | 269 | pointOnB += _cachedSeparatingAxis * (marginB / s); |
270 | distance = ((1 / rlen) - margin); | 270 | distance = ((1 / rlen) - margin); |
271 | 271 | ||
272 | isValid = true; | 272 | isValid = true; |
273 | 273 | ||
274 | _lastUsedMethod = 1; | 274 | _lastUsedMethod = 1; |
275 | } | 275 | } |
276 | else | 276 | else |
277 | { | 277 | { |
278 | _lastUsedMethod = 2; | 278 | _lastUsedMethod = 2; |
279 | } | 279 | } |
280 | } | 280 | } |
281 | 281 | ||
282 | bool catchDegeneratePenetrationCase = | 282 | bool catchDegeneratePenetrationCase = |
283 | (_catchDegeneracies != 0 && _penetrationDepthSolver != null && _degenerateSimplex != 0 && ((distance + margin) < 0.01f)); | 283 | (_catchDegeneracies != 0 && _penetrationDepthSolver != null && _degenerateSimplex != 0 && ((distance + margin) < 0.01f)); |
284 | 284 | ||
285 | if (checkPenetration && (!isValid || catchDegeneratePenetrationCase)) | 285 | if (checkPenetration && (!isValid || catchDegeneratePenetrationCase)) |
286 | { | 286 | { |
287 | #warning Check this | 287 | #warning Check this |
288 | if (_penetrationDepthSolver != null) | 288 | if (_penetrationDepthSolver != null) |
289 | { | 289 | { |
290 | Vector3 tmpPointOnA, tmpPointOnB; | 290 | Vector3 tmpPointOnA, tmpPointOnB; |
291 | 291 | ||
292 | _numDeepPenetrationChecks++; | 292 | _numDeepPenetrationChecks++; |
293 | 293 | ||
294 | bool isValid2 = _penetrationDepthSolver.CalculatePenetrationDepth( | 294 | bool isValid2 = _penetrationDepthSolver.CalculatePenetrationDepth( |
295 | _simplexSolver, _minkowskiA, _minkowskiB, localTransA, localTransB, | 295 | _simplexSolver, _minkowskiA, _minkowskiB, localTransA, localTransB, |
296 | _cachedSeparatingAxis, out tmpPointOnA, out tmpPointOnB, | 296 | _cachedSeparatingAxis, out tmpPointOnA, out tmpPointOnB, |
297 | debugDraw | 297 | debugDraw |
298 | ); | 298 | ); |
299 | 299 | ||
300 | if (isValid2) | 300 | if (isValid2) |
301 | { | 301 | { |
302 | Vector3 tmpNormalInB = tmpPointOnB - tmpPointOnA; | 302 | Vector3 tmpNormalInB = tmpPointOnB - tmpPointOnA; |
303 | float lengSqr = tmpNormalInB.LengthSquared(); | 303 | float lengSqr = tmpNormalInB.LengthSquared(); |
304 | 304 | ||
305 | if (lengSqr > (MathHelper.Epsilon * MathHelper.Epsilon)) | 305 | if (lengSqr > (MathHelper.Epsilon * MathHelper.Epsilon)) |
306 | { | 306 | { |
307 | tmpNormalInB /= (float)Math.Sqrt((float)lengSqr); | 307 | tmpNormalInB /= (float)Math.Sqrt((float)lengSqr); |
308 | float distance2 = -(tmpPointOnA - tmpPointOnB).Length(); | 308 | float distance2 = -(tmpPointOnA - tmpPointOnB).Length(); |
309 | 309 | ||
310 | if (!isValid || (distance2 < distance)) | 310 | if (!isValid || (distance2 < distance)) |
311 | { | 311 | { |
312 | distance = distance2; | 312 | distance = distance2; |
313 | pointOnA = tmpPointOnA; | 313 | pointOnA = tmpPointOnA; |
314 | pointOnB = tmpPointOnB; | 314 | pointOnB = tmpPointOnB; |
315 | normalInB = tmpNormalInB; | 315 | normalInB = tmpNormalInB; |
316 | isValid = true; | 316 | isValid = true; |
317 | _lastUsedMethod = 3; | 317 | _lastUsedMethod = 3; |
318 | } | 318 | } |
319 | else | 319 | else |
320 | { | 320 | { |
321 | 321 | ||
322 | } | 322 | } |
323 | } | 323 | } |
324 | else | 324 | else |
325 | { | 325 | { |
326 | _lastUsedMethod = 4; | 326 | _lastUsedMethod = 4; |
327 | } | 327 | } |
328 | } | 328 | } |
329 | else | 329 | else |
330 | { | 330 | { |
331 | _lastUsedMethod = 5; | 331 | _lastUsedMethod = 5; |
332 | } | 332 | } |
333 | } | 333 | } |
334 | } | 334 | } |
335 | 335 | ||
336 | if (isValid) | 336 | if (isValid) |
337 | { | 337 | { |
338 | output.AddContactPoint(normalInB, pointOnB + positionOffset, distance); | 338 | output.AddContactPoint(normalInB, pointOnB + positionOffset, distance); |
339 | } | 339 | } |
340 | } | 340 | } |
341 | } | 341 | } |
342 | } | 342 | } |
343 | } \ No newline at end of file | 343 | } \ No newline at end of file |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/IConvexPenetrationDepthSolver.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/IConvexPenetrationDepthSolver.cs index 59fd486..08206c8 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/IConvexPenetrationDepthSolver.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/IConvexPenetrationDepthSolver.cs | |||
@@ -1,42 +1,42 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | /// <summary> | 29 | /// <summary> |
30 | /// IConvexPenetrationDepthSolver provides an interface for penetration depth calculation. | 30 | /// IConvexPenetrationDepthSolver provides an interface for penetration depth calculation. |
31 | /// </summary> | 31 | /// </summary> |
32 | public interface IConvexPenetrationDepthSolver | 32 | public interface IConvexPenetrationDepthSolver |
33 | { | 33 | { |
34 | bool CalculatePenetrationDepth( | 34 | bool CalculatePenetrationDepth( |
35 | ISimplexSolver simplexSolver, | 35 | ISimplexSolver simplexSolver, |
36 | ConvexShape convexA, ConvexShape convexB, | 36 | ConvexShape convexA, ConvexShape convexB, |
37 | Matrix transformA, Matrix transformB, | 37 | Matrix transformA, Matrix transformB, |
38 | Vector3 vector, out Vector3 ptrA, out Vector3 ptrB, | 38 | Vector3 vector, out Vector3 ptrA, out Vector3 ptrB, |
39 | IDebugDraw debugDraw//, StackAlloc stackAlloc | 39 | IDebugDraw debugDraw//, StackAlloc stackAlloc |
40 | ); | 40 | ); |
41 | } | 41 | } |
42 | } | 42 | } |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ISimplexSolver.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ISimplexSolver.cs index 71b1eaa..f1b1807 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ISimplexSolver.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ISimplexSolver.cs | |||
@@ -1,48 +1,48 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | /// ISimplexSolver can incrementally calculate distance between origin and up to 4 vertices | 29 | /// ISimplexSolver can incrementally calculate distance between origin and up to 4 vertices |
30 | /// Used by GJK or Linear Casting. Can be implemented by the Johnson-algorithm or alternative approaches based on | 30 | /// Used by GJK or Linear Casting. Can be implemented by the Johnson-algorithm or alternative approaches based on |
31 | /// voronoi regions or barycentric coordinates | 31 | /// voronoi regions or barycentric coordinates |
32 | public interface ISimplexSolver | 32 | public interface ISimplexSolver |
33 | { | 33 | { |
34 | void Reset(); | 34 | void Reset(); |
35 | void AddVertex(Vector3 w, Vector3 p, Vector3 q); | 35 | void AddVertex(Vector3 w, Vector3 p, Vector3 q); |
36 | bool Closest(out Vector3 v); | 36 | bool Closest(out Vector3 v); |
37 | 37 | ||
38 | int GetSimplex(out Vector3[] pBuf, out Vector3[] qBuf, out Vector3[] yBuf); | 38 | int GetSimplex(out Vector3[] pBuf, out Vector3[] qBuf, out Vector3[] yBuf); |
39 | bool InSimplex(Vector3 w); | 39 | bool InSimplex(Vector3 w); |
40 | void BackupClosest(out Vector3 v); | 40 | void BackupClosest(out Vector3 v); |
41 | void ComputePoints(out Vector3 pA, out Vector3 pB); | 41 | void ComputePoints(out Vector3 pA, out Vector3 pB); |
42 | 42 | ||
43 | int NumVertices { get;} | 43 | int NumVertices { get;} |
44 | bool EmptySimplex { get;} | 44 | bool EmptySimplex { get;} |
45 | float MaxVertex { get;} | 45 | float MaxVertex { get;} |
46 | bool FullSimplex { get;} | 46 | bool FullSimplex { get;} |
47 | } | 47 | } |
48 | } \ No newline at end of file | 48 | } \ No newline at end of file |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ManifoldPoint.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ManifoldPoint.cs index 751a9df..f5bcedc 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ManifoldPoint.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/ManifoldPoint.cs | |||
@@ -1,78 +1,78 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | public class ManifoldPoint | 29 | public class ManifoldPoint |
30 | { | 30 | { |
31 | private Vector3 _localPointA; | 31 | private Vector3 _localPointA; |
32 | private Vector3 _localPointB; | 32 | private Vector3 _localPointB; |
33 | private Vector3 _positionWorldOnB; | 33 | private Vector3 _positionWorldOnB; |
34 | private Vector3 _positionWorldOnA; | 34 | private Vector3 _positionWorldOnA; |
35 | private Vector3 _normalWorldOnB; | 35 | private Vector3 _normalWorldOnB; |
36 | 36 | ||
37 | private float _distance; | 37 | private float _distance; |
38 | private float _combinedFriction; | 38 | private float _combinedFriction; |
39 | private float _combinedRestitution; | 39 | private float _combinedRestitution; |
40 | 40 | ||
41 | private object _userPersistentData; | 41 | private object _userPersistentData; |
42 | 42 | ||
43 | private int _lifeTime;//lifetime of the contactpoint in frames | 43 | private int _lifeTime;//lifetime of the contactpoint in frames |
44 | 44 | ||
45 | public ManifoldPoint() | 45 | public ManifoldPoint() |
46 | : this(new Vector3(), new Vector3(), new Vector3(), 0f) | 46 | : this(new Vector3(), new Vector3(), new Vector3(), 0f) |
47 | { | 47 | { |
48 | } | 48 | } |
49 | 49 | ||
50 | public ManifoldPoint(Vector3 pointA, Vector3 pointB, | 50 | public ManifoldPoint(Vector3 pointA, Vector3 pointB, |
51 | Vector3 normal, | 51 | Vector3 normal, |
52 | float distance) | 52 | float distance) |
53 | { | 53 | { |
54 | _localPointA = pointA; | 54 | _localPointA = pointA; |
55 | _localPointB = pointB; | 55 | _localPointB = pointB; |
56 | _normalWorldOnB = normal; | 56 | _normalWorldOnB = normal; |
57 | _distance = distance; | 57 | _distance = distance; |
58 | _positionWorldOnA = new Vector3(); | 58 | _positionWorldOnA = new Vector3(); |
59 | _positionWorldOnB = new Vector3(); | 59 | _positionWorldOnB = new Vector3(); |
60 | } | 60 | } |
61 | 61 | ||
62 | public float Distance { get { return _distance; } set { _distance = value; } } | 62 | public float Distance { get { return _distance; } set { _distance = value; } } |
63 | public int LifeTime { get { return _lifeTime; } set { _lifeTime = value; } } | 63 | public int LifeTime { get { return _lifeTime; } set { _lifeTime = value; } } |
64 | 64 | ||
65 | public Vector3 PositionWorldOnA { get { return _positionWorldOnA; } set { _positionWorldOnA = value; } } | 65 | public Vector3 PositionWorldOnA { get { return _positionWorldOnA; } set { _positionWorldOnA = value; } } |
66 | public Vector3 PositionWorldOnB { get { return _positionWorldOnB; } set { _positionWorldOnB = value; } } | 66 | public Vector3 PositionWorldOnB { get { return _positionWorldOnB; } set { _positionWorldOnB = value; } } |
67 | 67 | ||
68 | public Vector3 LocalPointA { get { return _localPointA; } set { _localPointA = value; } } | 68 | public Vector3 LocalPointA { get { return _localPointA; } set { _localPointA = value; } } |
69 | public Vector3 LocalPointB { get { return _localPointB; } set { _localPointB = value; } } | 69 | public Vector3 LocalPointB { get { return _localPointB; } set { _localPointB = value; } } |
70 | 70 | ||
71 | public Vector3 NormalWorldOnB { get { return _normalWorldOnB; } } | 71 | public Vector3 NormalWorldOnB { get { return _normalWorldOnB; } } |
72 | 72 | ||
73 | public float CombinedFriction { get { return _combinedFriction; } set { _combinedFriction = value; } } | 73 | public float CombinedFriction { get { return _combinedFriction; } set { _combinedFriction = value; } } |
74 | public float CombinedRestitution { get { return _combinedRestitution; } set { _combinedRestitution = value; } } | 74 | public float CombinedRestitution { get { return _combinedRestitution; } set { _combinedRestitution = value; } } |
75 | 75 | ||
76 | public object UserPersistentData { get { return _userPersistentData; } set { _userPersistentData = value; } } | 76 | public object UserPersistentData { get { return _userPersistentData; } set { _userPersistentData = value; } } |
77 | } | 77 | } |
78 | } | 78 | } |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/MinkowskiPenetrationDepthSolver.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/MinkowskiPenetrationDepthSolver.cs index 81b05b8..7363e28 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/MinkowskiPenetrationDepthSolver.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/MinkowskiPenetrationDepthSolver.cs | |||
@@ -1,246 +1,246 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | /// <summary> | 29 | /// <summary> |
30 | /// MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation. | 30 | /// MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation. |
31 | /// Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points. | 31 | /// Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points. |
32 | /// </summary> | 32 | /// </summary> |
33 | public class MinkowskiPenetrationDepthSolver : IConvexPenetrationDepthSolver | 33 | public class MinkowskiPenetrationDepthSolver : IConvexPenetrationDepthSolver |
34 | { | 34 | { |
35 | private const int UnitSpherePointsCount = 42; | 35 | private const int UnitSpherePointsCount = 42; |
36 | 36 | ||
37 | private static Vector3[] penetrationDirections = | 37 | private static Vector3[] penetrationDirections = |
38 | { | 38 | { |
39 | new Vector3(0.000000f , -0.000000f,-1.000000f), | 39 | new Vector3(0.000000f , -0.000000f,-1.000000f), |
40 | new Vector3(0.723608f , -0.525725f,-0.447219f), | 40 | new Vector3(0.723608f , -0.525725f,-0.447219f), |
41 | new Vector3(-0.276388f , -0.850649f,-0.447219f), | 41 | new Vector3(-0.276388f , -0.850649f,-0.447219f), |
42 | new Vector3(-0.894426f , -0.000000f,-0.447216f), | 42 | new Vector3(-0.894426f , -0.000000f,-0.447216f), |
43 | new Vector3(-0.276388f , 0.850649f,-0.447220f), | 43 | new Vector3(-0.276388f , 0.850649f,-0.447220f), |
44 | new Vector3(0.723608f , 0.525725f,-0.447219f), | 44 | new Vector3(0.723608f , 0.525725f,-0.447219f), |
45 | new Vector3(0.276388f , -0.850649f,0.447220f), | 45 | new Vector3(0.276388f , -0.850649f,0.447220f), |
46 | new Vector3(-0.723608f , -0.525725f,0.447219f), | 46 | new Vector3(-0.723608f , -0.525725f,0.447219f), |
47 | new Vector3(-0.723608f , 0.525725f,0.447219f), | 47 | new Vector3(-0.723608f , 0.525725f,0.447219f), |
48 | new Vector3(0.276388f , 0.850649f,0.447219f), | 48 | new Vector3(0.276388f , 0.850649f,0.447219f), |
49 | new Vector3(0.894426f , 0.000000f,0.447216f), | 49 | new Vector3(0.894426f , 0.000000f,0.447216f), |
50 | new Vector3(-0.000000f , 0.000000f,1.000000f), | 50 | new Vector3(-0.000000f , 0.000000f,1.000000f), |
51 | new Vector3(0.425323f , -0.309011f,-0.850654f), | 51 | new Vector3(0.425323f , -0.309011f,-0.850654f), |
52 | new Vector3(-0.162456f , -0.499995f,-0.850654f), | 52 | new Vector3(-0.162456f , -0.499995f,-0.850654f), |
53 | new Vector3(0.262869f , -0.809012f,-0.525738f), | 53 | new Vector3(0.262869f , -0.809012f,-0.525738f), |
54 | new Vector3(0.425323f , 0.309011f,-0.850654f), | 54 | new Vector3(0.425323f , 0.309011f,-0.850654f), |
55 | new Vector3(0.850648f , -0.000000f,-0.525736f), | 55 | new Vector3(0.850648f , -0.000000f,-0.525736f), |
56 | new Vector3(-0.525730f , -0.000000f,-0.850652f), | 56 | new Vector3(-0.525730f , -0.000000f,-0.850652f), |
57 | new Vector3(-0.688190f , -0.499997f,-0.525736f), | 57 | new Vector3(-0.688190f , -0.499997f,-0.525736f), |
58 | new Vector3(-0.162456f , 0.499995f,-0.850654f), | 58 | new Vector3(-0.162456f , 0.499995f,-0.850654f), |
59 | new Vector3(-0.688190f , 0.499997f,-0.525736f), | 59 | new Vector3(-0.688190f , 0.499997f,-0.525736f), |
60 | new Vector3(0.262869f , 0.809012f,-0.525738f), | 60 | new Vector3(0.262869f , 0.809012f,-0.525738f), |
61 | new Vector3(0.951058f , 0.309013f,0.000000f), | 61 | new Vector3(0.951058f , 0.309013f,0.000000f), |
62 | new Vector3(0.951058f , -0.309013f,0.000000f), | 62 | new Vector3(0.951058f , -0.309013f,0.000000f), |
63 | new Vector3(0.587786f , -0.809017f,0.000000f), | 63 | new Vector3(0.587786f , -0.809017f,0.000000f), |
64 | new Vector3(0.000000f , -1.000000f,0.000000f), | 64 | new Vector3(0.000000f , -1.000000f,0.000000f), |
65 | new Vector3(-0.587786f , -0.809017f,0.000000f), | 65 | new Vector3(-0.587786f , -0.809017f,0.000000f), |
66 | new Vector3(-0.951058f , -0.309013f,-0.000000f), | 66 | new Vector3(-0.951058f , -0.309013f,-0.000000f), |
67 | new Vector3(-0.951058f , 0.309013f,-0.000000f), | 67 | new Vector3(-0.951058f , 0.309013f,-0.000000f), |
68 | new Vector3(-0.587786f , 0.809017f,-0.000000f), | 68 | new Vector3(-0.587786f , 0.809017f,-0.000000f), |
69 | new Vector3(-0.000000f , 1.000000f,-0.000000f), | 69 | new Vector3(-0.000000f , 1.000000f,-0.000000f), |
70 | new Vector3(0.587786f , 0.809017f,-0.000000f), | 70 | new Vector3(0.587786f , 0.809017f,-0.000000f), |
71 | new Vector3(0.688190f , -0.499997f,0.525736f), | 71 | new Vector3(0.688190f , -0.499997f,0.525736f), |
72 | new Vector3(-0.262869f , -0.809012f,0.525738f), | 72 | new Vector3(-0.262869f , -0.809012f,0.525738f), |
73 | new Vector3(-0.850648f , 0.000000f,0.525736f), | 73 | new Vector3(-0.850648f , 0.000000f,0.525736f), |
74 | new Vector3(-0.262869f , 0.809012f,0.525738f), | 74 | new Vector3(-0.262869f , 0.809012f,0.525738f), |
75 | new Vector3(0.688190f , 0.499997f,0.525736f), | 75 | new Vector3(0.688190f , 0.499997f,0.525736f), |
76 | new Vector3(0.525730f , 0.000000f,0.850652f), | 76 | new Vector3(0.525730f , 0.000000f,0.850652f), |
77 | new Vector3(0.162456f , -0.499995f,0.850654f), | 77 | new Vector3(0.162456f , -0.499995f,0.850654f), |
78 | new Vector3(-0.425323f , -0.309011f,0.850654f), | 78 | new Vector3(-0.425323f , -0.309011f,0.850654f), |
79 | new Vector3(-0.425323f , 0.309011f,0.850654f), | 79 | new Vector3(-0.425323f , 0.309011f,0.850654f), |
80 | new Vector3(0.162456f , 0.499995f,0.850654f) | 80 | new Vector3(0.162456f , 0.499995f,0.850654f) |
81 | }; | 81 | }; |
82 | 82 | ||
83 | private class IntermediateResult : DiscreteCollisionDetectorInterface.Result | 83 | private class IntermediateResult : DiscreteCollisionDetectorInterface.Result |
84 | { | 84 | { |
85 | private Vector3 _normalOnBInWorld; | 85 | private Vector3 _normalOnBInWorld; |
86 | private Vector3 _pointInWorld; | 86 | private Vector3 _pointInWorld; |
87 | private float _depth; | 87 | private float _depth; |
88 | private bool _hasResult; | 88 | private bool _hasResult; |
89 | 89 | ||
90 | public IntermediateResult() | 90 | public IntermediateResult() |
91 | { | 91 | { |
92 | _hasResult = false; | 92 | _hasResult = false; |
93 | } | 93 | } |
94 | 94 | ||
95 | public bool HasResult { get { return _hasResult; } } | 95 | public bool HasResult { get { return _hasResult; } } |
96 | public float Depth { get { return _depth; } } | 96 | public float Depth { get { return _depth; } } |
97 | public Vector3 PointInWorld { get { return _pointInWorld; } } | 97 | public Vector3 PointInWorld { get { return _pointInWorld; } } |
98 | 98 | ||
99 | public override void SetShapeIdentifiers(int partId0, int index0, int partId1, int index1) | 99 | public override void SetShapeIdentifiers(int partId0, int index0, int partId1, int index1) |
100 | { | 100 | { |
101 | } | 101 | } |
102 | 102 | ||
103 | public override void AddContactPoint(Vector3 normalOnBInWorld, Vector3 pointInWorld, float depth) | 103 | public override void AddContactPoint(Vector3 normalOnBInWorld, Vector3 pointInWorld, float depth) |
104 | { | 104 | { |
105 | _normalOnBInWorld = normalOnBInWorld; | 105 | _normalOnBInWorld = normalOnBInWorld; |
106 | _pointInWorld = pointInWorld; | 106 | _pointInWorld = pointInWorld; |
107 | _depth = depth; | 107 | _depth = depth; |
108 | _hasResult = true; | 108 | _hasResult = true; |
109 | } | 109 | } |
110 | } | 110 | } |
111 | 111 | ||
112 | #region IConvexPenetrationDepthSolver Members | 112 | #region IConvexPenetrationDepthSolver Members |
113 | public bool CalculatePenetrationDepth(ISimplexSolver simplexSolver, | 113 | public bool CalculatePenetrationDepth(ISimplexSolver simplexSolver, |
114 | ConvexShape convexA, ConvexShape convexB, | 114 | ConvexShape convexA, ConvexShape convexB, |
115 | Matrix transformA, Matrix transformB, | 115 | Matrix transformA, Matrix transformB, |
116 | Vector3 v, out Vector3 pa, out Vector3 pb, IDebugDraw debugDraw) | 116 | Vector3 v, out Vector3 pa, out Vector3 pb, IDebugDraw debugDraw) |
117 | { | 117 | { |
118 | pa = new Vector3(); | 118 | pa = new Vector3(); |
119 | pb = new Vector3(); | 119 | pb = new Vector3(); |
120 | //just take fixed number of orientation, and sample the penetration depth in that direction | 120 | //just take fixed number of orientation, and sample the penetration depth in that direction |
121 | float minProj = 1e30f; | 121 | float minProj = 1e30f; |
122 | Vector3 minNorm = new Vector3(); | 122 | Vector3 minNorm = new Vector3(); |
123 | Vector3 minA = new Vector3(), minB = new Vector3(); | 123 | Vector3 minA = new Vector3(), minB = new Vector3(); |
124 | Vector3 seperatingAxisInA, seperatingAxisInB; | 124 | Vector3 seperatingAxisInA, seperatingAxisInB; |
125 | Vector3 pInA, qInB, pWorld, qWorld, w; | 125 | Vector3 pInA, qInB, pWorld, qWorld, w; |
126 | 126 | ||
127 | Vector3[] supportVerticesABatch = new Vector3[UnitSpherePointsCount + ConvexShape.MaxPreferredPenetrationDirections * 2]; | 127 | Vector3[] supportVerticesABatch = new Vector3[UnitSpherePointsCount + ConvexShape.MaxPreferredPenetrationDirections * 2]; |
128 | Vector3[] supportVerticesBBatch = new Vector3[UnitSpherePointsCount + ConvexShape.MaxPreferredPenetrationDirections * 2]; | 128 | Vector3[] supportVerticesBBatch = new Vector3[UnitSpherePointsCount + ConvexShape.MaxPreferredPenetrationDirections * 2]; |
129 | Vector3[] seperatingAxisInABatch = new Vector3[UnitSpherePointsCount + ConvexShape.MaxPreferredPenetrationDirections * 2]; | 129 | Vector3[] seperatingAxisInABatch = new Vector3[UnitSpherePointsCount + ConvexShape.MaxPreferredPenetrationDirections * 2]; |
130 | Vector3[] seperatingAxisInBBatch = new Vector3[UnitSpherePointsCount + ConvexShape.MaxPreferredPenetrationDirections * 2]; | 130 | Vector3[] seperatingAxisInBBatch = new Vector3[UnitSpherePointsCount + ConvexShape.MaxPreferredPenetrationDirections * 2]; |
131 | 131 | ||
132 | int numSampleDirections = UnitSpherePointsCount; | 132 | int numSampleDirections = UnitSpherePointsCount; |
133 | 133 | ||
134 | for (int i = 0; i < numSampleDirections; i++) | 134 | for (int i = 0; i < numSampleDirections; i++) |
135 | { | 135 | { |
136 | Vector3 norm = penetrationDirections[i]; | 136 | Vector3 norm = penetrationDirections[i]; |
137 | seperatingAxisInABatch[i] = Vector3.TransformNormal((-norm), transformA); | 137 | seperatingAxisInABatch[i] = Vector3.TransformNormal((-norm), transformA); |
138 | seperatingAxisInBBatch[i] = Vector3.TransformNormal(norm, transformB); | 138 | seperatingAxisInBBatch[i] = Vector3.TransformNormal(norm, transformB); |
139 | } | 139 | } |
140 | 140 | ||
141 | { | 141 | { |
142 | int numPDA = convexA.PreferredPenetrationDirectionsCount; | 142 | int numPDA = convexA.PreferredPenetrationDirectionsCount; |
143 | if (numPDA != 0) | 143 | if (numPDA != 0) |
144 | { | 144 | { |
145 | for (int i = 0; i < numPDA; i++) | 145 | for (int i = 0; i < numPDA; i++) |
146 | { | 146 | { |
147 | Vector3 norm; | 147 | Vector3 norm; |
148 | convexA.GetPreferredPenetrationDirection(i, out norm); | 148 | convexA.GetPreferredPenetrationDirection(i, out norm); |
149 | norm = Vector3.TransformNormal(norm, transformA); | 149 | norm = Vector3.TransformNormal(norm, transformA); |
150 | penetrationDirections[numSampleDirections] = norm; | 150 | penetrationDirections[numSampleDirections] = norm; |
151 | seperatingAxisInABatch[numSampleDirections] = Vector3.TransformNormal((-norm), transformA); | 151 | seperatingAxisInABatch[numSampleDirections] = Vector3.TransformNormal((-norm), transformA); |
152 | seperatingAxisInBBatch[numSampleDirections] = Vector3.TransformNormal(norm, transformB); | 152 | seperatingAxisInBBatch[numSampleDirections] = Vector3.TransformNormal(norm, transformB); |
153 | numSampleDirections++; | 153 | numSampleDirections++; |
154 | } | 154 | } |
155 | } | 155 | } |
156 | } | 156 | } |
157 | 157 | ||
158 | { | 158 | { |
159 | int numPDB = convexB.PreferredPenetrationDirectionsCount; | 159 | int numPDB = convexB.PreferredPenetrationDirectionsCount; |
160 | if (numPDB != 0) | 160 | if (numPDB != 0) |
161 | { | 161 | { |
162 | for (int i = 0; i < numPDB; i++) | 162 | for (int i = 0; i < numPDB; i++) |
163 | { | 163 | { |
164 | Vector3 norm; | 164 | Vector3 norm; |
165 | convexB.GetPreferredPenetrationDirection(i, out norm); | 165 | convexB.GetPreferredPenetrationDirection(i, out norm); |
166 | norm = Vector3.TransformNormal(norm, transformB); | 166 | norm = Vector3.TransformNormal(norm, transformB); |
167 | penetrationDirections[numSampleDirections] = norm; | 167 | penetrationDirections[numSampleDirections] = norm; |
168 | seperatingAxisInABatch[numSampleDirections] = Vector3.TransformNormal((-norm), transformA); | 168 | seperatingAxisInABatch[numSampleDirections] = Vector3.TransformNormal((-norm), transformA); |
169 | seperatingAxisInBBatch[numSampleDirections] = Vector3.TransformNormal(norm, transformB); | 169 | seperatingAxisInBBatch[numSampleDirections] = Vector3.TransformNormal(norm, transformB); |
170 | numSampleDirections++; | 170 | numSampleDirections++; |
171 | } | 171 | } |
172 | } | 172 | } |
173 | } | 173 | } |
174 | 174 | ||
175 | convexA.BatchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch, supportVerticesABatch); //, numSampleDirections); | 175 | convexA.BatchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch, supportVerticesABatch); //, numSampleDirections); |
176 | convexB.BatchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch, supportVerticesBBatch); //, numSampleDirections); | 176 | convexB.BatchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch, supportVerticesBBatch); //, numSampleDirections); |
177 | 177 | ||
178 | for (int i = 0; i < numSampleDirections; i++) | 178 | for (int i = 0; i < numSampleDirections; i++) |
179 | { | 179 | { |
180 | Vector3 norm = penetrationDirections[i]; | 180 | Vector3 norm = penetrationDirections[i]; |
181 | seperatingAxisInA = seperatingAxisInABatch[i]; | 181 | seperatingAxisInA = seperatingAxisInABatch[i]; |
182 | seperatingAxisInB = seperatingAxisInBBatch[i]; | 182 | seperatingAxisInB = seperatingAxisInBBatch[i]; |
183 | 183 | ||
184 | pInA = supportVerticesABatch[i]; | 184 | pInA = supportVerticesABatch[i]; |
185 | qInB = supportVerticesBBatch[i]; | 185 | qInB = supportVerticesBBatch[i]; |
186 | 186 | ||
187 | pWorld = MathHelper.MatrixToVector(transformA, pInA); | 187 | pWorld = MathHelper.MatrixToVector(transformA, pInA); |
188 | qWorld = MathHelper.MatrixToVector(transformB, qInB); | 188 | qWorld = MathHelper.MatrixToVector(transformB, qInB); |
189 | w = qWorld - pWorld; | 189 | w = qWorld - pWorld; |
190 | float delta = Vector3.Dot(norm, w); | 190 | float delta = Vector3.Dot(norm, w); |
191 | //find smallest delta | 191 | //find smallest delta |
192 | if (delta < minProj) | 192 | if (delta < minProj) |
193 | { | 193 | { |
194 | minProj = delta; | 194 | minProj = delta; |
195 | minNorm = norm; | 195 | minNorm = norm; |
196 | minA = pWorld; | 196 | minA = pWorld; |
197 | minB = qWorld; | 197 | minB = qWorld; |
198 | } | 198 | } |
199 | } | 199 | } |
200 | 200 | ||
201 | //add the margins | 201 | //add the margins |
202 | minA += minNorm * convexA.Margin; | 202 | minA += minNorm * convexA.Margin; |
203 | minB -= minNorm * convexB.Margin; | 203 | minB -= minNorm * convexB.Margin; |
204 | //no penetration | 204 | //no penetration |
205 | if (minProj < 0) | 205 | if (minProj < 0) |
206 | return false; | 206 | return false; |
207 | 207 | ||
208 | minProj += (convexA.Margin + convexB.Margin); | 208 | minProj += (convexA.Margin + convexB.Margin); |
209 | 209 | ||
210 | GjkPairDetector gjkdet = new GjkPairDetector(convexA, convexB, simplexSolver, null); | 210 | GjkPairDetector gjkdet = new GjkPairDetector(convexA, convexB, simplexSolver, null); |
211 | 211 | ||
212 | float offsetDist = minProj; | 212 | float offsetDist = minProj; |
213 | Vector3 offset = minNorm * offsetDist; | 213 | Vector3 offset = minNorm * offsetDist; |
214 | 214 | ||
215 | GjkPairDetector.ClosestPointInput input = new DiscreteCollisionDetectorInterface.ClosestPointInput(); | 215 | GjkPairDetector.ClosestPointInput input = new DiscreteCollisionDetectorInterface.ClosestPointInput(); |
216 | 216 | ||
217 | Vector3 newOrg = transformA.Translation + offset; | 217 | Vector3 newOrg = transformA.Translation + offset; |
218 | 218 | ||
219 | Matrix displacedTrans = transformA; | 219 | Matrix displacedTrans = transformA; |
220 | displacedTrans.Translation = newOrg; | 220 | displacedTrans.Translation = newOrg; |
221 | 221 | ||
222 | input.TransformA = displacedTrans; | 222 | input.TransformA = displacedTrans; |
223 | input.TransformB = transformB; | 223 | input.TransformB = transformB; |
224 | input.MaximumDistanceSquared = 1e30f;//minProj; | 224 | input.MaximumDistanceSquared = 1e30f;//minProj; |
225 | 225 | ||
226 | IntermediateResult res = new IntermediateResult(); | 226 | IntermediateResult res = new IntermediateResult(); |
227 | gjkdet.GetClosestPoints(input, res, debugDraw); | 227 | gjkdet.GetClosestPoints(input, res, debugDraw); |
228 | 228 | ||
229 | float correctedMinNorm = minProj - res.Depth; | 229 | float correctedMinNorm = minProj - res.Depth; |
230 | 230 | ||
231 | //the penetration depth is over-estimated, relax it | 231 | //the penetration depth is over-estimated, relax it |
232 | float penetration_relaxation = 1; | 232 | float penetration_relaxation = 1; |
233 | minNorm *= penetration_relaxation; | 233 | minNorm *= penetration_relaxation; |
234 | 234 | ||
235 | if (res.HasResult) | 235 | if (res.HasResult) |
236 | { | 236 | { |
237 | 237 | ||
238 | pa = res.PointInWorld - minNorm * correctedMinNorm; | 238 | pa = res.PointInWorld - minNorm * correctedMinNorm; |
239 | pb = res.PointInWorld; | 239 | pb = res.PointInWorld; |
240 | } | 240 | } |
241 | 241 | ||
242 | return res.HasResult; | 242 | return res.HasResult; |
243 | } | 243 | } |
244 | #endregion | 244 | #endregion |
245 | } | 245 | } |
246 | } | 246 | } |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/PersistentManifold.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/PersistentManifold.cs index 47cfe9a..04a533d 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/PersistentManifold.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/PersistentManifold.cs | |||
@@ -1,272 +1,272 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | public delegate bool ContactDestroyedCallback(object userPersistentData); | 29 | public delegate bool ContactDestroyedCallback(object userPersistentData); |
30 | 30 | ||
31 | public class PersistentManifold | 31 | public class PersistentManifold |
32 | { | 32 | { |
33 | private static ContactDestroyedCallback _contactDestroyedCallback = null; | 33 | private static ContactDestroyedCallback _contactDestroyedCallback = null; |
34 | private static float _contactBreakingThreshold = 0.02f; | 34 | private static float _contactBreakingThreshold = 0.02f; |
35 | 35 | ||
36 | private ManifoldPoint[] _pointCache = new ManifoldPoint[4]; | 36 | private ManifoldPoint[] _pointCache = new ManifoldPoint[4]; |
37 | 37 | ||
38 | // this two body pointers can point to the physics rigidbody class. | 38 | // this two body pointers can point to the physics rigidbody class. |
39 | // object will allow any rigidbody class | 39 | // object will allow any rigidbody class |
40 | private object _bodyA; | 40 | private object _bodyA; |
41 | private object _bodyB; | 41 | private object _bodyB; |
42 | private int _cachedPoints; | 42 | private int _cachedPoints; |
43 | 43 | ||
44 | public PersistentManifold(object bodyA, object bodyB) | 44 | public PersistentManifold(object bodyA, object bodyB) |
45 | { | 45 | { |
46 | _bodyA = bodyA; | 46 | _bodyA = bodyA; |
47 | _bodyB = bodyB; | 47 | _bodyB = bodyB; |
48 | _cachedPoints = 0; | 48 | _cachedPoints = 0; |
49 | } | 49 | } |
50 | 50 | ||
51 | public object BodyA { get { return _bodyA; } } | 51 | public object BodyA { get { return _bodyA; } } |
52 | public object BodyB { get { return _bodyB; } } | 52 | public object BodyB { get { return _bodyB; } } |
53 | 53 | ||
54 | public int ContactsCount { get { return _cachedPoints; } } | 54 | public int ContactsCount { get { return _cachedPoints; } } |
55 | 55 | ||
56 | public static ContactDestroyedCallback ContactDestroyedCallback { get { return _contactDestroyedCallback; } set { _contactDestroyedCallback = value; } } | 56 | public static ContactDestroyedCallback ContactDestroyedCallback { get { return _contactDestroyedCallback; } set { _contactDestroyedCallback = value; } } |
57 | public static float ContactBreakingThreshold { get { return _contactBreakingThreshold; } } | 57 | public static float ContactBreakingThreshold { get { return _contactBreakingThreshold; } } |
58 | 58 | ||
59 | public void SetBodies(object bodyA, object bodyB) | 59 | public void SetBodies(object bodyA, object bodyB) |
60 | { | 60 | { |
61 | _bodyA = bodyA; | 61 | _bodyA = bodyA; |
62 | _bodyB = bodyB; | 62 | _bodyB = bodyB; |
63 | } | 63 | } |
64 | 64 | ||
65 | public ManifoldPoint GetContactPoint(int index) | 65 | public ManifoldPoint GetContactPoint(int index) |
66 | { | 66 | { |
67 | if (index >= _cachedPoints) | 67 | if (index >= _cachedPoints) |
68 | throw new ArgumentOutOfRangeException("index", "index must be smaller than cachedPoints"); | 68 | throw new ArgumentOutOfRangeException("index", "index must be smaller than cachedPoints"); |
69 | 69 | ||
70 | return _pointCache[index]; | 70 | return _pointCache[index]; |
71 | } | 71 | } |
72 | 72 | ||
73 | public int GetCacheEntry(ManifoldPoint newPoint) | 73 | public int GetCacheEntry(ManifoldPoint newPoint) |
74 | { | 74 | { |
75 | float shortestDist = ContactBreakingThreshold * ContactBreakingThreshold; | 75 | float shortestDist = ContactBreakingThreshold * ContactBreakingThreshold; |
76 | int size = ContactsCount; | 76 | int size = ContactsCount; |
77 | int nearestPoint = -1; | 77 | int nearestPoint = -1; |
78 | for (int i = 0; i < size; i++) | 78 | for (int i = 0; i < size; i++) |
79 | { | 79 | { |
80 | ManifoldPoint mp = _pointCache[i]; | 80 | ManifoldPoint mp = _pointCache[i]; |
81 | 81 | ||
82 | Vector3 diffA = mp.LocalPointA - newPoint.LocalPointA; | 82 | Vector3 diffA = mp.LocalPointA - newPoint.LocalPointA; |
83 | float distToManiPoint = Vector3.Dot(diffA, diffA); | 83 | float distToManiPoint = Vector3.Dot(diffA, diffA); |
84 | if (distToManiPoint < shortestDist) | 84 | if (distToManiPoint < shortestDist) |
85 | { | 85 | { |
86 | shortestDist = distToManiPoint; | 86 | shortestDist = distToManiPoint; |
87 | nearestPoint = i; | 87 | nearestPoint = i; |
88 | } | 88 | } |
89 | } | 89 | } |
90 | return nearestPoint; | 90 | return nearestPoint; |
91 | } | 91 | } |
92 | 92 | ||
93 | public void AddManifoldPoint(ManifoldPoint newPoint) | 93 | public void AddManifoldPoint(ManifoldPoint newPoint) |
94 | { | 94 | { |
95 | if (!ValidContactDistance(newPoint)) | 95 | if (!ValidContactDistance(newPoint)) |
96 | throw new BulletException(); | 96 | throw new BulletException(); |
97 | 97 | ||
98 | int insertIndex = ContactsCount; | 98 | int insertIndex = ContactsCount; |
99 | if (insertIndex == 4) | 99 | if (insertIndex == 4) |
100 | { | 100 | { |
101 | //sort cache so best points come first, based on area | 101 | //sort cache so best points come first, based on area |
102 | insertIndex = SortCachedPoints(newPoint); | 102 | insertIndex = SortCachedPoints(newPoint); |
103 | } | 103 | } |
104 | else | 104 | else |
105 | { | 105 | { |
106 | _cachedPoints++; | 106 | _cachedPoints++; |
107 | } | 107 | } |
108 | ReplaceContactPoint(newPoint, insertIndex); | 108 | ReplaceContactPoint(newPoint, insertIndex); |
109 | } | 109 | } |
110 | 110 | ||
111 | public void RemoveContactPoint(int index) | 111 | public void RemoveContactPoint(int index) |
112 | { | 112 | { |
113 | ClearUserCache(_pointCache[index]); | 113 | ClearUserCache(_pointCache[index]); |
114 | 114 | ||
115 | int lastUsedIndex = ContactsCount - 1; | 115 | int lastUsedIndex = ContactsCount - 1; |
116 | _pointCache[index] = _pointCache[lastUsedIndex]; | 116 | _pointCache[index] = _pointCache[lastUsedIndex]; |
117 | //get rid of duplicated userPersistentData pointer | 117 | //get rid of duplicated userPersistentData pointer |
118 | _pointCache[lastUsedIndex].UserPersistentData = null; | 118 | _pointCache[lastUsedIndex].UserPersistentData = null; |
119 | _cachedPoints--; | 119 | _cachedPoints--; |
120 | } | 120 | } |
121 | 121 | ||
122 | public void ReplaceContactPoint(ManifoldPoint newPoint, int insertIndex) | 122 | public void ReplaceContactPoint(ManifoldPoint newPoint, int insertIndex) |
123 | { | 123 | { |
124 | BulletDebug.Assert(ValidContactDistance(newPoint)); | 124 | BulletDebug.Assert(ValidContactDistance(newPoint)); |
125 | 125 | ||
126 | if (_pointCache[insertIndex] != null) | 126 | if (_pointCache[insertIndex] != null) |
127 | { | 127 | { |
128 | int lifeTime = _pointCache[insertIndex].LifeTime; | 128 | int lifeTime = _pointCache[insertIndex].LifeTime; |
129 | BulletDebug.Assert(lifeTime >= 0); | 129 | BulletDebug.Assert(lifeTime >= 0); |
130 | object cache = _pointCache[insertIndex].UserPersistentData; | 130 | object cache = _pointCache[insertIndex].UserPersistentData; |
131 | 131 | ||
132 | _pointCache[insertIndex] = newPoint; | 132 | _pointCache[insertIndex] = newPoint; |
133 | 133 | ||
134 | _pointCache[insertIndex].UserPersistentData = cache; | 134 | _pointCache[insertIndex].UserPersistentData = cache; |
135 | _pointCache[insertIndex].LifeTime = lifeTime; | 135 | _pointCache[insertIndex].LifeTime = lifeTime; |
136 | } | 136 | } |
137 | else | 137 | else |
138 | { | 138 | { |
139 | _pointCache[insertIndex] = newPoint; | 139 | _pointCache[insertIndex] = newPoint; |
140 | } | 140 | } |
141 | 141 | ||
142 | //ClearUserCache(_pointCache[insertIndex]); | 142 | //ClearUserCache(_pointCache[insertIndex]); |
143 | //_pointCache[insertIndex] = newPoint; | 143 | //_pointCache[insertIndex] = newPoint; |
144 | } | 144 | } |
145 | 145 | ||
146 | public bool ValidContactDistance(ManifoldPoint pt) | 146 | public bool ValidContactDistance(ManifoldPoint pt) |
147 | { | 147 | { |
148 | return pt.Distance <= ContactBreakingThreshold; | 148 | return pt.Distance <= ContactBreakingThreshold; |
149 | } | 149 | } |
150 | 150 | ||
151 | // calculated new worldspace coordinates and depth, and reject points that exceed the collision margin | 151 | // calculated new worldspace coordinates and depth, and reject points that exceed the collision margin |
152 | public void RefreshContactPoints(Matrix trA, Matrix trB) | 152 | public void RefreshContactPoints(Matrix trA, Matrix trB) |
153 | { | 153 | { |
154 | // first refresh worldspace positions and distance | 154 | // first refresh worldspace positions and distance |
155 | for (int i = ContactsCount - 1; i >= 0; i--) | 155 | for (int i = ContactsCount - 1; i >= 0; i--) |
156 | { | 156 | { |
157 | ManifoldPoint manifoldPoint = _pointCache[i]; | 157 | ManifoldPoint manifoldPoint = _pointCache[i]; |
158 | manifoldPoint.PositionWorldOnA = MathHelper.MatrixToVector(trA,manifoldPoint.LocalPointA); | 158 | manifoldPoint.PositionWorldOnA = MathHelper.MatrixToVector(trA,manifoldPoint.LocalPointA); |
159 | manifoldPoint.PositionWorldOnB = MathHelper.MatrixToVector(trB, manifoldPoint.LocalPointB); | 159 | manifoldPoint.PositionWorldOnB = MathHelper.MatrixToVector(trB, manifoldPoint.LocalPointB); |
160 | manifoldPoint.Distance = Vector3.Dot(manifoldPoint.PositionWorldOnA - manifoldPoint.PositionWorldOnB, manifoldPoint.NormalWorldOnB); | 160 | manifoldPoint.Distance = Vector3.Dot(manifoldPoint.PositionWorldOnA - manifoldPoint.PositionWorldOnB, manifoldPoint.NormalWorldOnB); |
161 | manifoldPoint.LifeTime++; | 161 | manifoldPoint.LifeTime++; |
162 | } | 162 | } |
163 | 163 | ||
164 | // then | 164 | // then |
165 | float distance2d; | 165 | float distance2d; |
166 | Vector3 projectedDifference, projectedPoint; | 166 | Vector3 projectedDifference, projectedPoint; |
167 | for (int i = ContactsCount - 1; i >= 0; i--) | 167 | for (int i = ContactsCount - 1; i >= 0; i--) |
168 | { | 168 | { |
169 | 169 | ||
170 | ManifoldPoint manifoldPoint = _pointCache[i]; | 170 | ManifoldPoint manifoldPoint = _pointCache[i]; |
171 | //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction) | 171 | //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction) |
172 | if (!ValidContactDistance(manifoldPoint)) | 172 | if (!ValidContactDistance(manifoldPoint)) |
173 | { | 173 | { |
174 | RemoveContactPoint(i); | 174 | RemoveContactPoint(i); |
175 | } | 175 | } |
176 | else | 176 | else |
177 | { | 177 | { |
178 | //contact also becomes invalid when relative movement orthogonal to normal exceeds margin | 178 | //contact also becomes invalid when relative movement orthogonal to normal exceeds margin |
179 | projectedPoint = manifoldPoint.PositionWorldOnA - manifoldPoint.NormalWorldOnB * manifoldPoint.Distance; | 179 | projectedPoint = manifoldPoint.PositionWorldOnA - manifoldPoint.NormalWorldOnB * manifoldPoint.Distance; |
180 | projectedDifference = manifoldPoint.PositionWorldOnB - projectedPoint; | 180 | projectedDifference = manifoldPoint.PositionWorldOnB - projectedPoint; |
181 | distance2d = Vector3.Dot(projectedDifference, projectedDifference); | 181 | distance2d = Vector3.Dot(projectedDifference, projectedDifference); |
182 | if (distance2d > ContactBreakingThreshold * ContactBreakingThreshold) | 182 | if (distance2d > ContactBreakingThreshold * ContactBreakingThreshold) |
183 | { | 183 | { |
184 | RemoveContactPoint(i); | 184 | RemoveContactPoint(i); |
185 | } | 185 | } |
186 | } | 186 | } |
187 | } | 187 | } |
188 | } | 188 | } |
189 | 189 | ||
190 | public void ClearManifold() | 190 | public void ClearManifold() |
191 | { | 191 | { |
192 | for (int i = 0; i < _cachedPoints; i++) | 192 | for (int i = 0; i < _cachedPoints; i++) |
193 | { | 193 | { |
194 | ClearUserCache(_pointCache[i]); | 194 | ClearUserCache(_pointCache[i]); |
195 | } | 195 | } |
196 | _cachedPoints = 0; | 196 | _cachedPoints = 0; |
197 | } | 197 | } |
198 | 198 | ||
199 | private void ClearUserCache(ManifoldPoint pt) | 199 | private void ClearUserCache(ManifoldPoint pt) |
200 | { | 200 | { |
201 | if (pt != null) | 201 | if (pt != null) |
202 | { | 202 | { |
203 | object oldPtr = pt.UserPersistentData; | 203 | object oldPtr = pt.UserPersistentData; |
204 | 204 | ||
205 | if (oldPtr != null) | 205 | if (oldPtr != null) |
206 | { | 206 | { |
207 | if (pt.UserPersistentData != null && _contactDestroyedCallback != null) | 207 | if (pt.UserPersistentData != null && _contactDestroyedCallback != null) |
208 | { | 208 | { |
209 | _contactDestroyedCallback(pt.UserPersistentData); | 209 | _contactDestroyedCallback(pt.UserPersistentData); |
210 | pt.UserPersistentData = null; | 210 | pt.UserPersistentData = null; |
211 | } | 211 | } |
212 | } | 212 | } |
213 | } | 213 | } |
214 | } | 214 | } |
215 | 215 | ||
216 | // sort cached points so most isolated points come first | 216 | // sort cached points so most isolated points come first |
217 | private int SortCachedPoints(ManifoldPoint pt) | 217 | private int SortCachedPoints(ManifoldPoint pt) |
218 | { | 218 | { |
219 | //calculate 4 possible cases areas, and take biggest area | 219 | //calculate 4 possible cases areas, and take biggest area |
220 | //also need to keep 'deepest' | 220 | //also need to keep 'deepest' |
221 | 221 | ||
222 | int maxPenetrationIndex = -1; | 222 | int maxPenetrationIndex = -1; |
223 | float maxPenetration = pt.Distance; | 223 | float maxPenetration = pt.Distance; |
224 | for (int i = 0; i < 4; i++) | 224 | for (int i = 0; i < 4; i++) |
225 | { | 225 | { |
226 | if (_pointCache[i].Distance < maxPenetration) | 226 | if (_pointCache[i].Distance < maxPenetration) |
227 | { | 227 | { |
228 | maxPenetrationIndex = i; | 228 | maxPenetrationIndex = i; |
229 | maxPenetration = _pointCache[i].Distance; | 229 | maxPenetration = _pointCache[i].Distance; |
230 | } | 230 | } |
231 | } | 231 | } |
232 | 232 | ||
233 | float res0 = 0, res1 = 0, res2 = 0, res3 = 0; | 233 | float res0 = 0, res1 = 0, res2 = 0, res3 = 0; |
234 | if (maxPenetrationIndex != 0) | 234 | if (maxPenetrationIndex != 0) |
235 | { | 235 | { |
236 | Vector3 a0 = pt.LocalPointA - _pointCache[1].LocalPointA; | 236 | Vector3 a0 = pt.LocalPointA - _pointCache[1].LocalPointA; |
237 | Vector3 b0 = _pointCache[3].LocalPointA - _pointCache[2].LocalPointA; | 237 | Vector3 b0 = _pointCache[3].LocalPointA - _pointCache[2].LocalPointA; |
238 | Vector3 cross = Vector3.Cross(a0, b0); | 238 | Vector3 cross = Vector3.Cross(a0, b0); |
239 | res0 = cross.LengthSquared(); | 239 | res0 = cross.LengthSquared(); |
240 | } | 240 | } |
241 | if (maxPenetrationIndex != 1) | 241 | if (maxPenetrationIndex != 1) |
242 | { | 242 | { |
243 | Vector3 a1 = pt.LocalPointA - _pointCache[0].LocalPointA; | 243 | Vector3 a1 = pt.LocalPointA - _pointCache[0].LocalPointA; |
244 | Vector3 b1 = _pointCache[3].LocalPointA - _pointCache[2].LocalPointA; | 244 | Vector3 b1 = _pointCache[3].LocalPointA - _pointCache[2].LocalPointA; |
245 | Vector3 cross = Vector3.Cross(a1, b1); | 245 | Vector3 cross = Vector3.Cross(a1, b1); |
246 | res1 = cross.LengthSquared(); | 246 | res1 = cross.LengthSquared(); |
247 | } | 247 | } |
248 | 248 | ||
249 | if (maxPenetrationIndex != 2) | 249 | if (maxPenetrationIndex != 2) |
250 | { | 250 | { |
251 | Vector3 a2 = pt.LocalPointA - _pointCache[0].LocalPointA; | 251 | Vector3 a2 = pt.LocalPointA - _pointCache[0].LocalPointA; |
252 | Vector3 b2 = _pointCache[3].LocalPointA - _pointCache[1].LocalPointA; | 252 | Vector3 b2 = _pointCache[3].LocalPointA - _pointCache[1].LocalPointA; |
253 | Vector3 cross = Vector3.Cross(a2, b2); | 253 | Vector3 cross = Vector3.Cross(a2, b2); |
254 | res2 = cross.LengthSquared(); | 254 | res2 = cross.LengthSquared(); |
255 | } | 255 | } |
256 | 256 | ||
257 | if (maxPenetrationIndex != 3) | 257 | if (maxPenetrationIndex != 3) |
258 | { | 258 | { |
259 | Vector3 a3 = pt.LocalPointA - _pointCache[0].LocalPointA; | 259 | Vector3 a3 = pt.LocalPointA - _pointCache[0].LocalPointA; |
260 | Vector3 b3 = _pointCache[2].LocalPointA - _pointCache[1].LocalPointA; | 260 | Vector3 b3 = _pointCache[2].LocalPointA - _pointCache[1].LocalPointA; |
261 | Vector3 cross = Vector3.Cross(a3, b3); | 261 | Vector3 cross = Vector3.Cross(a3, b3); |
262 | res3 = cross.LengthSquared(); | 262 | res3 = cross.LengthSquared(); |
263 | } | 263 | } |
264 | 264 | ||
265 | Vector4 maxvec = new Vector4(res0, res1, res2, res3); | 265 | Vector4 maxvec = new Vector4(res0, res1, res2, res3); |
266 | int biggestarea = MathHelper.ClosestAxis(maxvec); | 266 | int biggestarea = MathHelper.ClosestAxis(maxvec); |
267 | return biggestarea; | 267 | return biggestarea; |
268 | } | 268 | } |
269 | 269 | ||
270 | private int FindContactPoint(ManifoldPoint unUsed, int numUnused, ManifoldPoint pt) { return 0; } | 270 | private int FindContactPoint(ManifoldPoint unUsed, int numUnused, ManifoldPoint pt) { return 0; } |
271 | } | 271 | } |
272 | } | 272 | } |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/PointCollector.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/PointCollector.cs index 4e0b0a0..c70741e 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/PointCollector.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/PointCollector.cs | |||
@@ -1,64 +1,64 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | public class PointCollector : DiscreteCollisionDetectorInterface.Result | 29 | public class PointCollector : DiscreteCollisionDetectorInterface.Result |
30 | { | 30 | { |
31 | private Vector3 _normalOnBInWorld; | 31 | private Vector3 _normalOnBInWorld; |
32 | private Vector3 _pointInWorld; | 32 | private Vector3 _pointInWorld; |
33 | private float _distance; //negative means penetration | 33 | private float _distance; //negative means penetration |
34 | private bool _hasResult; | 34 | private bool _hasResult; |
35 | 35 | ||
36 | public PointCollector() | 36 | public PointCollector() |
37 | { | 37 | { |
38 | _distance = 1e30f; | 38 | _distance = 1e30f; |
39 | _hasResult = false; | 39 | _hasResult = false; |
40 | } | 40 | } |
41 | 41 | ||
42 | public Vector3 NormalOnBInWorld { get { return _normalOnBInWorld; } } | 42 | public Vector3 NormalOnBInWorld { get { return _normalOnBInWorld; } } |
43 | public Vector3 PointInWorld { get { return _pointInWorld; } } | 43 | public Vector3 PointInWorld { get { return _pointInWorld; } } |
44 | public float Distance { get { return _distance; } } | 44 | public float Distance { get { return _distance; } } |
45 | public bool HasResult { get { return _hasResult; } } | 45 | public bool HasResult { get { return _hasResult; } } |
46 | 46 | ||
47 | public override void SetShapeIdentifiers(int partIdA, int indexA, int partIdB, int indexB) | 47 | public override void SetShapeIdentifiers(int partIdA, int indexA, int partIdB, int indexB) |
48 | { | 48 | { |
49 | //?? | 49 | //?? |
50 | } | 50 | } |
51 | 51 | ||
52 | public override void AddContactPoint(Vector3 normalOnBInWorld, Vector3 pointInWorld, float depth) | 52 | public override void AddContactPoint(Vector3 normalOnBInWorld, Vector3 pointInWorld, float depth) |
53 | { | 53 | { |
54 | if (depth < _distance) | 54 | if (depth < _distance) |
55 | { | 55 | { |
56 | _hasResult = true; | 56 | _hasResult = true; |
57 | _normalOnBInWorld = normalOnBInWorld; | 57 | _normalOnBInWorld = normalOnBInWorld; |
58 | _pointInWorld = pointInWorld; | 58 | _pointInWorld = pointInWorld; |
59 | //negative means penetration | 59 | //negative means penetration |
60 | _distance = depth; | 60 | _distance = depth; |
61 | } | 61 | } |
62 | } | 62 | } |
63 | } | 63 | } |
64 | } | 64 | } |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/SubsimplexConvexCast.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/SubsimplexConvexCast.cs index 6d320c4..5c92a0c 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/SubsimplexConvexCast.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/SubsimplexConvexCast.cs | |||
@@ -1,142 +1,142 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | /// <summary> | 29 | /// <summary> |
30 | /// SubsimplexConvexCast implements Gino van den Bergens' paper | 30 | /// SubsimplexConvexCast implements Gino van den Bergens' paper |
31 | /// "Ray Casting against bteral Convex Objects with Application to Continuous Collision Detection" | 31 | /// "Ray Casting against bteral Convex Objects with Application to Continuous Collision Detection" |
32 | /// GJK based Ray Cast, optimized version | 32 | /// GJK based Ray Cast, optimized version |
33 | /// Objects should not start in overlap, otherwise results are not defined. | 33 | /// Objects should not start in overlap, otherwise results are not defined. |
34 | /// </summary> | 34 | /// </summary> |
35 | public class SubsimplexConvexCast : IConvexCast | 35 | public class SubsimplexConvexCast : IConvexCast |
36 | { | 36 | { |
37 | private ISimplexSolver _simplexSolver; | 37 | private ISimplexSolver _simplexSolver; |
38 | private ConvexShape _convexA; | 38 | private ConvexShape _convexA; |
39 | private ConvexShape _convexB; | 39 | private ConvexShape _convexB; |
40 | 40 | ||
41 | /// <summary> | 41 | /// <summary> |
42 | /// Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases. | 42 | /// Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases. |
43 | /// See discussion about this here http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=565 | 43 | /// See discussion about this here http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=565 |
44 | /// </summary> | 44 | /// </summary> |
45 | private const int MaxIterations = 32; | 45 | private const int MaxIterations = 32; |
46 | 46 | ||
47 | public SubsimplexConvexCast(ConvexShape shapeA, ConvexShape shapeB, ISimplexSolver simplexSolver) | 47 | public SubsimplexConvexCast(ConvexShape shapeA, ConvexShape shapeB, ISimplexSolver simplexSolver) |
48 | { | 48 | { |
49 | _simplexSolver = simplexSolver; | 49 | _simplexSolver = simplexSolver; |
50 | _convexA = shapeA; | 50 | _convexA = shapeA; |
51 | _convexB = shapeB; | 51 | _convexB = shapeB; |
52 | } | 52 | } |
53 | 53 | ||
54 | #region IConvexCast Members | 54 | #region IConvexCast Members |
55 | /// <summary> | 55 | /// <summary> |
56 | /// SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects. | 56 | /// SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects. |
57 | /// Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using GjkPairDetector. | 57 | /// Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using GjkPairDetector. |
58 | /// </summary> | 58 | /// </summary> |
59 | /// <param name="fromA"></param> | 59 | /// <param name="fromA"></param> |
60 | /// <param name="toA"></param> | 60 | /// <param name="toA"></param> |
61 | /// <param name="fromB"></param> | 61 | /// <param name="fromB"></param> |
62 | /// <param name="toB"></param> | 62 | /// <param name="toB"></param> |
63 | /// <param name="result"></param> | 63 | /// <param name="result"></param> |
64 | /// <returns></returns> | 64 | /// <returns></returns> |
65 | public bool CalcTimeOfImpact(Matrix fromA, Matrix toA, Matrix fromB, Matrix toB, CastResult result) | 65 | public bool CalcTimeOfImpact(Matrix fromA, Matrix toA, Matrix fromB, Matrix toB, CastResult result) |
66 | { | 66 | { |
67 | MinkowskiSumShape convex = new MinkowskiSumShape(_convexA, _convexB); | 67 | MinkowskiSumShape convex = new MinkowskiSumShape(_convexA, _convexB); |
68 | 68 | ||
69 | Matrix rayFromLocalA; | 69 | Matrix rayFromLocalA; |
70 | Matrix rayToLocalA; | 70 | Matrix rayToLocalA; |
71 | 71 | ||
72 | rayFromLocalA = MathHelper.InvertMatrix(fromA) * fromB; | 72 | rayFromLocalA = MathHelper.InvertMatrix(fromA) * fromB; |
73 | rayToLocalA = MathHelper.InvertMatrix(toA) * toB; | 73 | rayToLocalA = MathHelper.InvertMatrix(toA) * toB; |
74 | 74 | ||
75 | _simplexSolver.Reset(); | 75 | _simplexSolver.Reset(); |
76 | 76 | ||
77 | convex.TransformB = rayFromLocalA; | 77 | convex.TransformB = rayFromLocalA; |
78 | 78 | ||
79 | float lambda = 0; | 79 | float lambda = 0; |
80 | //todo: need to verify this: | 80 | //todo: need to verify this: |
81 | //because of minkowski difference, we need the inverse direction | 81 | //because of minkowski difference, we need the inverse direction |
82 | 82 | ||
83 | Vector3 s = -rayFromLocalA.Translation; | 83 | Vector3 s = -rayFromLocalA.Translation; |
84 | Vector3 r = -(rayToLocalA.Translation - rayFromLocalA.Translation); | 84 | Vector3 r = -(rayToLocalA.Translation - rayFromLocalA.Translation); |
85 | Vector3 x = s; | 85 | Vector3 x = s; |
86 | Vector3 v; | 86 | Vector3 v; |
87 | Vector3 arbitraryPoint = convex.LocalGetSupportingVertex(r); | 87 | Vector3 arbitraryPoint = convex.LocalGetSupportingVertex(r); |
88 | 88 | ||
89 | v = x - arbitraryPoint; | 89 | v = x - arbitraryPoint; |
90 | 90 | ||
91 | int maxIter = MaxIterations; | 91 | int maxIter = MaxIterations; |
92 | 92 | ||
93 | Vector3 n = new Vector3(); | 93 | Vector3 n = new Vector3(); |
94 | float lastLambda = lambda; | 94 | float lastLambda = lambda; |
95 | 95 | ||
96 | float dist2 = v.LengthSquared(); | 96 | float dist2 = v.LengthSquared(); |
97 | float epsilon = 0.0001f; | 97 | float epsilon = 0.0001f; |
98 | 98 | ||
99 | Vector3 w, p; | 99 | Vector3 w, p; |
100 | float VdotR; | 100 | float VdotR; |
101 | 101 | ||
102 | while ((dist2 > epsilon) && (maxIter-- != 0)) | 102 | while ((dist2 > epsilon) && (maxIter-- != 0)) |
103 | { | 103 | { |
104 | p = convex.LocalGetSupportingVertex(v); | 104 | p = convex.LocalGetSupportingVertex(v); |
105 | w = x - p; | 105 | w = x - p; |
106 | 106 | ||
107 | float VdotW = Vector3.Dot(v, w); | 107 | float VdotW = Vector3.Dot(v, w); |
108 | 108 | ||
109 | if (VdotW > 0) | 109 | if (VdotW > 0) |
110 | { | 110 | { |
111 | VdotR = Vector3.Dot(v, r); | 111 | VdotR = Vector3.Dot(v, r); |
112 | 112 | ||
113 | if (VdotR >= -(MathHelper.Epsilon * MathHelper.Epsilon)) | 113 | if (VdotR >= -(MathHelper.Epsilon * MathHelper.Epsilon)) |
114 | return false; | 114 | return false; |
115 | else | 115 | else |
116 | { | 116 | { |
117 | lambda = lambda - VdotW / VdotR; | 117 | lambda = lambda - VdotW / VdotR; |
118 | x = s + lambda * r; | 118 | x = s + lambda * r; |
119 | _simplexSolver.Reset(); | 119 | _simplexSolver.Reset(); |
120 | //check next line | 120 | //check next line |
121 | w = x - p; | 121 | w = x - p; |
122 | lastLambda = lambda; | 122 | lastLambda = lambda; |
123 | n = v; | 123 | n = v; |
124 | } | 124 | } |
125 | } | 125 | } |
126 | _simplexSolver.AddVertex(w, x, p); | 126 | _simplexSolver.AddVertex(w, x, p); |
127 | if (_simplexSolver.Closest(out v)) | 127 | if (_simplexSolver.Closest(out v)) |
128 | { | 128 | { |
129 | dist2 = v.LengthSquared(); | 129 | dist2 = v.LengthSquared(); |
130 | } | 130 | } |
131 | else | 131 | else |
132 | { | 132 | { |
133 | dist2 = 0f; | 133 | dist2 = 0f; |
134 | } | 134 | } |
135 | } | 135 | } |
136 | result.Fraction = lambda; | 136 | result.Fraction = lambda; |
137 | result.Normal = n; | 137 | result.Normal = n; |
138 | return true; | 138 | return true; |
139 | } | 139 | } |
140 | #endregion | 140 | #endregion |
141 | } | 141 | } |
142 | } | 142 | } |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/TriangleRaycastCallback.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/TriangleRaycastCallback.cs index c127460..1e0fb3b 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/TriangleRaycastCallback.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/TriangleRaycastCallback.cs | |||
@@ -1,115 +1,115 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | public abstract class TriangleRaycastCallback : ITriangleCallback | 29 | public abstract class TriangleRaycastCallback : ITriangleCallback |
30 | { | 30 | { |
31 | private Vector3 _from; | 31 | private Vector3 _from; |
32 | private Vector3 _to; | 32 | private Vector3 _to; |
33 | private float _hitFraction; | 33 | private float _hitFraction; |
34 | 34 | ||
35 | public TriangleRaycastCallback(Vector3 from, Vector3 to) | 35 | public TriangleRaycastCallback(Vector3 from, Vector3 to) |
36 | { | 36 | { |
37 | _from = from; | 37 | _from = from; |
38 | _to = to; | 38 | _to = to; |
39 | _hitFraction = 1; | 39 | _hitFraction = 1; |
40 | } | 40 | } |
41 | 41 | ||
42 | public Vector3 From { get { return _from; } set { _from = value; } } | 42 | public Vector3 From { get { return _from; } set { _from = value; } } |
43 | public Vector3 To { get { return _to; } set { _to = value; } } | 43 | public Vector3 To { get { return _to; } set { _to = value; } } |
44 | public float HitFraction { get { return _hitFraction; } set { _hitFraction = value; } } | 44 | public float HitFraction { get { return _hitFraction; } set { _hitFraction = value; } } |
45 | 45 | ||
46 | public abstract float ReportHit(Vector3 hitNormalLocal, float hitFraction, int partId, int triangleIndex); | 46 | public abstract float ReportHit(Vector3 hitNormalLocal, float hitFraction, int partId, int triangleIndex); |
47 | 47 | ||
48 | #region ITriangleCallback Members | 48 | #region ITriangleCallback Members |
49 | 49 | ||
50 | public void ProcessTriangle(Vector3[] triangle, int partID, int triangleIndex) | 50 | public void ProcessTriangle(Vector3[] triangle, int partID, int triangleIndex) |
51 | { | 51 | { |
52 | Vector3 vertA = triangle[0]; | 52 | Vector3 vertA = triangle[0]; |
53 | Vector3 vertB = triangle[1]; | 53 | Vector3 vertB = triangle[1]; |
54 | Vector3 vertC = triangle[2]; | 54 | Vector3 vertC = triangle[2]; |
55 | 55 | ||
56 | Vector3 vBA = vertB - vertA; | 56 | Vector3 vBA = vertB - vertA; |
57 | Vector3 vCA = vertC - vertA; | 57 | Vector3 vCA = vertC - vertA; |
58 | 58 | ||
59 | Vector3 triangleNormal = Vector3.Cross(vBA, vCA); | 59 | Vector3 triangleNormal = Vector3.Cross(vBA, vCA); |
60 | 60 | ||
61 | float dist = Vector3.Dot(vertA, triangleNormal); | 61 | float dist = Vector3.Dot(vertA, triangleNormal); |
62 | float distA = Vector3.Dot(triangleNormal, _from); | 62 | float distA = Vector3.Dot(triangleNormal, _from); |
63 | distA -= dist; | 63 | distA -= dist; |
64 | float distB = Vector3.Dot(triangleNormal, _to); | 64 | float distB = Vector3.Dot(triangleNormal, _to); |
65 | distB -= dist; | 65 | distB -= dist; |
66 | 66 | ||
67 | if (distA * distB >= 0.0f) | 67 | if (distA * distB >= 0.0f) |
68 | { | 68 | { |
69 | return; // same sign | 69 | return; // same sign |
70 | } | 70 | } |
71 | 71 | ||
72 | float projLength = distA - distB; | 72 | float projLength = distA - distB; |
73 | float distance = (distA) / (projLength); | 73 | float distance = (distA) / (projLength); |
74 | // Now we have the intersection point on the plane, we'll see if it's inside the triangle | 74 | // Now we have the intersection point on the plane, we'll see if it's inside the triangle |
75 | // Add an epsilon as a tolerance for the raycast, | 75 | // Add an epsilon as a tolerance for the raycast, |
76 | // in case the ray hits exacly on the edge of the triangle. | 76 | // in case the ray hits exacly on the edge of the triangle. |
77 | // It must be scaled for the triangle size. | 77 | // It must be scaled for the triangle size. |
78 | 78 | ||
79 | if (distance < _hitFraction) | 79 | if (distance < _hitFraction) |
80 | { | 80 | { |
81 | float edgeTolerance = triangleNormal.LengthSquared(); | 81 | float edgeTolerance = triangleNormal.LengthSquared(); |
82 | edgeTolerance *= -0.0001f; | 82 | edgeTolerance *= -0.0001f; |
83 | Vector3 point = new Vector3(); | 83 | Vector3 point = new Vector3(); |
84 | MathHelper.SetInterpolate3(_from, _to, distance, ref point); | 84 | MathHelper.SetInterpolate3(_from, _to, distance, ref point); |
85 | 85 | ||
86 | Vector3 vertexAPoint = vertA - point; | 86 | Vector3 vertexAPoint = vertA - point; |
87 | Vector3 vertexBPoint = vertB - point; | 87 | Vector3 vertexBPoint = vertB - point; |
88 | Vector3 contactPointA = Vector3.Cross(vertexAPoint, vertexBPoint); | 88 | Vector3 contactPointA = Vector3.Cross(vertexAPoint, vertexBPoint); |
89 | 89 | ||
90 | if (Vector3.Dot(contactPointA, triangleNormal) >= edgeTolerance) | 90 | if (Vector3.Dot(contactPointA, triangleNormal) >= edgeTolerance) |
91 | { | 91 | { |
92 | Vector3 vertexCPoint = vertC - point; | 92 | Vector3 vertexCPoint = vertC - point; |
93 | Vector3 contactPointB = Vector3.Cross(vertexBPoint, vertexCPoint); | 93 | Vector3 contactPointB = Vector3.Cross(vertexBPoint, vertexCPoint); |
94 | if (Vector3.Dot(contactPointB, triangleNormal) >= edgeTolerance) | 94 | if (Vector3.Dot(contactPointB, triangleNormal) >= edgeTolerance) |
95 | { | 95 | { |
96 | Vector3 contactPointC = Vector3.Cross(vertexCPoint, vertexAPoint); | 96 | Vector3 contactPointC = Vector3.Cross(vertexCPoint, vertexAPoint); |
97 | 97 | ||
98 | if (Vector3.Dot(contactPointC, triangleNormal) >= edgeTolerance) | 98 | if (Vector3.Dot(contactPointC, triangleNormal) >= edgeTolerance) |
99 | { | 99 | { |
100 | if (distA > 0) | 100 | if (distA > 0) |
101 | { | 101 | { |
102 | _hitFraction = ReportHit(triangleNormal, distance, partID, triangleIndex); | 102 | _hitFraction = ReportHit(triangleNormal, distance, partID, triangleIndex); |
103 | } | 103 | } |
104 | else | 104 | else |
105 | { | 105 | { |
106 | _hitFraction = ReportHit(-triangleNormal, distance, partID, triangleIndex); | 106 | _hitFraction = ReportHit(-triangleNormal, distance, partID, triangleIndex); |
107 | } | 107 | } |
108 | } | 108 | } |
109 | } | 109 | } |
110 | } | 110 | } |
111 | } | 111 | } |
112 | } | 112 | } |
113 | #endregion | 113 | #endregion |
114 | } | 114 | } |
115 | } | 115 | } |
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/VoronoiSimplexSolver.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/VoronoiSimplexSolver.cs index 16f3dab..1bc94d3 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/VoronoiSimplexSolver.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/VoronoiSimplexSolver.cs | |||
@@ -1,643 +1,643 @@ | |||
1 | /* | 1 | /* |
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | 2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru |
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | 3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. | 7 | arising from the use of this software. |
8 | 8 | ||
9 | Permission is granted to anyone to use this software for any purpose, | 9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it | 10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: | 11 | freely, subject to the following restrictions: |
12 | 12 | ||
13 | 1. The origin of this software must not be misrepresented; you must not | 13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software | 14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be | 15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. | 16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be | 17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. | 18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. | 19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | using System; | 22 | using System; |
23 | using System.Collections.Generic; | 23 | using System.Collections.Generic; |
24 | using System.Text; | 24 | using System.Text; |
25 | using MonoXnaCompactMaths; | 25 | using MonoXnaCompactMaths; |
26 | 26 | ||
27 | namespace XnaDevRu.BulletX | 27 | namespace XnaDevRu.BulletX |
28 | { | 28 | { |
29 | public class UsageBitfield | 29 | public class UsageBitfield |
30 | { | 30 | { |
31 | private bool _usedVertexA, _usedVertexB, _usedVertexC, _usedVertexD; | 31 | private bool _usedVertexA, _usedVertexB, _usedVertexC, _usedVertexD; |
32 | 32 | ||
33 | public bool UsedVertexA { get { return _usedVertexA; } set { _usedVertexA = value; } } | 33 | public bool UsedVertexA { get { return _usedVertexA; } set { _usedVertexA = value; } } |
34 | public bool UsedVertexB { get { return _usedVertexB; } set { _usedVertexB = value; } } | 34 | public bool UsedVertexB { get { return _usedVertexB; } set { _usedVertexB = value; } } |
35 | public bool UsedVertexC { get { return _usedVertexC; } set { _usedVertexC = value; } } | 35 | public bool UsedVertexC { get { return _usedVertexC; } set { _usedVertexC = value; } } |
36 | public bool UsedVertexD { get { return _usedVertexD; } set { _usedVertexD = value; } } | 36 | public bool UsedVertexD { get { return _usedVertexD; } set { _usedVertexD = value; } } |
37 | 37 | ||
38 | public void Reset() | 38 | public void Reset() |
39 | { | 39 | { |
40 | _usedVertexA = _usedVertexB = _usedVertexC = _usedVertexD = false; | 40 | _usedVertexA = _usedVertexB = _usedVertexC = _usedVertexD = false; |
41 | } | 41 | } |
42 | } | 42 | } |
43 | 43 | ||
44 | public class SubSimplexClosestResult | 44 | public class SubSimplexClosestResult |
45 | { | 45 | { |
46 | private Vector3 _closestPointOnSimplex; | 46 | private Vector3 _closestPointOnSimplex; |
47 | 47 | ||
48 | //MASK for m_usedVertices | 48 | //MASK for m_usedVertices |
49 | //stores the simplex vertex-usage, using the MASK, | 49 | //stores the simplex vertex-usage, using the MASK, |
50 | // if m_usedVertices & MASK then the related vertex is used | 50 | // if m_usedVertices & MASK then the related vertex is used |
51 | private UsageBitfield _usedVertices = new UsageBitfield(); | 51 | private UsageBitfield _usedVertices = new UsageBitfield(); |
52 | private float[] _barycentricCoords = new float[4]; | 52 | private float[] _barycentricCoords = new float[4]; |
53 | private bool _degenerate; | 53 | private bool _degenerate; |
54 | 54 | ||
55 | public Vector3 ClosestPointOnSimplex { get { return _closestPointOnSimplex; } set { _closestPointOnSimplex = value; } } | 55 | public Vector3 ClosestPointOnSimplex { get { return _closestPointOnSimplex; } set { _closestPointOnSimplex = value; } } |
56 | public UsageBitfield UsedVertices { get { return _usedVertices; } set { _usedVertices = value; } } | 56 | public UsageBitfield UsedVertices { get { return _usedVertices; } set { _usedVertices = value; } } |
57 | public float[] BarycentricCoords { get { return _barycentricCoords; } set { _barycentricCoords = value; } } | 57 | public float[] BarycentricCoords { get { return _barycentricCoords; } set { _barycentricCoords = value; } } |
58 | public bool Degenerate { get { return _degenerate; } set { _degenerate = value; } } | 58 | public bool Degenerate { get { return _degenerate; } set { _degenerate = value; } } |
59 | 59 | ||
60 | public void Reset() | 60 | public void Reset() |
61 | { | 61 | { |
62 | _degenerate = false; | 62 | _degenerate = false; |
63 | SetBarycentricCoordinates(); | 63 | SetBarycentricCoordinates(); |
64 | _usedVertices.Reset(); | 64 | _usedVertices.Reset(); |
65 | } | 65 | } |
66 | 66 | ||
67 | public bool IsValid | 67 | public bool IsValid |
68 | { | 68 | { |
69 | get | 69 | get |
70 | { | 70 | { |
71 | return (_barycentricCoords[0] >= 0f) && | 71 | return (_barycentricCoords[0] >= 0f) && |
72 | (_barycentricCoords[1] >= 0f) && | 72 | (_barycentricCoords[1] >= 0f) && |
73 | (_barycentricCoords[2] >= 0f) && | 73 | (_barycentricCoords[2] >= 0f) && |
74 | (_barycentricCoords[3] >= 0f); | 74 | (_barycentricCoords[3] >= 0f); |
75 | } | 75 | } |
76 | } | 76 | } |
77 | 77 | ||
78 | public void SetBarycentricCoordinates() | 78 | public void SetBarycentricCoordinates() |
79 | { | 79 | { |
80 | SetBarycentricCoordinates(0f, 0f, 0f, 0f); | 80 | SetBarycentricCoordinates(0f, 0f, 0f, 0f); |
81 | } | 81 | } |
82 | 82 | ||
83 | public void SetBarycentricCoordinates(float a, float b, float c, float d) | 83 | public void SetBarycentricCoordinates(float a, float b, float c, float d) |
84 | { | 84 | { |
85 | _barycentricCoords[0] = a; | 85 | _barycentricCoords[0] = a; |
86 | _barycentricCoords[1] = b; | 86 | _barycentricCoords[1] = b; |
87 | _barycentricCoords[2] = c; | 87 | _barycentricCoords[2] = c; |
88 | _barycentricCoords[3] = d; | 88 | _barycentricCoords[3] = d; |
89 | } | 89 | } |
90 | } | 90 | } |
91 | 91 | ||
92 | /// VoronoiSimplexSolver is an implementation of the closest point distance | 92 | /// VoronoiSimplexSolver is an implementation of the closest point distance |
93 | /// algorithm from a 1-4 points simplex to the origin. | 93 | /// algorithm from a 1-4 points simplex to the origin. |
94 | /// Can be used with GJK, as an alternative to Johnson distance algorithm. | 94 | /// Can be used with GJK, as an alternative to Johnson distance algorithm. |
95 | public class VoronoiSimplexSolver : ISimplexSolver | 95 | public class VoronoiSimplexSolver : ISimplexSolver |
96 | { | 96 | { |
97 | private const int VertexA = 0, VertexB = 1, VertexC = 2, VertexD = 3; | 97 | private const int VertexA = 0, VertexB = 1, VertexC = 2, VertexD = 3; |
98 | 98 | ||
99 | private const int VoronoiSimplexMaxVerts = 5; | 99 | private const int VoronoiSimplexMaxVerts = 5; |
100 | private const bool CatchDegenerateTetrahedron = true; | 100 | private const bool CatchDegenerateTetrahedron = true; |
101 | 101 | ||
102 | private int _numVertices; | 102 | private int _numVertices; |
103 | 103 | ||
104 | private Vector3[] _simplexVectorW = new Vector3[VoronoiSimplexMaxVerts]; | 104 | private Vector3[] _simplexVectorW = new Vector3[VoronoiSimplexMaxVerts]; |
105 | private Vector3[] _simplexPointsP = new Vector3[VoronoiSimplexMaxVerts]; | 105 | private Vector3[] _simplexPointsP = new Vector3[VoronoiSimplexMaxVerts]; |
106 | private Vector3[] _simplexPointsQ = new Vector3[VoronoiSimplexMaxVerts]; | 106 | private Vector3[] _simplexPointsQ = new Vector3[VoronoiSimplexMaxVerts]; |
107 | 107 | ||
108 | private Vector3 _cachedPA; | 108 | private Vector3 _cachedPA; |
109 | private Vector3 _cachedPB; | 109 | private Vector3 _cachedPB; |
110 | private Vector3 _cachedV; | 110 | private Vector3 _cachedV; |
111 | private Vector3 _lastW; | 111 | private Vector3 _lastW; |
112 | private bool _cachedValidClosest; | 112 | private bool _cachedValidClosest; |
113 | 113 | ||
114 | private SubSimplexClosestResult _cachedBC = new SubSimplexClosestResult(); | 114 | private SubSimplexClosestResult _cachedBC = new SubSimplexClosestResult(); |
115 | 115 | ||
116 | private bool _needsUpdate; | 116 | private bool _needsUpdate; |
117 | 117 | ||
118 | #region ISimplexSolver Members | 118 | #region ISimplexSolver Members |
119 | 119 | ||
120 | public bool FullSimplex | 120 | public bool FullSimplex |
121 | { | 121 | { |
122 | get | 122 | get |
123 | { | 123 | { |
124 | return _numVertices == 4; | 124 | return _numVertices == 4; |
125 | } | 125 | } |
126 | } | 126 | } |
127 | 127 | ||
128 | public int NumVertices | 128 | public int NumVertices |
129 | { | 129 | { |
130 | get | 130 | get |
131 | { | 131 | { |
132 | return _numVertices; | 132 | return _numVertices; |
133 | } | 133 | } |
134 | } | 134 | } |
135 | 135 | ||
136 | public void Reset() | 136 | public void Reset() |
137 | { | 137 | { |
138 | _cachedValidClosest = false; | 138 | _cachedValidClosest = false; |
139 | _numVertices = 0; | 139 | _numVertices = 0; |
140 | _needsUpdate = true; | 140 | _needsUpdate = true; |
141 | _lastW = new Vector3(1e30f, 1e30f, 1e30f); | 141 | _lastW = new Vector3(1e30f, 1e30f, 1e30f); |
142 | _cachedBC.Reset(); | 142 | _cachedBC.Reset(); |
143 | } | 143 | } |
144 | 144 | ||
145 | public void AddVertex(Vector3 w, Vector3 p, Vector3 q) | 145 | public void AddVertex(Vector3 w, Vector3 p, Vector3 q) |
146 | { | 146 | { |
147 | _lastW = w; | 147 | _lastW = w; |
148 | _needsUpdate = true; | 148 | _needsUpdate = true; |
149 | 149 | ||
150 | _simplexVectorW[_numVertices] = w; | 150 | _simplexVectorW[_numVertices] = w; |
151 | _simplexPointsP[_numVertices] = p; | 151 | _simplexPointsP[_numVertices] = p; |
152 | _simplexPointsQ[_numVertices] = q; | 152 | _simplexPointsQ[_numVertices] = q; |
153 | 153 | ||
154 | _numVertices++; | 154 | _numVertices++; |
155 | } | 155 | } |
156 | 156 | ||
157 | //return/calculate the closest vertex | 157 | //return/calculate the closest vertex |
158 | public bool Closest(out Vector3 v) | 158 | public bool Closest(out Vector3 v) |
159 | { | 159 | { |
160 | bool succes = UpdateClosestVectorAndPoints(); | 160 | bool succes = UpdateClosestVectorAndPoints(); |
161 | v = _cachedV; | 161 | v = _cachedV; |
162 | return succes; | 162 | return succes; |
163 | } | 163 | } |
164 | 164 | ||
165 | public float MaxVertex | 165 | public float MaxVertex |
166 | { | 166 | { |
167 | get | 167 | get |
168 | { | 168 | { |
169 | int numverts = NumVertices; | 169 | int numverts = NumVertices; |
170 | float maxV = 0f, curLen2; | 170 | float maxV = 0f, curLen2; |
171 | for (int i = 0; i < numverts; i++) | 171 | for (int i = 0; i < numverts; i++) |
172 | { | 172 | { |
173 | curLen2 = _simplexVectorW[i].LengthSquared(); | 173 | curLen2 = _simplexVectorW[i].LengthSquared(); |
174 | if (maxV < curLen2) maxV = curLen2; | 174 | if (maxV < curLen2) maxV = curLen2; |
175 | } | 175 | } |
176 | return maxV; | 176 | return maxV; |
177 | } | 177 | } |
178 | } | 178 | } |
179 | 179 | ||
180 | //return the current simplex | 180 | //return the current simplex |
181 | public int GetSimplex(out Vector3[] pBuf, out Vector3[] qBuf, out Vector3[] yBuf) | 181 | public int GetSimplex(out Vector3[] pBuf, out Vector3[] qBuf, out Vector3[] yBuf) |
182 | { | 182 | { |
183 | int numverts = NumVertices; | 183 | int numverts = NumVertices; |
184 | pBuf = new Vector3[numverts]; | 184 | pBuf = new Vector3[numverts]; |
185 | qBuf = new Vector3[numverts]; | 185 | qBuf = new Vector3[numverts]; |
186 | yBuf = new Vector3[numverts]; | 186 | yBuf = new Vector3[numverts]; |
187 | for (int i = 0; i < numverts; i++) | 187 | for (int i = 0; i < numverts; i++) |
188 | { | 188 | { |
189 | yBuf[i] = _simplexVectorW[i]; | 189 | yBuf[i] = _simplexVectorW[i]; |
190 | pBuf[i] = _simplexPointsP[i]; | 190 | pBuf[i] = _simplexPointsP[i]; |
191 | qBuf[i] = _simplexPointsQ[i]; | 191 | qBuf[i] = _simplexPointsQ[i]; |
192 | } | 192 | } |
193 | return numverts; | 193 | return numverts; |
194 | } | 194 | } |
195 | 195 | ||
196 | public bool InSimplex(Vector3 w) | 196 | public bool InSimplex(Vector3 w) |
197 | { | 197 | { |
198 | //check in case lastW is already removed | 198 | //check in case lastW is already removed |
199 | if (w == _lastW) return true; | 199 | if (w == _lastW) return true; |
200 | 200 | ||
201 | //w is in the current (reduced) simplex | 201 | //w is in the current (reduced) simplex |
202 | int numverts = NumVertices; | 202 | int numverts = NumVertices; |
203 | for (int i = 0; i < numverts; i++) | 203 | for (int i = 0; i < numverts; i++) |
204 | if (_simplexVectorW[i] == w) return true; | 204 | if (_simplexVectorW[i] == w) return true; |
205 | 205 | ||
206 | return false; | 206 | return false; |
207 | } | 207 | } |
208 | 208 | ||
209 | public void BackupClosest(out Vector3 v) | 209 | public void BackupClosest(out Vector3 v) |
210 | { | 210 | { |
211 | v = _cachedV; | 211 | v = _cachedV; |
212 | } | 212 | } |
213 | 213 | ||
214 | public bool EmptySimplex | 214 | public bool EmptySimplex |
215 | { | 215 | { |
216 | get | 216 | get |
217 | { | 217 | { |
218 | return NumVertices == 0; | 218 | return NumVertices == 0; |
219 | } | 219 | } |
220 | } | 220 | } |
221 | 221 | ||
222 | public void ComputePoints(out Vector3 p1, out Vector3 p2) | 222 | public void ComputePoints(out Vector3 p1, out Vector3 p2) |
223 | { | 223 | { |
224 | UpdateClosestVectorAndPoints(); | 224 | UpdateClosestVectorAndPoints(); |
225 | p1 = _cachedPA; | 225 | p1 = _cachedPA; |
226 | p2 = _cachedPB; | 226 | p2 = _cachedPB; |
227 | } | 227 | } |
228 | 228 | ||
229 | #endregion | 229 | #endregion |
230 | 230 | ||
231 | public void RemoveVertex(int index) | 231 | public void RemoveVertex(int index) |
232 | { | 232 | { |
233 | BulletDebug.Assert(_numVertices > 0); | 233 | BulletDebug.Assert(_numVertices > 0); |
234 | _numVertices--; | 234 | _numVertices--; |
235 | _simplexVectorW[index] = _simplexVectorW[_numVertices]; | 235 | _simplexVectorW[index] = _simplexVectorW[_numVertices]; |
236 | _simplexPointsP[index] = _simplexPointsP[_numVertices]; | 236 | _simplexPointsP[index] = _simplexPointsP[_numVertices]; |
237 | _simplexPointsQ[index] = _simplexPointsQ[_numVertices]; | 237 | _simplexPointsQ[index] = _simplexPointsQ[_numVertices]; |
238 | } | 238 | } |
239 | 239 | ||
240 | public void ReduceVertices(UsageBitfield usedVerts) | 240 | public void ReduceVertices(UsageBitfield usedVerts) |
241 | { | 241 | { |
242 | if ((NumVertices >= 4) && (!usedVerts.UsedVertexD)) RemoveVertex(3); | 242 | if ((NumVertices >= 4) && (!usedVerts.UsedVertexD)) RemoveVertex(3); |
243 | if ((NumVertices >= 3) && (!usedVerts.UsedVertexC)) RemoveVertex(2); | 243 | if ((NumVertices >= 3) && (!usedVerts.UsedVertexC)) RemoveVertex(2); |
244 | if ((NumVertices >= 2) && (!usedVerts.UsedVertexB)) RemoveVertex(1); | 244 | if ((NumVertices >= 2) && (!usedVerts.UsedVertexB)) RemoveVertex(1); |
245 | if ((NumVertices >= 1) && (!usedVerts.UsedVertexA)) RemoveVertex(0); | 245 | if ((NumVertices >= 1) && (!usedVerts.UsedVertexA)) RemoveVertex(0); |
246 | } | 246 | } |
247 | 247 | ||
248 | public bool UpdateClosestVectorAndPoints() | 248 | public bool UpdateClosestVectorAndPoints() |
249 | { | 249 | { |
250 | if (_needsUpdate) | 250 | if (_needsUpdate) |
251 | { | 251 | { |
252 | _cachedBC.Reset(); | 252 | _cachedBC.Reset(); |
253 | _needsUpdate = false; | 253 | _needsUpdate = false; |
254 | 254 | ||
255 | Vector3 p, a, b, c, d; | 255 | Vector3 p, a, b, c, d; |
256 | switch (NumVertices) | 256 | switch (NumVertices) |
257 | { | 257 | { |
258 | case 0: | 258 | case 0: |
259 | _cachedValidClosest = false; | 259 | _cachedValidClosest = false; |
260 | break; | 260 | break; |
261 | case 1: | 261 | case 1: |
262 | _cachedPA = _simplexPointsP[0]; | 262 | _cachedPA = _simplexPointsP[0]; |
263 | _cachedPB = _simplexPointsQ[0]; | 263 | _cachedPB = _simplexPointsQ[0]; |
264 | _cachedV = _cachedPA - _cachedPB; | 264 | _cachedV = _cachedPA - _cachedPB; |
265 | _cachedBC.Reset(); | 265 | _cachedBC.Reset(); |
266 | _cachedBC.SetBarycentricCoordinates(1f, 0f, 0f, 0f); | 266 | _cachedBC.SetBarycentricCoordinates(1f, 0f, 0f, 0f); |
267 | _cachedValidClosest = _cachedBC.IsValid; | 267 | _cachedValidClosest = _cachedBC.IsValid; |
268 | break; | 268 | break; |
269 | case 2: | 269 | case 2: |
270 | //closest point origin from line segment | 270 | //closest point origin from line segment |
271 | Vector3 from = _simplexVectorW[0]; | 271 | Vector3 from = _simplexVectorW[0]; |
272 | Vector3 to = _simplexVectorW[1]; | 272 | Vector3 to = _simplexVectorW[1]; |
273 | Vector3 nearest; | 273 | Vector3 nearest; |
274 | 274 | ||
275 | Vector3 diff = -from; | 275 | Vector3 diff = -from; |
276 | Vector3 v = to - from; | 276 | Vector3 v = to - from; |
277 | float t = Vector3.Dot(v, diff); | 277 | float t = Vector3.Dot(v, diff); |
278 | 278 | ||
279 | if (t > 0) | 279 | if (t > 0) |
280 | { | 280 | { |
281 | float dotVV = v.LengthSquared(); | 281 | float dotVV = v.LengthSquared(); |
282 | if (t < dotVV) | 282 | if (t < dotVV) |
283 | { | 283 | { |
284 | t /= dotVV; | 284 | t /= dotVV; |
285 | diff -= t * v; | 285 | diff -= t * v; |
286 | _cachedBC.UsedVertices.UsedVertexA = true; | 286 | _cachedBC.UsedVertices.UsedVertexA = true; |
287 | _cachedBC.UsedVertices.UsedVertexB = true; | 287 | _cachedBC.UsedVertices.UsedVertexB = true; |
288 | } | 288 | } |
289 | else | 289 | else |
290 | { | 290 | { |
291 | t = 1; | 291 | t = 1; |
292 | diff -= v; | 292 | diff -= v; |
293 | //reduce to 1 point | 293 | //reduce to 1 point |
294 | _cachedBC.UsedVertices.UsedVertexB = true; | 294 | _cachedBC.UsedVertices.UsedVertexB = true; |
295 | } | 295 | } |
296 | } | 296 | } |
297 | else | 297 | else |
298 | { | 298 | { |
299 | t = 0; | 299 | t = 0; |
300 | //reduce to 1 point | 300 | //reduce to 1 point |
301 | _cachedBC.UsedVertices.UsedVertexA = true; | 301 | _cachedBC.UsedVertices.UsedVertexA = true; |
302 | } | 302 | } |
303 | 303 | ||
304 | _cachedBC.SetBarycentricCoordinates(1 - t, t, 0, 0); | 304 | _cachedBC.SetBarycentricCoordinates(1 - t, t, 0, 0); |
305 | nearest = from + t * v; | 305 | nearest = from + t * v; |
306 | 306 | ||
307 | _cachedPA = _simplexPointsP[0] + t * (_simplexPointsP[1] - _simplexPointsP[0]); | 307 | _cachedPA = _simplexPointsP[0] + t * (_simplexPointsP[1] - _simplexPointsP[0]); |
308 | _cachedPB = _simplexPointsQ[0] + t * (_simplexPointsQ[1] - _simplexPointsQ[0]); | 308 | _cachedPB = _simplexPointsQ[0] + t * (_simplexPointsQ[1] - _simplexPointsQ[0]); |
309 | _cachedV = _cachedPA - _cachedPB; | 309 | _cachedV = _cachedPA - _cachedPB; |
310 | 310 | ||
311 | ReduceVertices(_cachedBC.UsedVertices); | 311 | ReduceVertices(_cachedBC.UsedVertices); |
312 | 312 | ||
313 | _cachedValidClosest = _cachedBC.IsValid; | 313 | _cachedValidClosest = _cachedBC.IsValid; |
314 | break; | 314 | break; |
315 | case 3: | 315 | case 3: |
316 | //closest point origin from triangle | 316 | //closest point origin from triangle |
317 | p = new Vector3(); | 317 | p = new Vector3(); |
318 | a = _simplexVectorW[0]; | 318 | a = _simplexVectorW[0]; |
319 | b = _simplexVectorW[1]; | 319 | b = _simplexVectorW[1]; |
320 | c = _simplexVectorW[2]; | 320 | c = _simplexVectorW[2]; |
321 | 321 | ||
322 | ClosestPtPointTriangle(p, a, b, c, ref _cachedBC); | 322 | ClosestPtPointTriangle(p, a, b, c, ref _cachedBC); |
323 | _cachedPA = _simplexPointsP[0] * _cachedBC.BarycentricCoords[0] + | 323 | _cachedPA = _simplexPointsP[0] * _cachedBC.BarycentricCoords[0] + |
324 | _simplexPointsP[1] * _cachedBC.BarycentricCoords[1] + | 324 | _simplexPointsP[1] * _cachedBC.BarycentricCoords[1] + |
325 | _simplexPointsP[2] * _cachedBC.BarycentricCoords[2] + | 325 | _simplexPointsP[2] * _cachedBC.BarycentricCoords[2] + |
326 | _simplexPointsP[3] * _cachedBC.BarycentricCoords[3]; | 326 | _simplexPointsP[3] * _cachedBC.BarycentricCoords[3]; |
327 | 327 | ||
328 | _cachedPB = _simplexPointsQ[0] * _cachedBC.BarycentricCoords[0] + | 328 | _cachedPB = _simplexPointsQ[0] * _cachedBC.BarycentricCoords[0] + |
329 | _simplexPointsQ[1] * _cachedBC.BarycentricCoords[1] + | 329 | _simplexPointsQ[1] * _cachedBC.BarycentricCoords[1] + |
330 | _simplexPointsQ[2] * _cachedBC.BarycentricCoords[2] + | 330 | _simplexPointsQ[2] * _cachedBC.BarycentricCoords[2] + |
331 | _simplexPointsQ[3] * _cachedBC.BarycentricCoords[3]; | 331 | _simplexPointsQ[3] * _cachedBC.BarycentricCoords[3]; |
332 | 332 | ||
333 | _cachedV = _cachedPA - _cachedPB; | 333 | _cachedV = _cachedPA - _cachedPB; |
334 | 334 | ||
335 | ReduceVertices(_cachedBC.UsedVertices); | 335 | ReduceVertices(_cachedBC.UsedVertices); |
336 | _cachedValidClosest = _cachedBC.IsValid; | 336 | _cachedValidClosest = _cachedBC.IsValid; |
337 | break; | 337 | break; |
338 | case 4: | 338 | case 4: |
339 | p = new Vector3(); | 339 | p = new Vector3(); |
340 | a = _simplexVectorW[0]; | 340 | a = _simplexVectorW[0]; |
341 | b = _simplexVectorW[1]; | 341 | b = _simplexVectorW[1]; |
342 | c = _simplexVectorW[2]; | 342 | c = _simplexVectorW[2]; |
343 | d = _simplexVectorW[3]; | 343 | d = _simplexVectorW[3]; |
344 | 344 | ||
345 | bool hasSeperation = ClosestPtPointTetrahedron(p, a, b, c, d, ref _cachedBC); | 345 | bool hasSeperation = ClosestPtPointTetrahedron(p, a, b, c, d, ref _cachedBC); |
346 | 346 | ||
347 | if (hasSeperation) | 347 | if (hasSeperation) |
348 | { | 348 | { |
349 | _cachedPA = _simplexPointsP[0] * _cachedBC.BarycentricCoords[0] + | 349 | _cachedPA = _simplexPointsP[0] * _cachedBC.BarycentricCoords[0] + |
350 | _simplexPointsP[1] * _cachedBC.BarycentricCoords[1] + | 350 | _simplexPointsP[1] * _cachedBC.BarycentricCoords[1] + |
351 | _simplexPointsP[2] * _cachedBC.BarycentricCoords[2] + | 351 | _simplexPointsP[2] * _cachedBC.BarycentricCoords[2] + |
352 | _simplexPointsP[3] * _cachedBC.BarycentricCoords[3]; | 352 | _simplexPointsP[3] * _cachedBC.BarycentricCoords[3]; |
353 | 353 | ||
354 | _cachedPB = _simplexPointsQ[0] * _cachedBC.BarycentricCoords[0] + | 354 | _cachedPB = _simplexPointsQ[0] * _cachedBC.BarycentricCoords[0] + |
355 | _simplexPointsQ[1] * _cachedBC.BarycentricCoords[1] + | 355 | _simplexPointsQ[1] * _cachedBC.BarycentricCoords[1] + |
356 | _simplexPointsQ[2] * _cachedBC.BarycentricCoords[2] + | 356 | _simplexPointsQ[2] * _cachedBC.BarycentricCoords[2] + |
357 | _simplexPointsQ[3] * _cachedBC.BarycentricCoords[3]; | 357 | _simplexPointsQ[3] * _cachedBC.BarycentricCoords[3]; |
358 | 358 | ||
359 | _cachedV = _cachedPA - _cachedPB; | 359 | _cachedV = _cachedPA - _cachedPB; |
360 | ReduceVertices(_cachedBC.UsedVertices); | 360 | ReduceVertices(_cachedBC.UsedVertices); |
361 | } | 361 | } |
362 | else | 362 | else |
363 | { | 363 | { |
364 | if (_cachedBC.Degenerate) | 364 | if (_cachedBC.Degenerate) |
365 | { | 365 | { |
366 | _cachedValidClosest = false; | 366 | _cachedValidClosest = false; |
367 | } | 367 | } |
368 | else | 368 | else |
369 | { | 369 | { |
370 | _cachedValidClosest = true; | 370 | _cachedValidClosest = true; |
371 | //degenerate case == false, penetration = true + zero | 371 | //degenerate case == false, penetration = true + zero |
372 | _cachedV.X = _cachedV.Y = _cachedV.Z = 0f; | 372 | _cachedV.X = _cachedV.Y = _cachedV.Z = 0f; |
373 | } | 373 | } |
374 | break; // !!!!!!!!!!!! proverit na vsakiy sluchai | 374 | break; // !!!!!!!!!!!! proverit na vsakiy sluchai |
375 | } | 375 | } |
376 | 376 | ||
377 | _cachedValidClosest = _cachedBC.IsValid; | 377 | _cachedValidClosest = _cachedBC.IsValid; |
378 | 378 | ||
379 | //closest point origin from tetrahedron | 379 | //closest point origin from tetrahedron |
380 | break; | 380 | break; |
381 | default: | 381 | default: |
382 | _cachedValidClosest = false; | 382 | _cachedValidClosest = false; |
383 | break; | 383 | break; |
384 | } | 384 | } |
385 | } | 385 | } |
386 | 386 | ||
387 | return _cachedValidClosest; | 387 | return _cachedValidClosest; |
388 | } | 388 | } |
389 | 389 | ||
390 | public bool ClosestPtPointTriangle(Vector3 p, Vector3 a, Vector3 b, Vector3 c, | 390 | public bool ClosestPtPointTriangle(Vector3 p, Vector3 a, Vector3 b, Vector3 c, |
391 | ref SubSimplexClosestResult result) | 391 | ref SubSimplexClosestResult result) |
392 | { | 392 | { |
393 | result.UsedVertices.Reset(); | 393 | result.UsedVertices.Reset(); |
394 | 394 | ||
395 | float v, w; | 395 | float v, w; |
396 | 396 | ||
397 | // Check if P in vertex region outside A | 397 | // Check if P in vertex region outside A |
398 | Vector3 ab = b - a; | 398 | Vector3 ab = b - a; |
399 | Vector3 ac = c - a; | 399 | Vector3 ac = c - a; |
400 | Vector3 ap = p - a; | 400 | Vector3 ap = p - a; |
401 | float d1 = Vector3.Dot(ab, ap); | 401 | float d1 = Vector3.Dot(ab, ap); |
402 | float d2 = Vector3.Dot(ac, ap); | 402 | float d2 = Vector3.Dot(ac, ap); |
403 | if (d1 <= 0f && d2 <= 0f) | 403 | if (d1 <= 0f && d2 <= 0f) |
404 | { | 404 | { |
405 | result.ClosestPointOnSimplex = a; | 405 | result.ClosestPointOnSimplex = a; |
406 | result.UsedVertices.UsedVertexA = true; | 406 | result.UsedVertices.UsedVertexA = true; |
407 | result.SetBarycentricCoordinates(1, 0, 0, 0); | 407 | result.SetBarycentricCoordinates(1, 0, 0, 0); |
408 | return true; // a; // barycentric coordinates (1,0,0) | 408 | return true; // a; // barycentric coordinates (1,0,0) |
409 | } | 409 | } |
410 | 410 | ||
411 | // Check if P in vertex region outside B | 411 | // Check if P in vertex region outside B |
412 | Vector3 bp = p - b; | 412 | Vector3 bp = p - b; |
413 | float d3 = Vector3.Dot(ab, bp); | 413 | float d3 = Vector3.Dot(ab, bp); |
414 | float d4 = Vector3.Dot(ac, bp); | 414 | float d4 = Vector3.Dot(ac, bp); |
415 | if (d3 >= 0f && d4 <= d3) | 415 | if (d3 >= 0f && d4 <= d3) |
416 | { | 416 | { |
417 | result.ClosestPointOnSimplex = b; | 417 | result.ClosestPointOnSimplex = b; |
418 | result.UsedVertices.UsedVertexB = true; | 418 | result.UsedVertices.UsedVertexB = true; |
419 | result.SetBarycentricCoordinates(0, 1, 0, 0); | 419 | result.SetBarycentricCoordinates(0, 1, 0, 0); |
420 | 420 | ||
421 | return true; // b; // barycentric coordinates (0,1,0) | 421 | return true; // b; // barycentric coordinates (0,1,0) |
422 | } | 422 | } |
423 | // Check if P in edge region of AB, if so return projection of P onto AB | 423 | // Check if P in edge region of AB, if so return projection of P onto AB |
424 | float vc = d1 * d4 - d3 * d2; | 424 | float vc = d1 * d4 - d3 * d2; |
425 | if (vc <= 0f && d1 >= 0f && d3 <= 0f) | 425 | if (vc <= 0f && d1 >= 0f && d3 <= 0f) |
426 | { | 426 | { |
427 | v = d1 / (d1 - d3); | 427 | v = d1 / (d1 - d3); |
428 | result.ClosestPointOnSimplex = a + v * ab; | 428 | result.ClosestPointOnSimplex = a + v * ab; |
429 | result.UsedVertices.UsedVertexA = true; | 429 | result.UsedVertices.UsedVertexA = true; |
430 | result.UsedVertices.UsedVertexB = true; | 430 | result.UsedVertices.UsedVertexB = true; |
431 | result.SetBarycentricCoordinates(1 - v, v, 0, 0); | 431 | result.SetBarycentricCoordinates(1 - v, v, 0, 0); |
432 | return true; | 432 | return true; |
433 | //return a + v * ab; // barycentric coordinates (1-v,v,0) | 433 | //return a + v * ab; // barycentric coordinates (1-v,v,0) |
434 | } | 434 | } |
435 | 435 | ||
436 | // Check if P in vertex region outside C | 436 | // Check if P in vertex region outside C |
437 | Vector3 cp = p - c; | 437 | Vector3 cp = p - c; |
438 | float d5 = Vector3.Dot(ab, cp); | 438 | float d5 = Vector3.Dot(ab, cp); |
439 | float d6 = Vector3.Dot(ac, cp); | 439 | float d6 = Vector3.Dot(ac, cp); |
440 | if (d6 >= 0f && d5 <= d6) | 440 | if (d6 >= 0f && d5 <= d6) |
441 | { | 441 | { |
442 | result.ClosestPointOnSimplex = c; | 442 | result.ClosestPointOnSimplex = c; |
443 | result.UsedVertices.UsedVertexC = true; | 443 | result.UsedVertices.UsedVertexC = true; |
444 | result.SetBarycentricCoordinates(0, 0, 1, 0); | 444 | result.SetBarycentricCoordinates(0, 0, 1, 0); |
445 | return true;//c; // barycentric coordinates (0,0,1) | 445 | return true;//c; // barycentric coordinates (0,0,1) |
446 | } | 446 | } |
447 | 447 | ||
448 | // Check if P in edge region of AC, if so return projection of P onto AC | 448 | // Check if P in edge region of AC, if so return projection of P onto AC |
449 | float vb = d5 * d2 - d1 * d6; | 449 | float vb = d5 * d2 - d1 * d6; |
450 | if (vb <= 0f && d2 >= 0f && d6 <= 0f) | 450 | if (vb <= 0f && d2 >= 0f && d6 <= 0f) |
451 | { | 451 | { |
452 | w = d2 / (d2 - d6); | 452 | w = d2 / (d2 - d6); |
453 | result.ClosestPointOnSimplex = a + w * ac; | 453 | result.ClosestPointOnSimplex = a + w * ac; |
454 | result.UsedVertices.UsedVertexA = true; | 454 | result.UsedVertices.UsedVertexA = true; |
455 | result.UsedVertices.UsedVertexC = true; | 455 | result.UsedVertices.UsedVertexC = true; |
456 | result.SetBarycentricCoordinates(1 - w, 0, w, 0); | 456 | result.SetBarycentricCoordinates(1 - w, 0, w, 0); |
457 | return true; | 457 | return true; |
458 | //return a + w * ac; // barycentric coordinates (1-w,0,w) | 458 | //return a + w * ac; // barycentric coordinates (1-w,0,w) |
459 | } | 459 | } |
460 | 460 | ||
461 | // Check if P in edge region of BC, if so return projection of P onto BC | 461 | // Check if P in edge region of BC, if so return projection of P onto BC |
462 | float va = d3 * d6 - d5 * d4; | 462 | float va = d3 * d6 - d5 * d4; |
463 | if (va <= 0f && (d4 - d3) >= 0f && (d5 - d6) >= 0f) | 463 | if (va <= 0f && (d4 - d3) >= 0f && (d5 - d6) >= 0f) |
464 | { | 464 | { |
465 | w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); | 465 | w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); |
466 | 466 | ||
467 | result.ClosestPointOnSimplex = b + w * (c - b); | 467 | result.ClosestPointOnSimplex = b + w * (c - b); |
468 | result.UsedVertices.UsedVertexB = true; | 468 | result.UsedVertices.UsedVertexB = true; |
469 | result.UsedVertices.UsedVertexC = true; | 469 | result.UsedVertices.UsedVertexC = true; |
470 | result.SetBarycentricCoordinates(0, 1 - w, w, 0); | 470 | result.SetBarycentricCoordinates(0, 1 - w, w, 0); |
471 | return true; | 471 | return true; |
472 | // return b + w * (c - b); // barycentric coordinates (0,1-w,w) | 472 | // return b + w * (c - b); // barycentric coordinates (0,1-w,w) |
473 | } | 473 | } |
474 | 474 | ||
475 | // P inside face region. Compute Q through its barycentric coordinates (u,v,w) | 475 | // P inside face region. Compute Q through its barycentric coordinates (u,v,w) |
476 | float denom = 1.0f / (va + vb + vc); | 476 | float denom = 1.0f / (va + vb + vc); |
477 | v = vb * denom; | 477 | v = vb * denom; |
478 | w = vc * denom; | 478 | w = vc * denom; |
479 | 479 | ||
480 | result.ClosestPointOnSimplex = a + ab * v + ac * w; | 480 | result.ClosestPointOnSimplex = a + ab * v + ac * w; |
481 | result.UsedVertices.UsedVertexA = true; | 481 | result.UsedVertices.UsedVertexA = true; |
482 | result.UsedVertices.UsedVertexB = true; | 482 | result.UsedVertices.UsedVertexB = true; |
483 | result.UsedVertices.UsedVertexC = true; | 483 | result.UsedVertices.UsedVertexC = true; |
484 | result.SetBarycentricCoordinates(1 - v - w, v, w, 0); | 484 | result.SetBarycentricCoordinates(1 - v - w, v, w, 0); |
485 | 485 | ||
486 | return true; | 486 | return true; |
487 | } | 487 | } |
488 | 488 | ||
489 | /// Test if point p and d lie on opposite sides of plane through abc | 489 | /// Test if point p and d lie on opposite sides of plane through abc |
490 | public int PointOutsideOfPlane(Vector3 p, Vector3 a, Vector3 b, Vector3 c, Vector3 d) | 490 | public int PointOutsideOfPlane(Vector3 p, Vector3 a, Vector3 b, Vector3 c, Vector3 d) |
491 | { | 491 | { |
492 | Vector3 normal = Vector3.Cross(b - a, c - a); | 492 | Vector3 normal = Vector3.Cross(b - a, c - a); |
493 | 493 | ||
494 | float signp = Vector3.Dot(p - a, normal); // [AP AB AC] | 494 | float signp = Vector3.Dot(p - a, normal); // [AP AB AC] |
495 | float signd = Vector3.Dot(d - a, normal); // [AD AB AC] | 495 | float signd = Vector3.Dot(d - a, normal); // [AD AB AC] |
496 | 496 | ||
497 | if (CatchDegenerateTetrahedron) | 497 | if (CatchDegenerateTetrahedron) |
498 | if (signd * signd < (1e-4f * 1e-4f)) return -1; | 498 | if (signd * signd < (1e-4f * 1e-4f)) return -1; |
499 | 499 | ||
500 | // Points on opposite sides if expression signs are opposite | 500 | // Points on opposite sides if expression signs are opposite |
501 | return signp * signd < 0f ? 1 : 0; | 501 | return signp * signd < 0f ? 1 : 0; |
502 | } | 502 | } |
503 | 503 | ||
504 | public bool ClosestPtPointTetrahedron(Vector3 p, Vector3 a, Vector3 b, Vector3 c, Vector3 d, | 504 | public bool ClosestPtPointTetrahedron(Vector3 p, Vector3 a, Vector3 b, Vector3 c, Vector3 d, |
505 | ref SubSimplexClosestResult finalResult) | 505 | ref SubSimplexClosestResult finalResult) |
506 | { | 506 | { |
507 | SubSimplexClosestResult tempResult = new SubSimplexClosestResult(); | 507 | SubSimplexClosestResult tempResult = new SubSimplexClosestResult(); |
508 | 508 | ||
509 | // Start out assuming point inside all halfspaces, so closest to itself | 509 | // Start out assuming point inside all halfspaces, so closest to itself |
510 | finalResult.ClosestPointOnSimplex = p; | 510 | finalResult.ClosestPointOnSimplex = p; |
511 | finalResult.UsedVertices.Reset(); | 511 | finalResult.UsedVertices.Reset(); |
512 | finalResult.UsedVertices.UsedVertexA = true; | 512 | finalResult.UsedVertices.UsedVertexA = true; |
513 | finalResult.UsedVertices.UsedVertexB = true; | 513 | finalResult.UsedVertices.UsedVertexB = true; |
514 | finalResult.UsedVertices.UsedVertexC = true; | 514 | finalResult.UsedVertices.UsedVertexC = true; |
515 | finalResult.UsedVertices.UsedVertexD = true; | 515 | finalResult.UsedVertices.UsedVertexD = true; |
516 | 516 | ||
517 | int pointOutsideABC = PointOutsideOfPlane(p, a, b, c, d); | 517 | int pointOutsideABC = PointOutsideOfPlane(p, a, b, c, d); |
518 | int pointOutsideACD = PointOutsideOfPlane(p, a, c, d, b); | 518 | int pointOutsideACD = PointOutsideOfPlane(p, a, c, d, b); |
519 | int pointOutsideADB = PointOutsideOfPlane(p, a, d, b, c); | 519 | int pointOutsideADB = PointOutsideOfPlane(p, a, d, b, c); |
520 | int pointOutsideBDC = PointOutsideOfPlane(p, b, d, c, a); | 520 | int pointOutsideBDC = PointOutsideOfPlane(p, b, d, c, a); |
521 | 521 | ||
522 | if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0) | 522 | if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0) |
523 | { | 523 | { |
524 | finalResult.Degenerate = true; | 524 | finalResult.Degenerate = true; |
525 | return false; | 525 | return false; |
526 | } | 526 | } |
527 | 527 | ||
528 | if (pointOutsideABC == 0 && pointOutsideACD == 0 && pointOutsideADB == 0 && pointOutsideBDC == 0) | 528 | if (pointOutsideABC == 0 && pointOutsideACD == 0 && pointOutsideADB == 0 && pointOutsideBDC == 0) |
529 | return false; | 529 | return false; |
530 | 530 | ||
531 | float bestSqDist = float.MaxValue; | 531 | float bestSqDist = float.MaxValue; |
532 | // If point outside face abc then compute closest point on abc | 532 | // If point outside face abc then compute closest point on abc |
533 | if (pointOutsideABC != 0) | 533 | if (pointOutsideABC != 0) |
534 | { | 534 | { |
535 | ClosestPtPointTriangle(p, a, b, c, ref tempResult); | 535 | ClosestPtPointTriangle(p, a, b, c, ref tempResult); |
536 | Vector3 q = tempResult.ClosestPointOnSimplex; | 536 | Vector3 q = tempResult.ClosestPointOnSimplex; |
537 | 537 | ||
538 | float sqDist = ((Vector3)(q - p)).LengthSquared(); | 538 | float sqDist = ((Vector3)(q - p)).LengthSquared(); |
539 | // Update best closest point if (squared) distance is less than current best | 539 | // Update best closest point if (squared) distance is less than current best |
540 | if (sqDist < bestSqDist) | 540 | if (sqDist < bestSqDist) |
541 | { | 541 | { |
542 | bestSqDist = sqDist; | 542 | bestSqDist = sqDist; |
543 | finalResult.ClosestPointOnSimplex = q; | 543 | finalResult.ClosestPointOnSimplex = q; |
544 | //convert result bitmask! | 544 | //convert result bitmask! |
545 | finalResult.UsedVertices.Reset(); | 545 | finalResult.UsedVertices.Reset(); |
546 | finalResult.UsedVertices.UsedVertexA = tempResult.UsedVertices.UsedVertexA; | 546 | finalResult.UsedVertices.UsedVertexA = tempResult.UsedVertices.UsedVertexA; |
547 | finalResult.UsedVertices.UsedVertexB = tempResult.UsedVertices.UsedVertexB; | 547 | finalResult.UsedVertices.UsedVertexB = tempResult.UsedVertices.UsedVertexB; |
548 | finalResult.UsedVertices.UsedVertexC = tempResult.UsedVertices.UsedVertexC; | 548 | finalResult.UsedVertices.UsedVertexC = tempResult.UsedVertices.UsedVertexC; |
549 | finalResult.SetBarycentricCoordinates( | 549 | finalResult.SetBarycentricCoordinates( |
550 | tempResult.BarycentricCoords[VertexA], | 550 | tempResult.BarycentricCoords[VertexA], |
551 | tempResult.BarycentricCoords[VertexB], | 551 | tempResult.BarycentricCoords[VertexB], |
552 | tempResult.BarycentricCoords[VertexC], | 552 | tempResult.BarycentricCoords[VertexC], |
553 | 0); | 553 | 0); |
554 | } | 554 | } |
555 | } | 555 | } |
556 | 556 | ||
557 | // Repeat test for face acd | 557 | // Repeat test for face acd |
558 | if (pointOutsideACD != 0) | 558 | if (pointOutsideACD != 0) |
559 | { | 559 | { |
560 | ClosestPtPointTriangle(p, a, c, d, ref tempResult); | 560 | ClosestPtPointTriangle(p, a, c, d, ref tempResult); |
561 | Vector3 q = tempResult.ClosestPointOnSimplex; | 561 | Vector3 q = tempResult.ClosestPointOnSimplex; |
562 | //convert result bitmask! | 562 | //convert result bitmask! |
563 | 563 | ||
564 | float sqDist = ((Vector3)(q - p)).LengthSquared(); | 564 | float sqDist = ((Vector3)(q - p)).LengthSquared(); |
565 | if (sqDist < bestSqDist) | 565 | if (sqDist < bestSqDist) |
566 | { | 566 | { |
567 | bestSqDist = sqDist; | 567 | bestSqDist = sqDist; |
568 | finalResult.ClosestPointOnSimplex = q; | 568 | finalResult.ClosestPointOnSimplex = q; |
569 | finalResult.UsedVertices.Reset(); | 569 | finalResult.UsedVertices.Reset(); |
570 | finalResult.UsedVertices.UsedVertexA = tempResult.UsedVertices.UsedVertexA; | 570 | finalResult.UsedVertices.UsedVertexA = tempResult.UsedVertices.UsedVertexA; |
571 | finalResult.UsedVertices.UsedVertexC = tempResult.UsedVertices.UsedVertexB; | 571 | finalResult.UsedVertices.UsedVertexC = tempResult.UsedVertices.UsedVertexB; |
572 | finalResult.UsedVertices.UsedVertexD = tempResult.UsedVertices.UsedVertexC; | 572 | finalResult.UsedVertices.UsedVertexD = tempResult.UsedVertices.UsedVertexC; |
573 | finalResult.SetBarycentricCoordinates( | 573 | finalResult.SetBarycentricCoordinates( |
574 | tempResult.BarycentricCoords[VertexA], | 574 | tempResult.BarycentricCoords[VertexA], |
575 | 0, | 575 | 0, |
576 | tempResult.BarycentricCoords[VertexB], | 576 | tempResult.BarycentricCoords[VertexB], |
577 | tempResult.BarycentricCoords[VertexC]); | 577 | tempResult.BarycentricCoords[VertexC]); |
578 | } | 578 | } |
579 | } | 579 | } |
580 | // Repeat test for face adb | 580 | // Repeat test for face adb |
581 | 581 | ||
582 | if (pointOutsideADB != 0) | 582 | if (pointOutsideADB != 0) |
583 | { | 583 | { |
584 | ClosestPtPointTriangle(p, a, d, b, ref tempResult); | 584 | ClosestPtPointTriangle(p, a, d, b, ref tempResult); |
585 | Vector3 q = tempResult.ClosestPointOnSimplex; | 585 | Vector3 q = tempResult.ClosestPointOnSimplex; |
586 | //convert result bitmask! | 586 | //convert result bitmask! |
587 | 587 | ||
588 | float sqDist = ((Vector3)(q - p)).LengthSquared(); | 588 | float sqDist = ((Vector3)(q - p)).LengthSquared(); |
589 | if (sqDist < bestSqDist) | 589 | if (sqDist < bestSqDist) |
590 | { | 590 | { |
591 | bestSqDist = sqDist; | 591 | bestSqDist = sqDist; |
592 | finalResult.ClosestPointOnSimplex = q; | 592 | finalResult.ClosestPointOnSimplex = q; |
593 | finalResult.UsedVertices.Reset(); | 593 | finalResult.UsedVertices.Reset(); |
594 | finalResult.UsedVertices.UsedVertexA = tempResult.UsedVertices.UsedVertexA; | 594 | finalResult.UsedVertices.UsedVertexA = tempResult.UsedVertices.UsedVertexA; |
595 | finalResult.UsedVertices.UsedVertexD = tempResult.UsedVertices.UsedVertexB; | 595 | finalResult.UsedVertices.UsedVertexD = tempResult.UsedVertices.UsedVertexB; |
596 | finalResult.UsedVertices.UsedVertexB = tempResult.UsedVertices.UsedVertexC; | 596 | finalResult.UsedVertices.UsedVertexB = tempResult.UsedVertices.UsedVertexC; |
597 | finalResult.SetBarycentricCoordinates( | 597 | finalResult.SetBarycentricCoordinates( |
598 | tempResult.BarycentricCoords[VertexA], | 598 | tempResult.BarycentricCoords[VertexA], |
599 | tempResult.BarycentricCoords[VertexC], | 599 | tempResult.BarycentricCoords[VertexC], |
600 | 0, | 600 | 0, |
601 | tempResult.BarycentricCoords[VertexB]); | 601 | tempResult.BarycentricCoords[VertexB]); |
602 | 602 | ||
603 | } | 603 | } |
604 | } | 604 | } |
605 | // Repeat test for face bdc | 605 | // Repeat test for face bdc |
606 | 606 | ||
607 | if (pointOutsideBDC != 0) | 607 | if (pointOutsideBDC != 0) |
608 | { | 608 | { |
609 | ClosestPtPointTriangle(p, b, d, c, ref tempResult); | 609 | ClosestPtPointTriangle(p, b, d, c, ref tempResult); |
610 | Vector3 q = tempResult.ClosestPointOnSimplex; | 610 | Vector3 q = tempResult.ClosestPointOnSimplex; |
611 | //convert result bitmask! | 611 | //convert result bitmask! |
612 | float sqDist = ((Vector3)(q - p)).LengthSquared(); | 612 | float sqDist = ((Vector3)(q - p)).LengthSquared(); |
613 | if (sqDist < bestSqDist) | 613 | if (sqDist < bestSqDist) |
614 | { | 614 | { |
615 | bestSqDist = sqDist; | 615 | bestSqDist = sqDist; |
616 | finalResult.ClosestPointOnSimplex = q; | 616 | finalResult.ClosestPointOnSimplex = q; |
617 | finalResult.UsedVertices.Reset(); | 617 | finalResult.UsedVertices.Reset(); |
618 | finalResult.UsedVertices.UsedVertexB = tempResult.UsedVertices.UsedVertexA; | 618 | finalResult.UsedVertices.UsedVertexB = tempResult.UsedVertices.UsedVertexA; |
619 | finalResult.UsedVertices.UsedVertexD = tempResult.UsedVertices.UsedVertexB; | 619 | finalResult.UsedVertices.UsedVertexD = tempResult.UsedVertices.UsedVertexB; |
620 | finalResult.UsedVertices.UsedVertexC = tempResult.UsedVertices.UsedVertexC; | 620 | finalResult.UsedVertices.UsedVertexC = tempResult.UsedVertices.UsedVertexC; |
621 | 621 | ||
622 | finalResult.SetBarycentricCoordinates( | 622 | finalResult.SetBarycentricCoordinates( |
623 | 0, | 623 | 0, |
624 | tempResult.BarycentricCoords[VertexA], | 624 | tempResult.BarycentricCoords[VertexA], |
625 | tempResult.BarycentricCoords[VertexC], | 625 | tempResult.BarycentricCoords[VertexC], |
626 | tempResult.BarycentricCoords[VertexB]); | 626 | tempResult.BarycentricCoords[VertexB]); |
627 | } | 627 | } |
628 | } | 628 | } |
629 | 629 | ||
630 | //help! we ended up full ! | 630 | //help! we ended up full ! |
631 | 631 | ||
632 | if (finalResult.UsedVertices.UsedVertexA && | 632 | if (finalResult.UsedVertices.UsedVertexA && |
633 | finalResult.UsedVertices.UsedVertexB && | 633 | finalResult.UsedVertices.UsedVertexB && |
634 | finalResult.UsedVertices.UsedVertexC && | 634 | finalResult.UsedVertices.UsedVertexC && |
635 | finalResult.UsedVertices.UsedVertexD) | 635 | finalResult.UsedVertices.UsedVertexD) |
636 | { | 636 | { |
637 | return true; | 637 | return true; |
638 | } | 638 | } |
639 | 639 | ||
640 | return true; | 640 | return true; |
641 | } | 641 | } |
642 | } | 642 | } |
643 | } | 643 | } |