diff options
Diffstat (limited to 'libraries/ModifiedBulletX/ModifiedBulletX/Collision/CollisionDispatch/SphereBoxCollisionAlgorithm.cs')
-rw-r--r-- | libraries/ModifiedBulletX/ModifiedBulletX/Collision/CollisionDispatch/SphereBoxCollisionAlgorithm.cs | 540 |
1 files changed, 270 insertions, 270 deletions
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/CollisionDispatch/SphereBoxCollisionAlgorithm.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/CollisionDispatch/SphereBoxCollisionAlgorithm.cs index 8933638..2b4e801 100644 --- a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/CollisionDispatch/SphereBoxCollisionAlgorithm.cs +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/CollisionDispatch/SphereBoxCollisionAlgorithm.cs | |||
@@ -1,270 +1,270 @@ | |||
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 | /// SphereBoxCollisionAlgorithm provides sphere-box collision detection. | 30 | /// SphereBoxCollisionAlgorithm provides sphere-box collision detection. |
31 | /// Other features are frame-coherency (persistent data) and collision response. | 31 | /// Other features are frame-coherency (persistent data) and collision response. |
32 | /// </summary> | 32 | /// </summary> |
33 | public class SphereBoxCollisionAlgorithm : CollisionAlgorithm, IDisposable | 33 | public class SphereBoxCollisionAlgorithm : CollisionAlgorithm, IDisposable |
34 | { | 34 | { |
35 | private bool _ownManifold; | 35 | private bool _ownManifold; |
36 | private PersistentManifold _manifold; | 36 | private PersistentManifold _manifold; |
37 | private bool _isSwapped; | 37 | private bool _isSwapped; |
38 | 38 | ||
39 | public SphereBoxCollisionAlgorithm(PersistentManifold manifold, CollisionAlgorithmConstructionInfo collisionAlgorithmConstructionInfo, CollisionObject collisionObjectA, CollisionObject collisionObjectB, bool isSwapped) | 39 | public SphereBoxCollisionAlgorithm(PersistentManifold manifold, CollisionAlgorithmConstructionInfo collisionAlgorithmConstructionInfo, CollisionObject collisionObjectA, CollisionObject collisionObjectB, bool isSwapped) |
40 | : base(collisionAlgorithmConstructionInfo) | 40 | : base(collisionAlgorithmConstructionInfo) |
41 | { | 41 | { |
42 | _ownManifold = false; | 42 | _ownManifold = false; |
43 | _manifold = manifold; | 43 | _manifold = manifold; |
44 | _isSwapped = isSwapped; | 44 | _isSwapped = isSwapped; |
45 | 45 | ||
46 | CollisionObject sphereObject = _isSwapped ? collisionObjectB : collisionObjectA; | 46 | CollisionObject sphereObject = _isSwapped ? collisionObjectB : collisionObjectA; |
47 | CollisionObject boxObject = _isSwapped ? collisionObjectA : collisionObjectB; | 47 | CollisionObject boxObject = _isSwapped ? collisionObjectA : collisionObjectB; |
48 | 48 | ||
49 | if (_manifold == null && Dispatcher.NeedsCollision(sphereObject, boxObject)) | 49 | if (_manifold == null && Dispatcher.NeedsCollision(sphereObject, boxObject)) |
50 | { | 50 | { |
51 | _manifold = Dispatcher.GetNewManifold(sphereObject, boxObject); | 51 | _manifold = Dispatcher.GetNewManifold(sphereObject, boxObject); |
52 | _ownManifold = true; | 52 | _ownManifold = true; |
53 | } | 53 | } |
54 | } | 54 | } |
55 | 55 | ||
56 | public float GetSphereDistance(CollisionObject boxObject, out Vector3 pointOnBox, out Vector3 pointOnSphere, Vector3 sphereCenter, float radius) | 56 | public float GetSphereDistance(CollisionObject boxObject, out Vector3 pointOnBox, out Vector3 pointOnSphere, Vector3 sphereCenter, float radius) |
57 | { | 57 | { |
58 | pointOnBox = new Vector3(); | 58 | pointOnBox = new Vector3(); |
59 | pointOnSphere = new Vector3(); | 59 | pointOnSphere = new Vector3(); |
60 | 60 | ||
61 | float margins; | 61 | float margins; |
62 | Vector3[] bounds = new Vector3[2]; | 62 | Vector3[] bounds = new Vector3[2]; |
63 | BoxShape boxShape = boxObject.CollisionShape as BoxShape; | 63 | BoxShape boxShape = boxObject.CollisionShape as BoxShape; |
64 | 64 | ||
65 | bounds[0] = -boxShape.HalfExtents; | 65 | bounds[0] = -boxShape.HalfExtents; |
66 | bounds[1] = boxShape.HalfExtents; | 66 | bounds[1] = boxShape.HalfExtents; |
67 | 67 | ||
68 | margins = boxShape.Margin; //also add sphereShape margin? | 68 | margins = boxShape.Margin; //also add sphereShape margin? |
69 | 69 | ||
70 | Matrix m44T = boxObject.WorldTransform; | 70 | Matrix m44T = boxObject.WorldTransform; |
71 | 71 | ||
72 | Vector3[] boundsVec = new Vector3[2]; | 72 | Vector3[] boundsVec = new Vector3[2]; |
73 | float penetration; | 73 | float penetration; |
74 | 74 | ||
75 | boundsVec[0] = bounds[0]; | 75 | boundsVec[0] = bounds[0]; |
76 | boundsVec[1] = bounds[1]; | 76 | boundsVec[1] = bounds[1]; |
77 | 77 | ||
78 | Vector3 marginsVec = new Vector3(margins, margins, margins); | 78 | Vector3 marginsVec = new Vector3(margins, margins, margins); |
79 | 79 | ||
80 | // add margins | 80 | // add margins |
81 | bounds[0] += marginsVec; | 81 | bounds[0] += marginsVec; |
82 | bounds[1] -= marginsVec; | 82 | bounds[1] -= marginsVec; |
83 | 83 | ||
84 | ///////////////////////////////////////////////// | 84 | ///////////////////////////////////////////////// |
85 | 85 | ||
86 | Vector3 tmp, prel, normal, v3P; | 86 | Vector3 tmp, prel, normal, v3P; |
87 | Vector3[] n = new Vector3[6]; | 87 | Vector3[] n = new Vector3[6]; |
88 | float sep = 10000000.0f, sepThis; | 88 | float sep = 10000000.0f, sepThis; |
89 | 89 | ||
90 | n[0] = new Vector3(-1.0f, 0.0f, 0.0f); | 90 | n[0] = new Vector3(-1.0f, 0.0f, 0.0f); |
91 | n[1] = new Vector3(0.0f, -1.0f, 0.0f); | 91 | n[1] = new Vector3(0.0f, -1.0f, 0.0f); |
92 | n[2] = new Vector3(0.0f, 0.0f, -1.0f); | 92 | n[2] = new Vector3(0.0f, 0.0f, -1.0f); |
93 | n[3] = new Vector3(1.0f, 0.0f, 0.0f); | 93 | n[3] = new Vector3(1.0f, 0.0f, 0.0f); |
94 | n[4] = new Vector3(0.0f, 1.0f, 0.0f); | 94 | n[4] = new Vector3(0.0f, 1.0f, 0.0f); |
95 | n[5] = new Vector3(0.0f, 0.0f, 1.0f); | 95 | n[5] = new Vector3(0.0f, 0.0f, 1.0f); |
96 | 96 | ||
97 | // convert point in local space | 97 | // convert point in local space |
98 | prel = MathHelper.InvXForm(m44T, sphereCenter); | 98 | prel = MathHelper.InvXForm(m44T, sphereCenter); |
99 | 99 | ||
100 | bool found = false; | 100 | bool found = false; |
101 | 101 | ||
102 | v3P = prel; | 102 | v3P = prel; |
103 | 103 | ||
104 | for (int i = 0; i < 6; i++) | 104 | for (int i = 0; i < 6; i++) |
105 | { | 105 | { |
106 | int j = i < 3 ? 0 : 1; | 106 | int j = i < 3 ? 0 : 1; |
107 | if ((sepThis = (Vector3.Dot(v3P - bounds[j], n[i]))) > 0.0f) | 107 | if ((sepThis = (Vector3.Dot(v3P - bounds[j], n[i]))) > 0.0f) |
108 | { | 108 | { |
109 | v3P = v3P - n[i] * sepThis; | 109 | v3P = v3P - n[i] * sepThis; |
110 | found = true; | 110 | found = true; |
111 | } | 111 | } |
112 | } | 112 | } |
113 | 113 | ||
114 | // | 114 | // |
115 | 115 | ||
116 | if (found) | 116 | if (found) |
117 | { | 117 | { |
118 | bounds[0] = boundsVec[0]; | 118 | bounds[0] = boundsVec[0]; |
119 | bounds[1] = boundsVec[1]; | 119 | bounds[1] = boundsVec[1]; |
120 | 120 | ||
121 | normal = Vector3.Normalize(prel - v3P); | 121 | normal = Vector3.Normalize(prel - v3P); |
122 | pointOnBox = v3P + normal * margins; | 122 | pointOnBox = v3P + normal * margins; |
123 | pointOnSphere = prel - normal * radius; | 123 | pointOnSphere = prel - normal * radius; |
124 | 124 | ||
125 | if ((Vector3.Dot(pointOnSphere - pointOnBox, normal)) > 0.0f) | 125 | if ((Vector3.Dot(pointOnSphere - pointOnBox, normal)) > 0.0f) |
126 | { | 126 | { |
127 | return 1.0f; | 127 | return 1.0f; |
128 | } | 128 | } |
129 | 129 | ||
130 | // transform back in world space | 130 | // transform back in world space |
131 | tmp = MathHelper.MatrixToVector(m44T, pointOnBox); | 131 | tmp = MathHelper.MatrixToVector(m44T, pointOnBox); |
132 | pointOnBox = tmp; | 132 | pointOnBox = tmp; |
133 | tmp = MathHelper.MatrixToVector(m44T, pointOnSphere); | 133 | tmp = MathHelper.MatrixToVector(m44T, pointOnSphere); |
134 | pointOnSphere = tmp; | 134 | pointOnSphere = tmp; |
135 | float seps2 = (pointOnBox - pointOnSphere).LengthSquared(); | 135 | float seps2 = (pointOnBox - pointOnSphere).LengthSquared(); |
136 | 136 | ||
137 | //if this fails, fallback into deeper penetration case, below | 137 | //if this fails, fallback into deeper penetration case, below |
138 | if (seps2 > MathHelper.Epsilon) | 138 | if (seps2 > MathHelper.Epsilon) |
139 | { | 139 | { |
140 | sep = -(float)Math.Sqrt(seps2); | 140 | sep = -(float)Math.Sqrt(seps2); |
141 | normal = (pointOnBox - pointOnSphere); | 141 | normal = (pointOnBox - pointOnSphere); |
142 | normal *= 1f / sep; | 142 | normal *= 1f / sep; |
143 | } | 143 | } |
144 | return sep; | 144 | return sep; |
145 | } | 145 | } |
146 | 146 | ||
147 | ////////////////////////////////////////////////// | 147 | ////////////////////////////////////////////////// |
148 | // Deep penetration case | 148 | // Deep penetration case |
149 | 149 | ||
150 | penetration = GetSpherePenetration(boxObject, ref pointOnBox, ref pointOnSphere, sphereCenter, radius, bounds[0], bounds[1]); | 150 | penetration = GetSpherePenetration(boxObject, ref pointOnBox, ref pointOnSphere, sphereCenter, radius, bounds[0], bounds[1]); |
151 | 151 | ||
152 | bounds[0] = boundsVec[0]; | 152 | bounds[0] = boundsVec[0]; |
153 | bounds[1] = boundsVec[1]; | 153 | bounds[1] = boundsVec[1]; |
154 | 154 | ||
155 | if (penetration <= 0.0f) | 155 | if (penetration <= 0.0f) |
156 | return (penetration - margins); | 156 | return (penetration - margins); |
157 | else | 157 | else |
158 | return 1.0f; | 158 | return 1.0f; |
159 | } | 159 | } |
160 | 160 | ||
161 | public float GetSpherePenetration(CollisionObject boxObject, ref Vector3 pointOnBox, ref Vector3 pointOnSphere, Vector3 sphereCenter, float radius, Vector3 aabbMin, Vector3 aabbMax) | 161 | public float GetSpherePenetration(CollisionObject boxObject, ref Vector3 pointOnBox, ref Vector3 pointOnSphere, Vector3 sphereCenter, float radius, Vector3 aabbMin, Vector3 aabbMax) |
162 | { | 162 | { |
163 | Vector3[] bounds = new Vector3[2]; | 163 | Vector3[] bounds = new Vector3[2]; |
164 | 164 | ||
165 | bounds[0] = aabbMin; | 165 | bounds[0] = aabbMin; |
166 | bounds[1] = aabbMax; | 166 | bounds[1] = aabbMax; |
167 | 167 | ||
168 | Vector3 p0 = new Vector3(), tmp, prel, normal = new Vector3(); | 168 | Vector3 p0 = new Vector3(), tmp, prel, normal = new Vector3(); |
169 | Vector3[] n = new Vector3[6]; | 169 | Vector3[] n = new Vector3[6]; |
170 | float sep = -10000000.0f, sepThis; | 170 | float sep = -10000000.0f, sepThis; |
171 | 171 | ||
172 | n[0] = new Vector3(-1.0f, 0.0f, 0.0f); | 172 | n[0] = new Vector3(-1.0f, 0.0f, 0.0f); |
173 | n[1] = new Vector3(0.0f, -1.0f, 0.0f); | 173 | n[1] = new Vector3(0.0f, -1.0f, 0.0f); |
174 | n[2] = new Vector3(0.0f, 0.0f, -1.0f); | 174 | n[2] = new Vector3(0.0f, 0.0f, -1.0f); |
175 | n[3] = new Vector3(1.0f, 0.0f, 0.0f); | 175 | n[3] = new Vector3(1.0f, 0.0f, 0.0f); |
176 | n[4] = new Vector3(0.0f, 1.0f, 0.0f); | 176 | n[4] = new Vector3(0.0f, 1.0f, 0.0f); |
177 | n[5] = new Vector3(0.0f, 0.0f, 1.0f); | 177 | n[5] = new Vector3(0.0f, 0.0f, 1.0f); |
178 | 178 | ||
179 | Matrix m44T = boxObject.WorldTransform; | 179 | Matrix m44T = boxObject.WorldTransform; |
180 | 180 | ||
181 | // convert point in local space | 181 | // convert point in local space |
182 | prel = MathHelper.InvXForm(m44T, sphereCenter); | 182 | prel = MathHelper.InvXForm(m44T, sphereCenter); |
183 | 183 | ||
184 | /////////// | 184 | /////////// |
185 | 185 | ||
186 | for (int i = 0; i < 6; i++) | 186 | for (int i = 0; i < 6; i++) |
187 | { | 187 | { |
188 | int j = i < 3 ? 0 : 1; | 188 | int j = i < 3 ? 0 : 1; |
189 | if ((sepThis = (Vector3.Dot(prel - bounds[j], n[i])) - radius) > 0.0f) return 1.0f; | 189 | if ((sepThis = (Vector3.Dot(prel - bounds[j], n[i])) - radius) > 0.0f) return 1.0f; |
190 | if (sepThis > sep) | 190 | if (sepThis > sep) |
191 | { | 191 | { |
192 | p0 = bounds[j]; | 192 | p0 = bounds[j]; |
193 | normal = n[i]; | 193 | normal = n[i]; |
194 | sep = sepThis; | 194 | sep = sepThis; |
195 | } | 195 | } |
196 | } | 196 | } |
197 | 197 | ||
198 | pointOnBox = prel - normal * (Vector3.Dot(normal, (prel - p0))); | 198 | pointOnBox = prel - normal * (Vector3.Dot(normal, (prel - p0))); |
199 | pointOnSphere = pointOnBox + normal * sep; | 199 | pointOnSphere = pointOnBox + normal * sep; |
200 | 200 | ||
201 | // transform back in world space | 201 | // transform back in world space |
202 | tmp = MathHelper.MatrixToVector(m44T, pointOnBox); | 202 | tmp = MathHelper.MatrixToVector(m44T, pointOnBox); |
203 | pointOnBox = tmp; | 203 | pointOnBox = tmp; |
204 | tmp = MathHelper.MatrixToVector(m44T, pointOnSphere); | 204 | tmp = MathHelper.MatrixToVector(m44T, pointOnSphere); |
205 | pointOnSphere = tmp; | 205 | pointOnSphere = tmp; |
206 | normal = Vector3.Normalize(pointOnBox - pointOnSphere); | 206 | normal = Vector3.Normalize(pointOnBox - pointOnSphere); |
207 | 207 | ||
208 | return sep; | 208 | return sep; |
209 | } | 209 | } |
210 | 210 | ||
211 | public override void ProcessCollision(CollisionObject bodyA, CollisionObject bodyB, DispatcherInfo dispatchInfo, ManifoldResult resultOut) | 211 | public override void ProcessCollision(CollisionObject bodyA, CollisionObject bodyB, DispatcherInfo dispatchInfo, ManifoldResult resultOut) |
212 | { | 212 | { |
213 | if (_manifold == null) | 213 | if (_manifold == null) |
214 | return; | 214 | return; |
215 | 215 | ||
216 | CollisionObject sphereObject = _isSwapped ? bodyB : bodyA; | 216 | CollisionObject sphereObject = _isSwapped ? bodyB : bodyA; |
217 | CollisionObject boxObject = _isSwapped ? bodyA : bodyB; | 217 | CollisionObject boxObject = _isSwapped ? bodyA : bodyB; |
218 | 218 | ||
219 | SphereShape sphereA = sphereObject.CollisionShape as SphereShape; | 219 | SphereShape sphereA = sphereObject.CollisionShape as SphereShape; |
220 | 220 | ||
221 | Vector3 pOnBox, pOnSphere; | 221 | Vector3 pOnBox, pOnSphere; |
222 | Vector3 sphereCenter = sphereObject.WorldTransform.Translation; | 222 | Vector3 sphereCenter = sphereObject.WorldTransform.Translation; |
223 | float radius = sphereA.Radius; | 223 | float radius = sphereA.Radius; |
224 | 224 | ||
225 | float dist = GetSphereDistance(boxObject, out pOnBox, out pOnSphere, sphereCenter, radius); | 225 | float dist = GetSphereDistance(boxObject, out pOnBox, out pOnSphere, sphereCenter, radius); |
226 | 226 | ||
227 | if (dist < MathHelper.Epsilon) | 227 | if (dist < MathHelper.Epsilon) |
228 | { | 228 | { |
229 | Vector3 normalOnSurfaceB = Vector3.Normalize(pOnBox - pOnSphere); | 229 | Vector3 normalOnSurfaceB = Vector3.Normalize(pOnBox - pOnSphere); |
230 | 230 | ||
231 | // report a contact. internally this will be kept persistent, and contact reduction is done | 231 | // report a contact. internally this will be kept persistent, and contact reduction is done |
232 | resultOut.SetPersistentManifold(_manifold); | 232 | resultOut.SetPersistentManifold(_manifold); |
233 | resultOut.AddContactPoint(normalOnSurfaceB, pOnBox, dist); | 233 | resultOut.AddContactPoint(normalOnSurfaceB, pOnBox, dist); |
234 | } | 234 | } |
235 | } | 235 | } |
236 | 236 | ||
237 | public override float CalculateTimeOfImpact(CollisionObject collisionObjectA, CollisionObject collisionObjectB, DispatcherInfo dispatchInfo, ManifoldResult resultOut) | 237 | public override float CalculateTimeOfImpact(CollisionObject collisionObjectA, CollisionObject collisionObjectB, DispatcherInfo dispatchInfo, ManifoldResult resultOut) |
238 | { | 238 | { |
239 | //not yet | 239 | //not yet |
240 | return 1; | 240 | return 1; |
241 | } | 241 | } |
242 | 242 | ||
243 | public class CreateFunc : CollisionAlgorithmCreateFunction | 243 | public class CreateFunc : CollisionAlgorithmCreateFunction |
244 | { | 244 | { |
245 | public override CollisionAlgorithm CreateCollisionAlgorithm(CollisionAlgorithmConstructionInfo collisionAlgorithmConstructionInfo, CollisionObject bodyA, CollisionObject bodyB) | 245 | public override CollisionAlgorithm CreateCollisionAlgorithm(CollisionAlgorithmConstructionInfo collisionAlgorithmConstructionInfo, CollisionObject bodyA, CollisionObject bodyB) |
246 | { | 246 | { |
247 | if (!IsSwapped) | 247 | if (!IsSwapped) |
248 | return new SphereBoxCollisionAlgorithm(null, collisionAlgorithmConstructionInfo, bodyA, bodyB, false); | 248 | return new SphereBoxCollisionAlgorithm(null, collisionAlgorithmConstructionInfo, bodyA, bodyB, false); |
249 | else | 249 | else |
250 | return new SphereBoxCollisionAlgorithm(null, collisionAlgorithmConstructionInfo, bodyA, bodyB, true); | 250 | return new SphereBoxCollisionAlgorithm(null, collisionAlgorithmConstructionInfo, bodyA, bodyB, true); |
251 | } | 251 | } |
252 | } | 252 | } |
253 | 253 | ||
254 | #region IDisposable Members | 254 | #region IDisposable Members |
255 | public void Dispose() | 255 | public void Dispose() |
256 | { | 256 | { |
257 | Dispose(true); | 257 | Dispose(true); |
258 | } | 258 | } |
259 | 259 | ||
260 | public void Dispose(bool disposing) | 260 | public void Dispose(bool disposing) |
261 | { | 261 | { |
262 | if (disposing && _ownManifold) | 262 | if (disposing && _ownManifold) |
263 | { | 263 | { |
264 | if (_manifold != null) | 264 | if (_manifold != null) |
265 | Dispatcher.ReleaseManifold(_manifold); | 265 | Dispatcher.ReleaseManifold(_manifold); |
266 | } | 266 | } |
267 | } | 267 | } |
268 | #endregion | 268 | #endregion |
269 | } | 269 | } |
270 | } | 270 | } |