diff options
Diffstat (limited to 'libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpa.cs')
-rw-r--r-- | libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpa.cs | 633 |
1 files changed, 633 insertions, 0 deletions
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpa.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpa.cs new file mode 100644 index 0000000..50ae7ab --- /dev/null +++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/NarrowPhaseCollision/GjkEpa.cs | |||
@@ -0,0 +1,633 @@ | |||
1 | /* | ||
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 | ||
4 | |||
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 | ||
7 | arising from the use of this software. | ||
8 | |||
9 | Permission is granted to anyone to use this software for any purpose, | ||
10 | including commercial applications, and to alter it and redistribute it | ||
11 | freely, subject to the following restrictions: | ||
12 | |||
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 | ||
15 | in a product, an acknowledgment in the product documentation would be | ||
16 | appreciated but is not required. | ||
17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
18 | misrepresented as being the original software. | ||
19 | 3. This notice may not be removed or altered from any source distribution. | ||
20 | */ | ||
21 | |||
22 | using System; | ||
23 | using System.Collections.Generic; | ||
24 | using System.Text; | ||
25 | using MonoXnaCompactMaths; | ||
26 | |||
27 | namespace XnaDevRu.BulletX | ||
28 | { | ||
29 | /// <summary> | ||
30 | /// GJK-EPA collision solver by Nathanael Presson | ||
31 | /// Nov.2006 | ||
32 | /// </summary> | ||
33 | public class GjkEpa | ||
34 | { | ||
35 | //private static readonly int _precision = 1 /* U(sizeof(F) == 4)*/; | ||
36 | |||
37 | private static readonly float _infinity = MathHelper.Infinity; | ||
38 | //private static readonly float _pi = (float)Math.PI; | ||
39 | private static readonly float _twoPi = (float)(Math.PI * 2); | ||
40 | |||
41 | private static readonly int _gjkMaxIterations = 128; | ||
42 | private static readonly int _gjkHashSize = 1 << 6; | ||
43 | private static readonly int _gjkHashMask = _gjkHashSize - 1; | ||
44 | private static readonly float _gjkInSimplexEpsilon = 0.0001f; | ||
45 | private static readonly float _gjkSquareInSimplexEpsilon = _gjkInSimplexEpsilon * _gjkInSimplexEpsilon; | ||
46 | |||
47 | private static readonly int _epaMaxIterations = 256; | ||
48 | private static readonly float _epaInFaceEpsilon = 0.01f; | ||
49 | private static readonly float _epaAccuracy = 0.001f; | ||
50 | |||
51 | public static float EpaAccuracy { get { return _epaAccuracy; } } | ||
52 | |||
53 | private static float Abs(float v) { return (v < 0 ? -v : v); } | ||
54 | private static float Sign(float v) { return (v < 0 ? -1 : 1); } | ||
55 | |||
56 | static void Swap<T>(ref T a, ref T b) | ||
57 | { | ||
58 | T t = a; | ||
59 | a = b; | ||
60 | b = t; | ||
61 | } | ||
62 | |||
63 | public class Gjk | ||
64 | { | ||
65 | public class MinkowskiVertice | ||
66 | { | ||
67 | private Vector3 _vertice; /* Minkowski vertice */ | ||
68 | private Vector3 _ray; /* Ray */ | ||
69 | |||
70 | public Vector3 Vertice { get { return _vertice; } set { _vertice = value; } } | ||
71 | public Vector3 Ray { get { return _ray; } set { _ray = value; } } | ||
72 | } | ||
73 | public class He | ||
74 | { | ||
75 | private Vector3 _ray; | ||
76 | private He _next; | ||
77 | |||
78 | public He Next { get { return _next; } set { _next = value; } } | ||
79 | public Vector3 Ray { get { return _ray; } set { _ray = value; } } | ||
80 | } | ||
81 | |||
82 | private He[] _table = new He[_gjkHashSize]; | ||
83 | private Matrix[] _wrotations = new Matrix[2]; | ||
84 | private Vector3[] _positions = new Vector3[2]; | ||
85 | private ConvexShape[] _shapes = new ConvexShape[2]; | ||
86 | private MinkowskiVertice[] _simplex = new MinkowskiVertice[5]; | ||
87 | private Vector3 _ray; | ||
88 | private int _order; | ||
89 | private int _iterations; | ||
90 | private float _margin; | ||
91 | private bool _failed; | ||
92 | |||
93 | public Gjk(Matrix wrotationA, Vector3 positionA, ConvexShape shapeA, | ||
94 | Matrix wrotationB, Vector3 positionB, ConvexShape shapeB) | ||
95 | : this(wrotationA, positionA, shapeA, wrotationB, positionB, shapeB, 0) { } | ||
96 | |||
97 | public Gjk(Matrix wrotationA, Vector3 positionA, ConvexShape shapeA, | ||
98 | Matrix wrotationB, Vector3 positionB, ConvexShape shapeB, | ||
99 | float pmargin) | ||
100 | { | ||
101 | for (int i = 0; i < _simplex.Length; i++) | ||
102 | _simplex[i] = new MinkowskiVertice(); | ||
103 | |||
104 | for (int i = 0; i < _wrotations.Length; i++) | ||
105 | _wrotations[i] = new Matrix(); | ||
106 | |||
107 | for (int i = 0; i < _positions.Length; i++) | ||
108 | _positions[i] = new Vector3(); | ||
109 | |||
110 | _wrotations[0] = wrotationA; _positions[0] = positionA; | ||
111 | _shapes[0] = shapeA; | ||
112 | _wrotations[0].Translation = Vector3.Zero; | ||
113 | _wrotations[1] = wrotationB; _positions[1] = positionB; | ||
114 | _shapes[1] = shapeB; | ||
115 | _wrotations[1].Translation = Vector3.Zero; | ||
116 | //sablock = sa->BeginBlock(); | ||
117 | _margin = pmargin; | ||
118 | _failed = false; | ||
119 | } | ||
120 | |||
121 | public bool Failed { get { return _failed; } } | ||
122 | public int Iterations { get { return _iterations; } } | ||
123 | public int Order { get { return _order; } } | ||
124 | public MinkowskiVertice[] Simplex { get { return _simplex; } } | ||
125 | |||
126 | public int Hash(Vector3 v) | ||
127 | { | ||
128 | int h = ((int)(v.X * 15461) ^ (int)(v.Y * 83003) ^ (int)(v.Z * 15473)); | ||
129 | return (h * 169639) & _gjkHashMask; | ||
130 | } | ||
131 | |||
132 | public bool FetchSupport() | ||
133 | { | ||
134 | int h = Hash(_ray); | ||
135 | He e = _table[h]; | ||
136 | while (e != null) | ||
137 | { | ||
138 | if (e.Ray == _ray) | ||
139 | { | ||
140 | --_order; | ||
141 | return (false); | ||
142 | } | ||
143 | else e = e.Next; | ||
144 | } | ||
145 | e = new He(); | ||
146 | e.Ray = _ray; | ||
147 | e.Next = _table[h]; | ||
148 | _table[h] = e; | ||
149 | Support(_ray, ref _simplex[++_order]); | ||
150 | return (Vector3.Dot(_ray, _simplex[_order].Vertice) > 0); | ||
151 | } | ||
152 | |||
153 | public Vector3 LocalSupport(Vector3 d, int i) | ||
154 | { | ||
155 | Matrix m = _wrotations[i]; | ||
156 | m.Translation = Vector3.Zero; | ||
157 | Vector3 vtx = Vector3.TransformNormal(d, m); | ||
158 | Vector3 result = MathHelper.MatrixToVector(_wrotations[i], _shapes[i].LocalGetSupportingVertex(vtx)); | ||
159 | return (result + _positions[i]); | ||
160 | } | ||
161 | |||
162 | public void Support(Vector3 d, ref MinkowskiVertice v) | ||
163 | { | ||
164 | v.Ray = d; | ||
165 | v.Vertice = LocalSupport(d, 0) - LocalSupport(-d, 1) + d * _margin; | ||
166 | } | ||
167 | |||
168 | public bool SolveSimplex2(Vector3 ao, Vector3 ab) | ||
169 | { | ||
170 | if (Vector3.Dot(ab, ao) >= 0) | ||
171 | { | ||
172 | Vector3 cabo = Vector3.Cross(ab, ao); | ||
173 | if (cabo.LengthSquared() > _gjkSquareInSimplexEpsilon) | ||
174 | { _ray = Vector3.Cross(cabo, ab); } | ||
175 | else | ||
176 | { return true; } | ||
177 | } | ||
178 | else | ||
179 | { | ||
180 | _order = 0; | ||
181 | _simplex[0].Ray = _simplex[1].Ray; | ||
182 | _simplex[0].Vertice = _simplex[1].Vertice; | ||
183 | |||
184 | _ray = ao; | ||
185 | } | ||
186 | return false; | ||
187 | } | ||
188 | |||
189 | public bool SolveSimplex3(Vector3 ao, Vector3 ab, Vector3 ac) | ||
190 | { | ||
191 | return (SolveSimplex3a(ao, ab, ac, Vector3.Cross(ab, ac))); | ||
192 | } | ||
193 | |||
194 | public bool SolveSimplex3a(Vector3 ao, Vector3 ab, Vector3 ac, Vector3 cabc) | ||
195 | { | ||
196 | if ((Vector3.Dot(Vector3.Cross(cabc, ab), ao)) < -_gjkInSimplexEpsilon) | ||
197 | { | ||
198 | _order = 1; | ||
199 | _simplex[0].Vertice = _simplex[1].Vertice; | ||
200 | _simplex[0].Ray = _simplex[1].Ray; | ||
201 | |||
202 | _simplex[1].Vertice = _simplex[2].Vertice; | ||
203 | _simplex[1].Ray = _simplex[2].Ray; | ||
204 | |||
205 | return (SolveSimplex2(ao, ab)); | ||
206 | } | ||
207 | else if (Vector3.Dot(Vector3.Cross(cabc, ac), ao) > +_gjkInSimplexEpsilon) | ||
208 | { | ||
209 | _order = 1; | ||
210 | _simplex[1].Vertice = _simplex[2].Vertice; | ||
211 | _simplex[1].Ray = _simplex[2].Ray; | ||
212 | |||
213 | return (SolveSimplex2(ao, ac)); | ||
214 | } | ||
215 | else | ||
216 | { | ||
217 | float d = Vector3.Dot(cabc, ao); | ||
218 | if (Abs(d) > _gjkInSimplexEpsilon) | ||
219 | { | ||
220 | if (d > 0) | ||
221 | { _ray = cabc; } | ||
222 | else | ||
223 | { _ray = -cabc; Swap<MinkowskiVertice>(ref _simplex[0], ref _simplex[1]); } | ||
224 | return (false); | ||
225 | } | ||
226 | else return (true); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | public bool SolveSimplex4(Vector3 ao, Vector3 ab, Vector3 ac, Vector3 ad) | ||
231 | { | ||
232 | Vector3 crs; | ||
233 | if (Vector3.Dot((crs = Vector3.Cross(ab, ac)), ao) > _gjkInSimplexEpsilon) | ||
234 | { | ||
235 | _order = 2; | ||
236 | _simplex[0].Vertice = _simplex[1].Vertice; | ||
237 | _simplex[0].Ray = _simplex[1].Ray; | ||
238 | |||
239 | _simplex[1].Vertice = _simplex[2].Vertice; | ||
240 | _simplex[1].Ray = _simplex[2].Ray; | ||
241 | |||
242 | _simplex[2].Vertice = _simplex[3].Vertice; | ||
243 | _simplex[2].Ray = _simplex[3].Ray; | ||
244 | |||
245 | return (SolveSimplex3a(ao, ab, ac, crs)); | ||
246 | } | ||
247 | else if (Vector3.Dot((crs = Vector3.Cross(ac, ad)), ao) > _gjkInSimplexEpsilon) | ||
248 | { | ||
249 | _order = 2; | ||
250 | _simplex[2].Vertice = _simplex[3].Vertice; | ||
251 | _simplex[2].Ray = _simplex[3].Ray; | ||
252 | |||
253 | return (SolveSimplex3a(ao, ac, ad, crs)); | ||
254 | } | ||
255 | else if (Vector3.Dot((crs = Vector3.Cross(ad, ab)), ao) > _gjkInSimplexEpsilon) | ||
256 | { | ||
257 | _order = 2; | ||
258 | |||
259 | _simplex[1].Vertice = _simplex[0].Vertice; | ||
260 | _simplex[1].Ray = _simplex[0].Ray; | ||
261 | |||
262 | _simplex[0].Vertice = _simplex[2].Vertice; | ||
263 | _simplex[0].Ray = _simplex[2].Ray; | ||
264 | |||
265 | _simplex[2].Vertice = _simplex[3].Vertice; | ||
266 | _simplex[2].Ray = _simplex[3].Ray; | ||
267 | |||
268 | return (SolveSimplex3a(ao, ad, ab, crs)); | ||
269 | } | ||
270 | else return (true); | ||
271 | } | ||
272 | |||
273 | public bool SearchOrigin() | ||
274 | { | ||
275 | return SearchOrigin(new Vector3(1, 0, 0)); | ||
276 | } | ||
277 | |||
278 | public bool SearchOrigin(Vector3 initray) | ||
279 | { | ||
280 | _iterations = 0; | ||
281 | unchecked | ||
282 | { | ||
283 | _order = (int)(-1); | ||
284 | } | ||
285 | _failed = false; | ||
286 | _ray = Vector3.Normalize(initray); | ||
287 | |||
288 | //ClearMemory(table, sizeof(void*) * GJK_hashsize); | ||
289 | for (int i = 0; i < _table.Length; i++) | ||
290 | _table[i] = null; | ||
291 | FetchSupport(); | ||
292 | _ray = -_simplex[0].Vertice; | ||
293 | for (; _iterations < _gjkMaxIterations; ++_iterations) | ||
294 | { | ||
295 | float rl = _ray.Length(); | ||
296 | _ray /= rl > 0 ? rl : 1; | ||
297 | if (FetchSupport()) | ||
298 | { | ||
299 | bool found = (false); | ||
300 | switch (_order) | ||
301 | { | ||
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; | ||
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 | } | ||
306 | if (found) return (true); | ||
307 | } | ||
308 | else return (false); | ||
309 | } | ||
310 | _failed = true; | ||
311 | return (false); | ||
312 | } | ||
313 | |||
314 | public bool EncloseOrigin() | ||
315 | { | ||
316 | switch (_order) | ||
317 | { | ||
318 | /* Point */ | ||
319 | case 0: break; | ||
320 | /* Line */ | ||
321 | case 1: | ||
322 | Vector3 ab = _simplex[1].Vertice - _simplex[0].Vertice; | ||
323 | Vector3[] b ={ Vector3.Cross(ab, new Vector3(1, 0, 0)), | ||
324 | Vector3.Cross(ab, new Vector3(0, 1, 0)), | ||
325 | Vector3.Cross(ab, new Vector3(0, 0, 1)) }; | ||
326 | float[] m ={ b[0].LengthSquared(), b[1].LengthSquared(), b[2].LengthSquared() }; | ||
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]; | ||
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); | ||
331 | Support(Vector3.Normalize(w), ref _simplex[3]); w = Vector3.TransformNormal(w, r); | ||
332 | _order = 4; | ||
333 | return true; | ||
334 | /* Triangle */ | ||
335 | case 2: | ||
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]); | ||
338 | Support(-n, ref _simplex[4]); | ||
339 | _order = 4; | ||
340 | return true; | ||
341 | /* Tetrahedron */ | ||
342 | case 3: return (true); | ||
343 | /* Hexahedron */ | ||
344 | case 4: return (true); | ||
345 | } | ||
346 | return (false); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | public class Epa | ||
351 | { | ||
352 | public class Face | ||
353 | { | ||
354 | public Gjk.MinkowskiVertice[] _vertices = new Gjk.MinkowskiVertice[3]; | ||
355 | public Face[] _faces = new Face[3]; | ||
356 | public int[] _e = new int[3]; | ||
357 | public Vector3 _n; | ||
358 | public float _d; | ||
359 | public int _mark; | ||
360 | public Face _prev; | ||
361 | public Face _next; | ||
362 | } | ||
363 | |||
364 | private Gjk _gjk; | ||
365 | private Face _root; | ||
366 | private int _nfaces; | ||
367 | private int _iterations; | ||
368 | private Vector3[,] _features = new Vector3[2, 3]; | ||
369 | private Vector3[] _nearest = new Vector3[2]; | ||
370 | private Vector3 _normal; | ||
371 | private float _depth; | ||
372 | private bool _failed; | ||
373 | |||
374 | public Epa(Gjk gjk) | ||
375 | { | ||
376 | this._gjk = gjk; | ||
377 | } | ||
378 | |||
379 | public bool Failed { get { return _failed; } } | ||
380 | public int Iterations { get { return _iterations; } } | ||
381 | public Vector3 Normal { get { return _normal; } } | ||
382 | public Vector3[] Nearest { get { return _nearest; } } | ||
383 | |||
384 | public Vector3 GetCoordinates(Face face) | ||
385 | { | ||
386 | Vector3 o = face._n * -face._d; | ||
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(), | ||
389 | Vector3.Cross(face._vertices[2].Vertice - o, face._vertices[0].Vertice - o).Length()}; | ||
390 | float sm = a[0] + a[1] + a[2]; | ||
391 | return (new Vector3(a[1], a[2], a[0]) / (sm > 0 ? sm : 1)); | ||
392 | } | ||
393 | |||
394 | public Face FindBest() | ||
395 | { | ||
396 | Face bf = null; | ||
397 | if (_root != null) | ||
398 | { | ||
399 | Face cf = _root; | ||
400 | float bd = _infinity; | ||
401 | do | ||
402 | { | ||
403 | if (cf._d < bd) { bd = cf._d; bf = cf; } | ||
404 | } while (null != (cf = cf._next)); | ||
405 | } | ||
406 | return bf; | ||
407 | } | ||
408 | |||
409 | public bool Set(ref Face f, Gjk.MinkowskiVertice a, Gjk.MinkowskiVertice b, Gjk.MinkowskiVertice c) | ||
410 | { | ||
411 | Vector3 nrm = Vector3.Cross(b.Vertice - a.Vertice, c.Vertice - a.Vertice); | ||
412 | float len = nrm.Length(); | ||
413 | bool valid = (Vector3.Dot(Vector3.Cross(a.Vertice, b.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); | ||
416 | f._vertices[0] = a; | ||
417 | f._vertices[1] = b; | ||
418 | f._vertices[2] = c; | ||
419 | f._mark = 0; | ||
420 | f._n = nrm / (len > 0 ? len : _infinity); | ||
421 | f._d = Max(0, -Vector3.Dot(f._n, a.Vertice)); | ||
422 | return valid; | ||
423 | } | ||
424 | |||
425 | public Face NewFace(Gjk.MinkowskiVertice a, Gjk.MinkowskiVertice b, Gjk.MinkowskiVertice c) | ||
426 | { | ||
427 | Face pf = new Face(); | ||
428 | if (Set(ref pf, a, b, c)) | ||
429 | { | ||
430 | if (_root != null) _root._prev = pf; | ||
431 | pf._prev = null; | ||
432 | pf._next = _root; | ||
433 | _root = pf; | ||
434 | ++_nfaces; | ||
435 | } | ||
436 | else | ||
437 | { | ||
438 | pf._prev = pf._next = null; | ||
439 | } | ||
440 | return (pf); | ||
441 | } | ||
442 | |||
443 | public void Detach(ref Face face) | ||
444 | { | ||
445 | if (face._prev != null || face._next != null) | ||
446 | { | ||
447 | --_nfaces; | ||
448 | if (face == _root) | ||
449 | { | ||
450 | _root = face._next; | ||
451 | _root._prev = null; | ||
452 | } | ||
453 | else | ||
454 | { | ||
455 | if (face._next == null) | ||
456 | { | ||
457 | face._prev._next = null; | ||
458 | } | ||
459 | else | ||
460 | { | ||
461 | face._prev._next = face._next; | ||
462 | face._next._prev = face._prev; | ||
463 | } | ||
464 | } | ||
465 | face._prev = face._next = null; | ||
466 | } | ||
467 | } | ||
468 | |||
469 | public void Link(ref Face f0, int e0, ref Face f1, int e1) | ||
470 | { | ||
471 | f0._faces[e0] = f1; f1._e[e1] = e0; | ||
472 | f1._faces[e1] = f0; f0._e[e0] = e1; | ||
473 | } | ||
474 | |||
475 | public Gjk.MinkowskiVertice Support(Vector3 w) | ||
476 | { | ||
477 | Gjk.MinkowskiVertice v = new Gjk.MinkowskiVertice(); | ||
478 | _gjk.Support(w, ref v); | ||
479 | return v; | ||
480 | } | ||
481 | |||
482 | private static int[] mod3 ={ 0, 1, 2, 0, 1 }; | ||
483 | |||
484 | public int BuildHorizon(int markid, Gjk.MinkowskiVertice w, ref Face f, int e, ref Face cf, ref Face ff) | ||
485 | { | ||
486 | int ne = (0); | ||
487 | if (f._mark != markid) | ||
488 | { | ||
489 | int e1 = (mod3[e + 1]); | ||
490 | if ((Vector3.Dot(f._n, w.Vertice) + f._d) > 0) | ||
491 | { | ||
492 | Face nf = NewFace(f._vertices[e1], f._vertices[e], w); | ||
493 | Link(ref nf, 0, ref f, e); | ||
494 | if (cf != null) Link(ref cf, 1, ref nf, 2); else ff = nf; | ||
495 | cf = nf; ne = 1; | ||
496 | } | ||
497 | else | ||
498 | { | ||
499 | int e2 = (mod3[e + 2]); | ||
500 | Detach(ref f); | ||
501 | f._mark = markid; | ||
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); | ||
504 | } | ||
505 | } | ||
506 | return (ne); | ||
507 | } | ||
508 | |||
509 | public float EvaluatePD() | ||
510 | { | ||
511 | return EvaluatePD(_epaAccuracy); | ||
512 | } | ||
513 | |||
514 | private int[,] fidx; | ||
515 | private int[,] eidx; | ||
516 | |||
517 | public float EvaluatePD(float accuracy) | ||
518 | { | ||
519 | //Block* sablock = sa->BeginBlock(); | ||
520 | Face bestface = null; | ||
521 | int markid = 1; | ||
522 | _depth = -_infinity; | ||
523 | _normal = new Vector3(); | ||
524 | _root = null; | ||
525 | _nfaces = 0; | ||
526 | _iterations = 0; | ||
527 | _failed = false; | ||
528 | /* Prepare hull */ | ||
529 | if (_gjk.EncloseOrigin()) | ||
530 | { | ||
531 | int nfidx = 0; | ||
532 | int neidx = 0; | ||
533 | Gjk.MinkowskiVertice[] basemkv = new Gjk.MinkowskiVertice[5]; | ||
534 | Face[] basefaces = new Face[6]; | ||
535 | switch (_gjk.Order) | ||
536 | { | ||
537 | /* Tetrahedron */ | ||
538 | case 3: | ||
539 | { | ||
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 } }; | ||
542 | nfidx = 4; neidx = 6; | ||
543 | } break; | ||
544 | /* Hexahedron */ | ||
545 | case 4: | ||
546 | { | ||
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 } }; | ||
549 | nfidx = 6; neidx = 9; | ||
550 | } break; | ||
551 | } | ||
552 | int i; | ||
553 | |||
554 | for (i = 0; i <= _gjk.Order; ++i) | ||
555 | { | ||
556 | //basemkv[i] = (GJK::Mkv*)sa->Allocate(sizeof(GJK::Mkv)); | ||
557 | basemkv[i] = new Gjk.MinkowskiVertice(); | ||
558 | basemkv[i].Vertice = _gjk.Simplex[i].Vertice; | ||
559 | basemkv[i].Ray = _gjk.Simplex[i].Ray; | ||
560 | } | ||
561 | for (i = 0; i < nfidx; ++i) | ||
562 | { | ||
563 | basefaces[i] = NewFace(basemkv[fidx[i, 0]], basemkv[fidx[i, 1]], basemkv[fidx[i, 2]]); | ||
564 | } | ||
565 | for (i = 0; i < neidx; ++i) | ||
566 | { | ||
567 | Link(ref basefaces[eidx[i, 0]], eidx[i, 1], ref basefaces[eidx[i, 2]], eidx[i, 3]); | ||
568 | } | ||
569 | } | ||
570 | if (0 == _nfaces) | ||
571 | { | ||
572 | return _depth; | ||
573 | } | ||
574 | /* Expand hull */ | ||
575 | for (; _iterations < _epaMaxIterations; ++_iterations) | ||
576 | { | ||
577 | Face bf = FindBest(); | ||
578 | if (bf != null) | ||
579 | { | ||
580 | Gjk.MinkowskiVertice w = Support(-bf._n); | ||
581 | float d = Vector3.Dot(bf._n, w.Vertice) + bf._d; | ||
582 | bestface = bf; | ||
583 | if (d < -accuracy) | ||
584 | { | ||
585 | Face cf = null; | ||
586 | Face ff = null; | ||
587 | int nf = 0; | ||
588 | Detach(ref bf); | ||
589 | bf._mark = ++markid; | ||
590 | for (int i = 0; i < 3; ++i) | ||
591 | { | ||
592 | nf += BuildHorizon(markid, w, ref bf._faces[i], bf._e[i], ref cf, ref ff); | ||
593 | } | ||
594 | if (nf <= 2) { break; } | ||
595 | Link(ref cf, 1, ref ff, 2); | ||
596 | } | ||
597 | else break; | ||
598 | } | ||
599 | else break; | ||
600 | } | ||
601 | /* Extract contact */ | ||
602 | if (bestface != null) | ||
603 | { | ||
604 | Vector3 b = GetCoordinates(bestface); | ||
605 | _normal = bestface._n; | ||
606 | _depth = Max(0, bestface._d); | ||
607 | for (int i = 0; i < 2; ++i) | ||
608 | { | ||
609 | float s = i != 0 ? -1 : 1; | ||
610 | for (int j = 0; j < 3; ++j) | ||
611 | { | ||
612 | _features[i, j] = _gjk.LocalSupport(s * bestface._vertices[j].Ray, i); | ||
613 | } | ||
614 | } | ||
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; | ||
617 | } | ||
618 | else _failed = true; | ||
619 | return _depth; | ||
620 | } | ||
621 | |||
622 | private float Max(float a, float b) | ||
623 | { | ||
624 | return (a > b ? a : b); | ||
625 | } | ||
626 | |||
627 | private float Min(float a, float b) | ||
628 | { | ||
629 | return (a < b ? a : b); | ||
630 | } | ||
631 | } | ||
632 | } | ||
633 | } | ||