1
2use crate::*;
7
8#[repr(C)]
12#[derive(Copy, Clone, Debug, PartialEq, Eq)]
13pub enum ContainmentType {
14 DISJOINT = 0,
16 INTERSECTS = 1,
18 CONTAINS = 2,
20}
21
22#[repr(C)]
26#[derive(Copy, Clone, Debug, PartialEq, Eq)]
27pub enum PlaneIntersectionType {
28 FRONT = 0,
30 INTERSECTING = 1,
32 BACK = 2,
34}
35
36use ContainmentType::{DISJOINT, INTERSECTS, CONTAINS};
37use PlaneIntersectionType::{FRONT, INTERSECTING, BACK};
38
39#[repr(C)]
41#[derive(Copy, Clone, Debug, Default)]
42pub struct BoundingSphere {
43 pub Center: XMFLOAT3,
45
46 pub Radius: f32,
48}
49
50#[repr(C)]
54#[derive(Copy, Clone, Debug, Default)]
55pub struct BoundingBox {
56 pub Center: XMFLOAT3,
58
59 pub Extents: XMFLOAT3,
61}
62
63#[repr(C)]
67#[derive(Copy, Clone, Debug, Default)]
68pub struct BoundingOrientedBox {
69 pub Center: XMFLOAT3,
71
72 pub Extents: XMFLOAT3,
74
75 pub Orientation: XMFLOAT4,
77}
78
79#[repr(C)]
83#[derive(Copy, Clone, Debug, Default)]
84pub struct BoundingFrustum {
85 pub Origin: XMFLOAT3,
87
88 pub Orientation: XMFLOAT4,
90
91 pub RightSlope: f32,
93
94 pub LeftSlope: f32,
96
97 pub TopSlope: f32,
99
100 pub BottomSlope: f32,
102
103 pub Near: f32,
105
106 pub Far: f32,
108}
109
110const g_BoxOffset: [XMVECTORF32; BoundingBox::CORNER_COUNT] = [
111 XMVECTORF32 { f: [ -1.0, -1.0, 1.0, 0.0 ] },
112 XMVECTORF32 { f: [ 1.0, -1.0, 1.0, 0.0 ] },
113 XMVECTORF32 { f: [ 1.0, 1.0, 1.0, 0.0 ] },
114 XMVECTORF32 { f: [ -1.0, 1.0, 1.0, 0.0 ] },
115 XMVECTORF32 { f: [ -1.0, -1.0, -1.0, 0.0 ] },
116 XMVECTORF32 { f: [ 1.0, -1.0, -1.0, 0.0 ] },
117 XMVECTORF32 { f: [ 1.0, 1.0, -1.0, 0.0 ] },
118 XMVECTORF32 { f: [ -1.0, 1.0, -1.0, 0.0 ] },
119];
120
121const FLT_MAX: f32 = std::f32::MAX;
122
123const g_RayEpsilon: XMVECTORF32 = XMVECTORF32 { f: [ 1e-20, 1e-20, 1e-20, 1e-20 ] };
124const g_RayNegEpsilon: XMVECTORF32 = XMVECTORF32 { f: [ -1e-20, -1e-20, -1e-20, -1e-20 ] };
125const g_FltMin: XMVECTORF32 = XMVECTORF32 { f: [ -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX ] };
126const g_FltMax: XMVECTORF32 = XMVECTORF32 { f: [ FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX ] };
127
128mod internal {
129 use crate::*;
130
131 const g_UnitVectorEpsilon: XMVECTORF32 = XMVECTORF32 { f: [ 1.0e-4, 1.0e-4, 1.0e-4, 1.0e-4 ] };
132 const g_UnitQuaternionEpsilon: XMVECTORF32 = XMVECTORF32 { f: [ 1.0e-4, 1.0e-4, 1.0e-4, 1.0e-4 ] };
133 const g_UnitPlaneEpsilon: XMVECTORF32 = XMVECTORF32 { f: [ 1.0e-4, 1.0e-4, 1.0e-4, 1.0e-4 ] };
134
135 #[inline]
138 pub fn XMVector3AnyTrue(V: FXMVECTOR) -> bool {
139 let C: XMVECTOR = <(XM_SWIZZLE_X, XM_SWIZZLE_Y, XM_SWIZZLE_Z, XM_SWIZZLE_X)>::XMVectorSwizzle(V);
141 return XMComparisonAnyTrue(XMVector4EqualIntR(C, XMVectorTrueInt()));
142 }
143
144 #[inline]
147 pub fn XMVector3AllTrue(V: FXMVECTOR) -> bool {
148 let C: XMVECTOR = <(XM_SWIZZLE_X, XM_SWIZZLE_Y, XM_SWIZZLE_Z, XM_SWIZZLE_X)>::XMVectorSwizzle(V);
150 return XMComparisonAllTrue(XMVector4EqualIntR(C, XMVectorTrueInt()));
151 }
152
153 #[inline]
155 pub fn XMVector3IsUnit(V: FXMVECTOR) -> bool {
156 let Difference: XMVECTOR = XMVectorSubtract(XMVector3Length(V), XMVectorSplatOne());
157 return XMVector4Less(XMVectorAbs(Difference), g_UnitVectorEpsilon.v());
158 }
159
160 #[inline]
162 pub fn XMQuaternionIsUnit(Q: FXMVECTOR) -> bool {
163 let Difference: XMVECTOR = XMVectorSubtract(XMVector4Length(Q), XMVectorSplatOne());
164 return XMVector4Less(XMVectorAbs(Difference), g_UnitQuaternionEpsilon.v());
165 }
166
167 #[inline]
169 pub fn XMPlaneIsUnit(Plane: FXMVECTOR) -> bool {
170 let Difference: XMVECTOR = XMVectorSubtract(XMVector3Length(Plane), XMVectorSplatOne());
171 return XMVector4Less(XMVectorAbs(Difference), g_UnitPlaneEpsilon.v());
172 }
173
174 #[inline]
175 pub fn XMPlaneTransform(Plane: FXMVECTOR, Rotation: FXMVECTOR, Translation: FXMVECTOR) -> XMVECTOR {
176 let vNormal: XMVECTOR = XMVector3Rotate(Plane, Rotation);
177 let vD: XMVECTOR = XMVectorSubtract(XMVectorSplatW(Plane), XMVector3Dot(vNormal, Translation));
178
179 return XMVectorInsert(vNormal, vD, 0, 0, 0, 0, 1);
181 }
182
183 #[inline]
185 pub fn PointOnLineSegmentNearestPoint(S1: FXMVECTOR, S2: FXMVECTOR, P: FXMVECTOR) -> XMVECTOR {
186 let Dir: XMVECTOR = XMVectorSubtract(S2, S1);
187 let Projection: XMVECTOR = XMVectorSubtract(XMVector3Dot(P, Dir), XMVector3Dot(S1, Dir));
188 let LengthSq: XMVECTOR = XMVector3Dot(Dir, Dir);
189
190 let t: XMVECTOR = XMVectorMultiply(Projection, XMVectorReciprocal(LengthSq));
191 let mut Point: XMVECTOR = XMVectorMultiplyAdd(t, Dir, S1);
192
193 let SelectS1: XMVECTOR = XMVectorLess(Projection, XMVectorZero());
195 Point = XMVectorSelect(Point, S1, SelectS1);
196
197 let SelectS2: XMVECTOR = XMVectorGreater(Projection, LengthSq);
199 Point = XMVectorSelect(Point, S2, SelectS2);
200
201 return Point;
202 }
203
204 #[inline]
207 pub fn PointOnPlaneInsideTriangle(P: FXMVECTOR, V0: FXMVECTOR, V1: FXMVECTOR, V2: GXMVECTOR) -> XMVECTOR {
208 let N: XMVECTOR = XMVector3Cross(XMVectorSubtract(V2, V0), XMVectorSubtract(V1, V0));
210
211 let C0: XMVECTOR = XMVector3Cross(XMVectorSubtract(P, V0), XMVectorSubtract(V1, V0));
214 let C1: XMVECTOR = XMVector3Cross(XMVectorSubtract(P, V1), XMVectorSubtract(V2, V1));
215 let C2: XMVECTOR = XMVector3Cross(XMVectorSubtract(P, V2), XMVectorSubtract(V0, V2));
216
217 let Zero: XMVECTOR = XMVectorZero();
220 let Inside0: XMVECTOR = XMVectorGreaterOrEqual(XMVector3Dot(C0, N), Zero);
221 let Inside1: XMVECTOR = XMVectorGreaterOrEqual(XMVector3Dot(C1, N), Zero);
222 let Inside2: XMVECTOR = XMVectorGreaterOrEqual(XMVector3Dot(C2, N), Zero);
223
224 return XMVectorAndInt(XMVectorAndInt(Inside0, Inside1), Inside2);
226 }
227
228 #[inline]
229 pub fn SolveCubic(e: f32, f: f32, g: f32, t: &mut f32, u: &mut f32, v: &mut f32) -> bool {
230 let p: f32;
231 let q: f32;
232 let h: f32;
233 let rc: f32;
234 let d: f32;
235 let theta: f32;
236 let costh3: f32;
237 let sinth3: f32;
238
239 p = f - e * e / 3.0;
240 q = g - e * f / 3.0 + e * e * e * 2.0 / 27.0;
241 h = q * q / 4.0 + p * p * p / 27.0;
242
243 if (h > 0.0)
244 {
245 *t = 0.0;
246 *u = 0.0;
247 *v = 0.0;
248 return false; }
250
251 if ((h == 0.0) && (q == 0.0)) {
253 *t = -e / 3.0;
254 *u = -e / 3.0;
255 *v = -e / 3.0;
256
257 return true;
258 }
259
260 d = sqrtf(q * q / 4.0 - h);
261 if (d < 0.0) {
262 rc = -powf(-d, 1.0 / 3.0);
263 }
264 else {
265 rc = powf(d, 1.0 / 3.0);
266 }
267
268 theta = XMScalarACos(-q / (2.0 * d));
269 costh3 = XMScalarCos(theta / 3.0);
270 sinth3 = sqrtf(3.0) * XMScalarSin(theta / 3.0);
271 *t = 2.0 * rc * costh3 - e / 3.0;
272 *u = -rc * (costh3 + sinth3) - e / 3.0;
273 *v = -rc * (costh3 - sinth3) - e / 3.0;
274
275 return true;
276 }
277
278 #[inline]
279 pub fn CalculateEigenVector(
280 m11: f32, m12: f32, m13: f32,
281 m22: f32, m23: f32, m33: f32,
282 e: f32,
283 ) -> XMVECTOR {
284 let mut fTmp: [f32; 3] = unsafe { undefined() };
285 fTmp[0] = m12 * m23 - m13 * (m22 - e);
286 fTmp[1] = m13 * m12 - m23 * (m11 - e);
287 fTmp[2] = (m11 - e) * (m22 - e) - m12 * m12;
288
289 let fTmp: XMFLOAT3 = unsafe { mem::transmute(fTmp) };
290 let mut vTmp: XMVECTOR = XMLoadFloat3(&fTmp);
291
292 if (XMVector3Equal(vTmp, XMVectorZero())) {
294 let f1: f32;
295 let f2: f32;
296 let f3: f32;
297
298 if ((m11 - e != 0.0) || (m12 != 0.0) || (m13 != 0.0))
300 {
301 f1 = m11 - e; f2 = m12; f3 = m13;
302 }
303 else if ((m12 != 0.0) || (m22 - e != 0.0) || (m23 != 0.0))
304 {
305 f1 = m12; f2 = m22 - e; f3 = m23;
306 }
307 else if ((m13 != 0.0) || (m23 != 0.0) || (m33 - e != 0.0))
308 {
309 f1 = m13; f2 = m23; f3 = m33 - e;
310 }
311 else
312 {
313 f1 = 1.0; f2 = 0.0; f3 = 0.0;
315 }
316
317 if (f1 == 0.0) {
318 vTmp = XMVectorSetX(vTmp, 0.0);
319 } else {
320 vTmp = XMVectorSetX(vTmp, 1.0);
321 }
322 if (f2 == 0.0) {
323 vTmp = XMVectorSetY(vTmp, 0.0);
324 } else {
325 vTmp = XMVectorSetY(vTmp, 1.0);
326 }
327 if (f3 == 0.0)
328 {
329 vTmp = XMVectorSetZ(vTmp, 0.0);
330 if (m12 != 0.0) {
332 vTmp = XMVectorSetY(vTmp, -f1 / f2);
333 }
334 }
335 else
336 {
337 vTmp = XMVectorSetZ(vTmp, (f2 - f1) / f3);
338 }
339 }
340
341 if (XMVectorGetX(XMVector3LengthSq(vTmp)) > 1e-5)
342 {
343 return XMVector3Normalize(vTmp);
344 }
345 else
346 {
347 vTmp = XMVectorScale(vTmp, 1e5);
349 return XMVector3Normalize(vTmp);
350 }
351 }
352
353 #[inline]
354 pub fn CalculateEigenVectors(
355 m11: f32, m12: f32, m13: f32,
356 m22: f32, m23: f32, m33: f32,
357 e1: f32, e2: f32, e3: f32,
358 pV1: &mut XMVECTOR,
359 pV2: &mut XMVECTOR,
360 pV3: &mut XMVECTOR,
361 ) -> bool {
362 *pV1 = CalculateEigenVector(m11, m12, m13, m22, m23, m33, e1);
363 *pV2 = CalculateEigenVector(m11, m12, m13, m22, m23, m33, e2);
364 *pV3 = CalculateEigenVector(m11, m12, m13, m22, m23, m33, e3);
365
366 let mut v1z: bool = false;
367 let mut v2z: bool = false;
368 let mut v3z: bool = false;
369
370 let Zero: XMVECTOR = XMVectorZero();
371
372 if (XMVector3Equal(*pV1, Zero)) {
373 v1z = true;
374 }
375
376 if (XMVector3Equal(*pV2, Zero)) {
377 v2z = true;
378 }
379
380 if (XMVector3Equal(*pV3, Zero)) {
381 v3z = true;
382 }
383
384 let e12: bool = (fabsf(XMVectorGetX(XMVector3Dot(*pV1, *pV2))) > 0.1); let e13: bool = (fabsf(XMVectorGetX(XMVector3Dot(*pV1, *pV3))) > 0.1);
386 let e23: bool = (fabsf(XMVectorGetX(XMVector3Dot(*pV2, *pV3))) > 0.1);
387
388 if ((v1z && v2z && v3z) || (e12 && e13 && e23) ||
389 (e12 && v3z) || (e13 && v2z) || (e23 && v1z)) {
391 *pV1 = g_XMIdentityR0.v();
392 *pV2 = g_XMIdentityR1.v();
393 *pV3 = g_XMIdentityR2.v();
394 return true;
395 }
396
397 if (v1z && v2z)
398 {
399 let mut vTmp: XMVECTOR = XMVector3Cross(g_XMIdentityR1.v(), *pV3);
400 if (XMVectorGetX(XMVector3LengthSq(vTmp)) < 1e-5)
401 {
402 vTmp = XMVector3Cross(g_XMIdentityR0.v(), *pV3);
403 }
404 *pV1 = XMVector3Normalize(vTmp);
405 *pV2 = XMVector3Cross(*pV3, *pV1);
406 return true;
407 }
408
409 if (v3z && v1z)
410 {
411 let mut vTmp: XMVECTOR = XMVector3Cross(g_XMIdentityR1.v(), *pV2);
412 if (XMVectorGetX(XMVector3LengthSq(vTmp)) < 1e-5)
413 {
414 vTmp = XMVector3Cross(g_XMIdentityR0.v(), *pV2);
415 }
416 *pV3 = XMVector3Normalize(vTmp);
417 *pV1 = XMVector3Cross(*pV2, *pV3);
418 return true;
419 }
420
421 if (v2z && v3z)
422 {
423 let mut vTmp: XMVECTOR = XMVector3Cross(g_XMIdentityR1.v(), *pV1);
424 if (XMVectorGetX(XMVector3LengthSq(vTmp)) < 1e-5)
425 {
426 vTmp = XMVector3Cross(g_XMIdentityR0.v(), *pV1);
427 }
428 *pV2 = XMVector3Normalize(vTmp);
429 *pV3 = XMVector3Cross(*pV1, *pV2);
430 return true;
431 }
432
433 if ((v1z) || e12)
434 {
435 *pV1 = XMVector3Cross(*pV2, *pV3);
436 return true;
437 }
438
439 if ((v2z) || e23)
440 {
441 *pV2 = XMVector3Cross(*pV3, *pV1);
442 return true;
443 }
444
445 if ((v3z) || e13)
446 {
447 *pV3 = XMVector3Cross(*pV1, *pV2);
448 return true;
449 }
450
451 return true;
452 }
453
454 #[inline]
455 pub fn CalculateEigenVectorsFromCovarianceMatrix(
456 Cxx: f32,
457 Cyy: f32,
458 Czz: f32,
459 Cxy: f32,
460 Cxz: f32,
461 Cyz: f32,
462 pV1: &mut XMVECTOR,
463 pV2: &mut XMVECTOR,
464 pV3: &mut XMVECTOR,
465
466 ) -> bool {
467 let e: f32 = -(Cxx + Cyy + Czz);
469 let f: f32 = Cxx * Cyy + Cyy * Czz + Czz * Cxx - Cxy * Cxy - Cxz * Cxz - Cyz * Cyz;
470 let g: f32 = Cxy * Cxy * Czz + Cxz * Cxz * Cyy + Cyz * Cyz * Cxx - Cxy * Cyz * Cxz * 2.0 - Cxx * Cyy * Czz;
471
472 let mut ev1: f32 = 0.0;
473 let mut ev2: f32 = 0.0;
474 let mut ev3: f32 = 0.0;
475 if (!SolveCubic(e, f, g, &mut ev1, &mut ev2, &mut ev3))
476 {
477 *pV1 = g_XMIdentityR0.v();
479 *pV2 = g_XMIdentityR1.v();
480 *pV3 = g_XMIdentityR2.v();
481 return false;
482 }
483
484 return CalculateEigenVectors(Cxx, Cxy, Cxz, Cyy, Cyz, Czz, ev1, ev2, ev3, pV1, pV2, pV3);
485 }
486
487 #[inline]
488 pub fn FastIntersectTrianglePlane(
489 V0: FXMVECTOR,
490 V1: FXMVECTOR,
491 V2: FXMVECTOR,
492 Plane: GXMVECTOR,
493 Outside: &mut XMVECTOR,
494 Inside: &mut XMVECTOR
495 ) {
496 let Dist0: XMVECTOR = XMVector4Dot(V0, Plane);
498 let Dist1: XMVECTOR = XMVector4Dot(V1, Plane);
499 let Dist2: XMVECTOR = XMVector4Dot(V2, Plane);
500
501 let mut MinDist: XMVECTOR = XMVectorMin(Dist0, Dist1);
502 MinDist = XMVectorMin(MinDist, Dist2);
503
504 let mut MaxDist: XMVECTOR = XMVectorMax(Dist0, Dist1);
505 MaxDist = XMVectorMax(MaxDist, Dist2);
506
507 let Zero: XMVECTOR = XMVectorZero();
508
509 *Outside = XMVectorGreater(MinDist, Zero);
511
512 *Inside = XMVectorLess(MaxDist, Zero);
514 }
515
516 #[inline]
517 pub fn FastIntersectSpherePlane(
518 Center: FXMVECTOR,
519 Radius: FXMVECTOR,
520 Plane: FXMVECTOR,
521 Outside: &mut XMVECTOR,
522 Inside: &mut XMVECTOR,
523 ) {
524 let Dist: XMVECTOR = XMVector4Dot(Center, Plane);
525
526 *Outside = XMVectorGreater(Dist, Radius);
528
529 *Inside = XMVectorLess(Dist, XMVectorNegate(Radius));
531 }
532
533 #[inline]
534 pub fn FastIntersectAxisAlignedBoxPlane(
535 Center: FXMVECTOR,
536 Extents: FXMVECTOR,
537 Plane: FXMVECTOR,
538 Outside: &mut XMVECTOR,
539 Inside: &mut XMVECTOR,
540 ) {
541 let Dist: XMVECTOR = XMVector4Dot(Center, Plane);
543
544 let Radius: XMVECTOR = XMVector3Dot(Extents, XMVectorAbs(Plane));
550
551 *Outside = XMVectorGreater(Dist, Radius);
553
554 *Inside = XMVectorLess(Dist, XMVectorNegate(Radius));
556 }
557
558 #[inline]
559 pub fn FastIntersectOrientedBoxPlane(
560 Center: FXMVECTOR,
561 Extents: FXMVECTOR,
562 Axis0: FXMVECTOR,
563 Axis1: GXMVECTOR,
564 Axis2: HXMVECTOR,
565 Plane: HXMVECTOR,
566 Outside: &mut XMVECTOR,
567 Inside: &mut XMVECTOR,
568 ) {
569 let Dist: XMVECTOR = XMVector4Dot(Center, Plane);
571
572 let mut Radius: XMVECTOR = XMVector3Dot(Plane, Axis0);
578 Radius = XMVectorInsert(Radius, XMVector3Dot(Plane, Axis1), 0, 0, 1, 0, 0);
580 Radius = XMVectorInsert(Radius, XMVector3Dot(Plane, Axis2), 0, 0, 0, 1, 0);
581 Radius = XMVector3Dot(Extents, XMVectorAbs(Radius));
582
583 *Outside = XMVectorGreater(Dist, Radius);
585
586 *Inside = XMVectorLess(Dist, XMVectorNegate(Radius));
588 }
589
590 #[inline]
591 pub fn FastIntersectFrustumPlane(
592 Point0: FXMVECTOR,
593 Point1: FXMVECTOR,
594 Point2: FXMVECTOR,
595 Point3: GXMVECTOR,
596 Point4: HXMVECTOR,
597 Point5: HXMVECTOR,
598 Point6: CXMVECTOR,
599 Point7: CXMVECTOR,
600 Plane: CXMVECTOR,
601 Outside: &mut XMVECTOR,
602 Inside: &mut XMVECTOR,
603 ) {
604 let Plane = *Plane;
605 let Point6 = *Point6;
606 let Point7 = *Point7;
607
608 let mut Min: XMVECTOR = XMVector3Dot(Plane, Point0);
610 let mut Max: XMVECTOR = Min;
611 let mut Dist: XMVECTOR;
612
613 Dist = XMVector3Dot(Plane, Point1);
614 Min = XMVectorMin(Min, Dist);
615 Max = XMVectorMax(Max, Dist);
616
617 Dist = XMVector3Dot(Plane, Point2);
618 Min = XMVectorMin(Min, Dist);
619 Max = XMVectorMax(Max, Dist);
620
621 Dist = XMVector3Dot(Plane, Point3);
622 Min = XMVectorMin(Min, Dist);
623 Max = XMVectorMax(Max, Dist);
624
625 Dist = XMVector3Dot(Plane, Point4);
626 Min = XMVectorMin(Min, Dist);
627 Max = XMVectorMax(Max, Dist);
628
629 Dist = XMVector3Dot(Plane, Point5);
630 Min = XMVectorMin(Min, Dist);
631 Max = XMVectorMax(Max, Dist);
632
633 Dist = XMVector3Dot(Plane, Point6);
634 Min = XMVectorMin(Min, Dist);
635 Max = XMVectorMax(Max, Dist);
636
637 Dist = XMVector3Dot(Plane, Point7);
638 Min = XMVectorMin(Min, Dist);
639 Max = XMVectorMax(Max, Dist);
640
641 let PlaneDist: XMVECTOR = XMVectorNegate(XMVectorSplatW(Plane));
642
643 *Outside = XMVectorGreater(Min, PlaneDist);
645
646 *Inside = XMVectorLess(Max, PlaneDist);
648 }
649}
650
651impl BoundingSphere {
654 #[inline]
670 pub fn TransformMatrix(&self, Out: &mut Self, M: FXMMATRIX) {
671 unsafe {
672 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
674
675 let C: XMVECTOR = XMVector3Transform(vCenter, M);
677
678 let dX: XMVECTOR = XMVector3Dot(M.r[0], M.r[0]);
679 let dY: XMVECTOR = XMVector3Dot(M.r[1], M.r[1]);
680 let dZ: XMVECTOR = XMVector3Dot(M.r[2], M.r[2]);
681
682 let d: XMVECTOR = XMVectorMax(dX, XMVectorMax(dY, dZ));
683
684 XMStoreFloat3(&mut Out.Center, C);
686
687 let Scale: f32 = sqrtf(XMVectorGetX(d));
689 Out.Radius = self.Radius * Scale;
690 }
691 }
692
693 #[inline]
713 pub fn TransformDecomposed(&self, Out: &mut Self, Scale: f32, Rotation: FXMVECTOR, Translation: FXMVECTOR) {
714 let mut vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
716
717 vCenter = XMVectorAdd(XMVector3Rotate(XMVectorScale(vCenter, Scale), Rotation), Translation);
719
720 XMStoreFloat3(&mut Out.Center, vCenter);
722
723 Out.Radius = self.Radius * Scale;
725 }
726
727 #[inline]
741 pub fn ContainsPoint(&self, Point: FXMVECTOR) -> ContainmentType {
742 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
743 let vRadius: XMVECTOR = XMVectorReplicatePtr(&self.Radius);
744
745 let DistanceSquared: XMVECTOR = XMVector3LengthSq(XMVectorSubtract(Point, vCenter));
746 let RadiusSquared: XMVECTOR = XMVectorMultiply(vRadius, vRadius);
747
748 if XMVector3LessOrEqual(DistanceSquared, RadiusSquared) {
749 ContainmentType::CONTAINS
750 } else {
751 ContainmentType::DISJOINT
752 }
753 }
754
755 #[inline]
773 pub fn ContainsTriangle(&self, V0: FXMVECTOR, V1: FXMVECTOR, V2: FXMVECTOR) -> ContainmentType {
774 if (!self.IntersectsTriangle(V0, V1, V2)) {
775 return ContainmentType::DISJOINT;
776 }
777
778 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
779 let vRadius: XMVECTOR = XMVectorReplicatePtr(&self.Radius);
780 let RadiusSquared: XMVECTOR = XMVectorMultiply(vRadius, vRadius);
781
782 let mut DistanceSquared: XMVECTOR = XMVector3LengthSq(XMVectorSubtract(V0, vCenter));
783 let mut Inside: XMVECTOR = XMVectorLessOrEqual(DistanceSquared, RadiusSquared);
784
785 DistanceSquared = XMVector3LengthSq(XMVectorSubtract(V1, vCenter));
786 Inside = XMVectorAndInt(Inside, XMVectorLessOrEqual(DistanceSquared, RadiusSquared));
787
788 DistanceSquared = XMVector3LengthSq(XMVectorSubtract(V2, vCenter));
789 Inside = XMVectorAndInt(Inside, XMVectorLessOrEqual(DistanceSquared, RadiusSquared));
790
791 return if (XMVector3EqualInt(Inside, XMVectorTrueInt())) { CONTAINS } else { INTERSECTS }
792 }
793
794 #[inline]
808 pub fn ContainsSphere(&self, sh: &BoundingSphere) -> ContainmentType {
809 let Center1: XMVECTOR = XMLoadFloat3(&self.Center);
810 let r1: f32 = self.Radius;
811
812 let Center2: XMVECTOR = XMLoadFloat3(&sh.Center);
813 let r2: f32 = sh.Radius;
814
815 let V: XMVECTOR = XMVectorSubtract(Center2, Center1);
816
817 let Dist: XMVECTOR = XMVector3Length(V);
818
819 let d: f32 = XMVectorGetX(Dist);
820
821 return if (r1 + r2 >= d) { if (r1 - r2 >= d) { CONTAINS } else { INTERSECTS } } else { DISJOINT }
822 }
823
824 #[inline]
838 pub fn ContainsBox(&self, box_: &BoundingBox) -> ContainmentType {
839 if (!box_.IntersectsSphere(self)) {
840 return DISJOINT;
841 }
842
843 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
844 let vRadius: XMVECTOR = XMVectorReplicatePtr(&self.Radius);
845 let RadiusSq: XMVECTOR = XMVectorMultiply(vRadius, vRadius);
846
847 let boxCenter: XMVECTOR = XMLoadFloat3(&box_.Center);
848 let boxExtents: XMVECTOR = XMLoadFloat3(&box_.Extents);
849
850 let mut InsideAll: XMVECTOR = XMVectorTrueInt();
851
852 let offset: XMVECTOR = XMVectorSubtract(boxCenter, vCenter);
853
854 for i in 0 .. BoundingBox::CORNER_COUNT {
855 let C: XMVECTOR = XMVectorMultiplyAdd(boxExtents, g_BoxOffset[i].v(), offset);
856 let d: XMVECTOR = XMVector3LengthSq(C);
857 InsideAll = XMVectorAndInt(InsideAll, XMVectorLessOrEqual(d, RadiusSq));
858 }
859
860 return if (XMVector3EqualInt(InsideAll, XMVectorTrueInt())) { CONTAINS } else { INTERSECTS };
861 }
862
863 #[inline]
877 pub fn ContainsOrientedBox(&self, box_: &BoundingOrientedBox) -> ContainmentType {
878 if (!box_.IntersectsSphere(self)) {
879 return DISJOINT;
880 }
881
882 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
883 let vRadius: XMVECTOR = XMVectorReplicatePtr(&self.Radius);
884 let RadiusSq: XMVECTOR = XMVectorMultiply(vRadius, vRadius);
885
886 let boxCenter: XMVECTOR = XMLoadFloat3(&box_.Center);
887 let boxExtents: XMVECTOR = XMLoadFloat3(&box_.Extents);
888 let boxOrientation: XMVECTOR = XMLoadFloat4(&box_.Orientation);
889
890 debug_assert!(internal::XMQuaternionIsUnit(boxOrientation));
891
892 let mut InsideAll: XMVECTOR = XMVectorTrueInt();
893
894 for i in 0 .. BoundingOrientedBox::CORNER_COUNT {
895 let C: XMVECTOR = XMVectorAdd(XMVector3Rotate(XMVectorMultiply(boxExtents, g_BoxOffset[i].v()), boxOrientation), boxCenter);
896 let d: XMVECTOR = XMVector3LengthSq(XMVectorSubtract(vCenter, C));
897 InsideAll = XMVectorAndInt(InsideAll, XMVectorLessOrEqual(d, RadiusSq));
898 }
899
900 return if (XMVector3EqualInt(InsideAll, XMVectorTrueInt())) { CONTAINS } else { INTERSECTS };
901 }
902
903 #[inline]
917 pub fn ContainsFrustum(&self, fr: &BoundingFrustum) -> ContainmentType {
918 if (!fr.IntersectsSphere(self)) {
919 return DISJOINT;
920 }
921
922 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
923 let vRadius: XMVECTOR = XMVectorReplicatePtr(&self.Radius);
924 let RadiusSq: XMVECTOR = XMVectorMultiply(vRadius, vRadius);
925
926 let vOrigin: XMVECTOR = XMLoadFloat3(&fr.Origin);
927 let vOrientation: XMVECTOR = XMLoadFloat4(&fr.Orientation);
928
929 debug_assert!(internal::XMQuaternionIsUnit(vOrientation));
930
931 let vRightTop: XMVECTOR = XMVectorSet(fr.RightSlope, fr.TopSlope, 1.0, 0.0);
933 let vRightBottom: XMVECTOR = XMVectorSet(fr.RightSlope, fr.BottomSlope, 1.0, 0.0);
934 let vLeftTop: XMVECTOR = XMVectorSet(fr.LeftSlope, fr.TopSlope, 1.0, 0.0);
935 let vLeftBottom: XMVECTOR = XMVectorSet(fr.LeftSlope, fr.BottomSlope, 1.0, 0.0);
936 let vNear: XMVECTOR = XMVectorReplicatePtr(&fr.Near);
937 let vFar: XMVECTOR = XMVectorReplicatePtr(&fr.Far);
938
939 let mut Corners: [XMVECTOR; BoundingFrustum::CORNER_COUNT] = unsafe { undefined() };
940 Corners[0] = XMVectorMultiply(vRightTop, vNear);
941 Corners[1] = XMVectorMultiply(vRightBottom, vNear);
942 Corners[2] = XMVectorMultiply(vLeftTop, vNear);
943 Corners[3] = XMVectorMultiply(vLeftBottom, vNear);
944 Corners[4] = XMVectorMultiply(vRightTop, vFar);
945 Corners[5] = XMVectorMultiply(vRightBottom, vFar);
946 Corners[6] = XMVectorMultiply(vLeftTop, vFar);
947 Corners[7] = XMVectorMultiply(vLeftBottom, vFar);
948
949 let mut InsideAll: XMVECTOR = XMVectorTrueInt();
950 for i in 0..BoundingFrustum::CORNER_COUNT {
951 let C: XMVECTOR = XMVectorAdd(XMVector3Rotate(Corners[i], vOrientation), vOrigin);
952 let d: XMVECTOR = XMVector3LengthSq(XMVectorSubtract(vCenter, C));
953 InsideAll = XMVectorAndInt(InsideAll, XMVectorLessOrEqual(d, RadiusSq));
954 }
955
956 return if (XMVector3EqualInt(InsideAll, XMVectorTrueInt())) { CONTAINS } else { INTERSECTS };
957 }
958
959 #[inline]
973 pub fn IntersectsSphere(&self, sh: &BoundingSphere) -> bool {
974 let vCenterA: XMVECTOR = XMLoadFloat3(&self.Center);
976 let vRadiusA: XMVECTOR = XMVectorReplicatePtr(&self.Radius);
977
978 let vCenterB: XMVECTOR = XMLoadFloat3(&sh.Center);
980 let vRadiusB: XMVECTOR = XMVectorReplicatePtr(&sh.Radius);
981
982 let Delta: XMVECTOR = XMVectorSubtract(vCenterB, vCenterA);
984 let DistanceSquared: XMVECTOR = XMVector3LengthSq(Delta);
985
986 let mut RadiusSquared: XMVECTOR = XMVectorAdd(vRadiusA, vRadiusB);
988 RadiusSquared = XMVectorMultiply(RadiusSquared, RadiusSquared);
989
990 return XMVector3LessOrEqual(DistanceSquared, RadiusSquared);
991 }
992
993 #[inline]
997 pub fn IntersectsBox(&self, box_: &BoundingBox) -> bool {
998 return box_.IntersectsSphere(self);
999 }
1000
1001 #[inline]
1005 pub fn IntersectsOrientedBox(&self, box_: &BoundingOrientedBox) -> bool {
1006 return box_.IntersectsSphere(self);
1007 }
1008
1009 #[inline]
1013 pub fn IntersectsFrustum(&self, fr: &BoundingFrustum) -> bool {
1014 return fr.IntersectsSphere(self);
1015 }
1016
1017 #[inline]
1021 pub fn IntersectsTriangle(&self, V0: FXMVECTOR, V1: FXMVECTOR, V2: FXMVECTOR) -> bool {
1022 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
1024 let vRadius: XMVECTOR = XMVectorReplicatePtr(&self.Radius);
1025
1026 let N: XMVECTOR = XMVector3Normalize(XMVector3Cross(XMVectorSubtract(V1, V0), XMVectorSubtract(V2, V0)));
1028
1029 debug_assert!(!XMVector3Equal(N, XMVectorZero()));
1031
1032 let Dist: XMVECTOR = XMVector3Dot(XMVectorSubtract(vCenter, V0), N);
1034
1035 let mut NoIntersection: XMVECTOR = XMVectorLess(Dist, XMVectorNegate(vRadius));
1038 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Dist, vRadius));
1039
1040 let mut Point: XMVECTOR = XMVectorNegativeMultiplySubtract(N, Dist, vCenter);
1042
1043 let mut Intersection: XMVECTOR = internal::PointOnPlaneInsideTriangle(Point, V0, V1, V2);
1046
1047 let RadiusSq: XMVECTOR = XMVectorMultiply(vRadius, vRadius);
1049
1050 Point = internal::PointOnLineSegmentNearestPoint(V0, V1, vCenter);
1052
1053 Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(vCenter, Point)), RadiusSq));
1056
1057 Point = internal::PointOnLineSegmentNearestPoint(V1, V2, vCenter);
1059
1060 Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(vCenter, Point)), RadiusSq));
1063
1064 Point = internal::PointOnLineSegmentNearestPoint(V2, V0, vCenter);
1066
1067 Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(vCenter, Point)), RadiusSq));
1070
1071 return XMVector4EqualInt(XMVectorAndCInt(Intersection, NoIntersection), XMVectorTrueInt());
1072 }
1073
1074 #[inline]
1088 pub fn IntersectsPlane(&self, Plane: FXMVECTOR) -> PlaneIntersectionType {
1089 debug_assert!(internal::XMPlaneIsUnit(Plane));
1090
1091 let mut vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
1093 let vRadius: XMVECTOR = XMVectorReplicatePtr(&self.Radius);
1094
1095 vCenter = XMVectorInsert(vCenter, XMVectorSplatOne(), 0, 0, 0, 0, 1);
1098
1099 let mut Outside: XMVECTOR = unsafe { undefined() };
1100 let mut Inside: XMVECTOR = unsafe { undefined() };
1101 internal::FastIntersectSpherePlane(vCenter, vRadius, Plane, &mut Outside, &mut Inside);
1102
1103 if (XMVector4EqualInt(Outside, XMVectorTrueInt())) {
1105 return FRONT;
1106 }
1107
1108 if (XMVector4EqualInt(Inside, XMVectorTrueInt())) {
1110 return BACK;
1111 }
1112
1113 return INTERSECTING;
1115 }
1116
1117 #[inline]
1140 pub fn IntersectsRay(&self, Origin: FXMVECTOR, Direction: FXMVECTOR, Dist: &mut f32) -> bool {
1141 debug_assert!(internal::XMVector3IsUnit(Direction));
1142
1143 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
1144 let vRadius: XMVECTOR = XMVectorReplicatePtr(&self.Radius);
1145
1146 let l: XMVECTOR = XMVectorSubtract(vCenter, Origin);
1148
1149 let s: XMVECTOR = XMVector3Dot(l, Direction);
1151
1152 let l2: XMVECTOR = XMVector3Dot(l, l);
1153
1154 let r2: XMVECTOR = XMVectorMultiply(vRadius, vRadius);
1155
1156 let m2: XMVECTOR = XMVectorNegativeMultiplySubtract(s, s, l2);
1158
1159 let mut NoIntersection: XMVECTOR;
1160
1161 NoIntersection = XMVectorAndInt(XMVectorLess(s, XMVectorZero()), XMVectorGreater(l2, r2));
1164
1165 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(m2, r2));
1168
1169 let q: XMVECTOR = XMVectorSqrt(XMVectorSubtract(r2, m2));
1171 let t1: XMVECTOR = XMVectorSubtract(s, q);
1172 let t2: XMVECTOR = XMVectorAdd(s, q);
1173
1174 let OriginInside: XMVECTOR = XMVectorLessOrEqual(l2, r2);
1175 let t: XMVECTOR = XMVectorSelect(t1, t2, OriginInside);
1176
1177 if (XMVector4NotEqualInt(NoIntersection, XMVectorTrueInt()))
1178 {
1179 XMStoreFloat(Dist, t);
1181 return true;
1182 }
1183
1184 *Dist = 0.0;
1185 return false;
1186 }
1187
1188 #[inline]
1192 pub fn ContainedBy(
1193 &self,
1194 Plane0: FXMVECTOR,
1195 Plane1: FXMVECTOR,
1196 Plane2: GXMVECTOR,
1197 Plane3: HXMVECTOR,
1198 Plane4: HXMVECTOR,
1199 Plane5: HXMVECTOR,
1200 ) -> ContainmentType
1201 {
1202 let mut vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
1204 let vRadius: XMVECTOR = XMVectorReplicatePtr(&self.Radius);
1205
1206 vCenter = XMVectorInsert(vCenter, XMVectorSplatOne(), 0, 0, 0, 0, 1);
1209
1210 let mut Outside: XMVECTOR = unsafe { undefined() };
1211 let mut Inside: XMVECTOR = unsafe { undefined() };
1212
1213 internal::FastIntersectSpherePlane(vCenter, vRadius, Plane0, &mut Outside, &mut Inside);
1215
1216 let mut AnyOutside: XMVECTOR = Outside;
1217 let mut AllInside: XMVECTOR = Inside;
1218
1219 internal::FastIntersectSpherePlane(vCenter, vRadius, Plane1, &mut Outside, &mut Inside);
1220 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
1221 AllInside = XMVectorAndInt(AllInside, Inside);
1222
1223 internal::FastIntersectSpherePlane(vCenter, vRadius, Plane2, &mut Outside, &mut Inside);
1224 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
1225 AllInside = XMVectorAndInt(AllInside, Inside);
1226
1227 internal::FastIntersectSpherePlane(vCenter, vRadius, Plane3, &mut Outside, &mut Inside);
1228 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
1229 AllInside = XMVectorAndInt(AllInside, Inside);
1230
1231 internal::FastIntersectSpherePlane(vCenter, vRadius, Plane4, &mut Outside, &mut Inside);
1232 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
1233 AllInside = XMVectorAndInt(AllInside, Inside);
1234
1235 internal::FastIntersectSpherePlane(vCenter, vRadius, Plane5, &mut Outside, &mut Inside);
1236 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
1237 AllInside = XMVectorAndInt(AllInside, Inside);
1238
1239 if (XMVector4EqualInt(AnyOutside, XMVectorTrueInt())) {
1241 return DISJOINT;
1242 }
1243
1244 if (XMVector4EqualInt(AllInside, XMVectorTrueInt())) {
1246 return CONTAINS;
1247 }
1248
1249 return INTERSECTS;
1251 }
1252
1253 #[inline]
1257 pub fn CreateMerged(Out: &mut Self, S1: &Self, S2: &Self) {
1258 let Center1: XMVECTOR = XMLoadFloat3(&S1.Center);
1259 let r1: f32 = S1.Radius;
1260
1261 let Center2: XMVECTOR = XMLoadFloat3(&S2.Center);
1262 let r2: f32 = S2.Radius;
1263
1264 let V: XMVECTOR = XMVectorSubtract(Center2, Center1);
1265
1266 let Dist: XMVECTOR = XMVector3Length(V);
1267
1268 let d: f32 = XMVectorGetX(Dist);
1269
1270 if (r1 + r2 >= d)
1271 {
1272 if (r1 - r2 >= d)
1273 {
1274 *Out = *S1;
1275 return;
1276 }
1277 else if (r2 - r1 >= d)
1278 {
1279 *Out = *S2;
1280 return;
1281 }
1282 }
1283
1284 let N: XMVECTOR = XMVectorDivide(V, Dist);
1285
1286 let t1: f32 = XMMin(-r1, d - r2);
1287 let t2: f32 = XMMax(r1, d + r2);
1288 let t_5: f32 = (t2 - t1) * 0.5;
1289
1290 let NCenter: XMVECTOR = XMVectorAdd(Center1, XMVectorMultiply(N, XMVectorReplicate(t_5 + t1)));
1291
1292 XMStoreFloat3(&mut Out.Center, NCenter);
1293 Out.Radius = t_5;
1294 }
1295
1296 #[inline]
1300 pub fn CreateFromBoundingBox(Out: &mut Self, box_: &BoundingBox) {
1301 Out.Center = box_.Center;
1302 let vExtents: XMVECTOR = XMLoadFloat3(&box_.Extents);
1303 Out.Radius = XMVectorGetX(XMVector3Length(vExtents));
1304 }
1305
1306 #[inline]
1310 pub fn CreateFromBoundingOrientedBox(Out: &mut Self, box_: &BoundingOrientedBox) {
1311 Out.Center = box_.Center;
1313 let vExtents: XMVECTOR = XMLoadFloat3(&box_.Extents);
1314 Out.Radius = XMVectorGetX(XMVector3Length(vExtents));
1315 }
1316
1317 #[inline]
1321 pub fn CreateFromPoints<'a>(Out: &mut Self, pPoints: impl Iterator<Item=&'a XMFLOAT3> + Clone) {
1322 let mut MinX = g_XMInfinity.v();
1331 let mut MaxX = g_XMNegInfinity.v();
1332 let mut MinY = g_XMInfinity.v();
1333 let mut MaxY = g_XMNegInfinity.v();
1334 let mut MinZ = g_XMInfinity.v();
1335 let mut MaxZ = g_XMNegInfinity.v();
1336
1337 for (i, pPoint) in pPoints.clone().enumerate()
1339 {
1340 let Point = XMLoadFloat3(pPoint);
1342
1343 if i == 0 {
1344 MinX = Point;
1345 MaxX = Point;
1346 MinY = Point;
1347 MaxY = Point;
1348 MinZ = Point;
1349 MaxZ = Point;
1350 }
1351
1352 let px: f32 = XMVectorGetX(Point);
1353 let py: f32 = XMVectorGetY(Point);
1354 let pz: f32 = XMVectorGetZ(Point);
1355
1356 if (px < XMVectorGetX(MinX)) {
1357 MinX = Point;
1358 }
1359
1360 if (px > XMVectorGetX(MaxX)) {
1361 MaxX = Point;
1362 }
1363
1364 if (py < XMVectorGetY(MinY)) {
1365 MinY = Point;
1366 }
1367
1368 if (py > XMVectorGetY(MaxY)) {
1369 MaxY = Point;
1370 }
1371
1372 if (pz < XMVectorGetZ(MinZ)) {
1373 MinZ = Point;
1374 }
1375
1376 if (pz > XMVectorGetZ(MaxZ)) {
1377 MaxZ = Point;
1378 }
1379 }
1380
1381 let DeltaX: XMVECTOR = XMVectorSubtract(MaxX, MinX);
1383 let DistX: XMVECTOR = XMVector3Length(DeltaX);
1384
1385 let DeltaY: XMVECTOR = XMVectorSubtract(MaxY, MinY);
1386 let DistY: XMVECTOR = XMVector3Length(DeltaY);
1387
1388 let DeltaZ: XMVECTOR = XMVectorSubtract(MaxZ, MinZ);
1389 let DistZ: XMVECTOR = XMVector3Length(DeltaZ);
1390
1391 let mut vCenter: XMVECTOR;
1392 let mut vRadius: XMVECTOR;
1393
1394 if (XMVector3Greater(DistX, DistY))
1395 {
1396 if (XMVector3Greater(DistX, DistZ))
1397 {
1398 vCenter = XMVectorLerp(MaxX, MinX, 0.5);
1400 vRadius = XMVectorScale(DistX, 0.5);
1401 }
1402 else
1403 {
1404 vCenter = XMVectorLerp(MaxZ, MinZ, 0.5);
1406 vRadius = XMVectorScale(DistZ, 0.5);
1407 }
1408 }
1409 else {
1411 if (XMVector3Greater(DistY, DistZ))
1412 {
1413 vCenter = XMVectorLerp(MaxY, MinY, 0.5);
1415 vRadius = XMVectorScale(DistY, 0.5);
1416 }
1417 else
1418 {
1419 vCenter = XMVectorLerp(MaxZ, MinZ, 0.5);
1421 vRadius = XMVectorScale(DistZ, 0.5);
1422 }
1423 }
1424
1425 for pPoint in pPoints
1427 {
1428 let Point: XMVECTOR = XMLoadFloat3(pPoint);
1429
1430 let Delta: XMVECTOR = XMVectorSubtract(Point, vCenter);
1431
1432 let Dist: XMVECTOR = XMVector3Length(Delta);
1433
1434 if (XMVector3Greater(Dist, vRadius))
1435 {
1436 vRadius = XMVectorScale(XMVectorAdd(vRadius, Dist), 0.5);
1438 vCenter = XMVectorAdd(vCenter, XMVectorMultiply(XMVectorSubtract(XMVectorReplicate(1.0), XMVectorDivide(vRadius, Dist)), Delta));
1439 }
1440 }
1441
1442 XMStoreFloat3(&mut Out.Center, vCenter);
1443 XMStoreFloat(&mut Out.Radius, vRadius);
1444 }
1445
1446 #[inline]
1448 pub fn CreateFromFrustum(Out: &mut Self, fr: &BoundingFrustum) {
1449 let mut Corners: [XMFLOAT3; BoundingFrustum::CORNER_COUNT] = unsafe { undefined() };
1450 fr.GetCorners(&mut Corners);
1451 BoundingSphere::CreateFromPoints(Out, Corners.iter())
1452 }
1453}
1454
1455#[test]
1456fn test_BoundingSphere_CreateFromPoints() {
1457 let mut bounds: BoundingSphere = BoundingSphere::default();
1458 let points = &[
1459 XMFLOAT3 { x: 1.0, y: 0.0, z: 1.0 },
1460 XMFLOAT3 { x: -1.0, y: 0.0, z: -1.0 },
1461 ];
1462 BoundingSphere::CreateFromPoints(&mut bounds, points.iter());
1463
1464 assert_eq!(0.0, bounds.Center.x);
1465 assert_eq!(0.0, bounds.Center.y);
1466 assert_eq!(0.0, bounds.Center.z);
1467 assert_eq!(2.0f32.sqrt(), bounds.Radius);
1468
1469 assert_eq!(ContainmentType::CONTAINS, bounds.ContainsPoint(XMVectorSet(0.5, 0.5, 0.5, 0.0)));
1470 assert_eq!(ContainmentType::DISJOINT, bounds.ContainsPoint(XMVectorSet(3.0, 3.0, 3.0, 0.0)));
1471
1472 let points_f32x3: &[[f32; 3]] = &[
1473 [ 1.0, 0.0, 1.0 ],
1474 [-1.0, 0.0, -1.0 ],
1475 ];
1476 BoundingSphere::CreateFromPoints(&mut bounds, points_f32x3.iter().map(Into::into));
1477
1478 assert_eq!(0.0, bounds.Center.x);
1479 assert_eq!(0.0, bounds.Center.y);
1480 assert_eq!(0.0, bounds.Center.z);
1481 assert_eq!(2.0f32.sqrt(), bounds.Radius);
1482
1483 assert_eq!(ContainmentType::CONTAINS, bounds.ContainsPoint(XMVectorSet(0.5, 0.5, 0.5, 0.0)));
1484 assert_eq!(ContainmentType::DISJOINT, bounds.ContainsPoint(XMVectorSet(3.0, 3.0, 3.0, 0.0)));
1485
1486 let mut bounds: BoundingSphere = BoundingSphere::default();
1487 let points = &[];
1488 BoundingSphere::CreateFromPoints(&mut bounds, points.iter());
1489
1490 assert!(bounds.Center.x.is_nan());
1492 assert!(bounds.Center.y.is_nan());
1493 assert!(bounds.Center.z.is_nan());
1494 assert!(bounds.Radius.is_infinite());
1495
1496 assert_eq!(ContainmentType::DISJOINT, bounds.ContainsPoint(XMVectorSet(0.0, 0.0, 0.0, 0.0)));
1497}
1498
1499impl BoundingBox {
1502 pub const CORNER_COUNT: usize = 8;
1503
1504 #[inline]
1505 pub fn GetCorners(&self, Corners: &mut [XMFLOAT3; BoundingBox::CORNER_COUNT]) {
1506 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
1508 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
1509
1510 for i in 0..BoundingBox::CORNER_COUNT
1511 {
1512 let C: XMVECTOR = XMVectorMultiplyAdd(vExtents, g_BoxOffset[i].v(), vCenter);
1513 XMStoreFloat3(&mut Corners[i], C);
1514 }
1515 }
1516
1517 #[inline]
1533 pub fn TransformMatrix(&self, Out: &mut Self, M: FXMMATRIX) {
1534 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
1536 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
1537
1538 let mut Corner: XMVECTOR = XMVectorMultiplyAdd(vExtents, g_BoxOffset[0].v(), vCenter);
1540 Corner = XMVector3Transform(Corner, M);
1541
1542 let mut Min: XMVECTOR = Corner;
1543 let mut Max: XMVECTOR = Corner;
1544
1545 for i in 1 .. BoundingBox::CORNER_COUNT
1546 {
1547 Corner = XMVectorMultiplyAdd(vExtents, g_BoxOffset[i].v(), vCenter);
1548 Corner = XMVector3Transform(Corner, M);
1549
1550 Min = XMVectorMin(Min, Corner);
1551 Max = XMVectorMax(Max, Corner);
1552 }
1553
1554 XMStoreFloat3(&mut Out.Center, XMVectorScale(XMVectorAdd(Min, Max), 0.5));
1556 XMStoreFloat3(&mut Out.Extents, XMVectorScale(XMVectorSubtract(Max, Min), 0.5));
1557 }
1558
1559 #[inline]
1579 pub fn TransformDecomposed(&self, Out: &mut Self, Scale: f32, Rotation: FXMVECTOR, Translation: FXMVECTOR) {
1580 debug_assert!(internal::XMQuaternionIsUnit(Rotation));
1581
1582 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
1584 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
1585
1586 let VectorScale: XMVECTOR = XMVectorReplicate(Scale);
1587
1588 let mut Corner: XMVECTOR = XMVectorMultiplyAdd(vExtents, g_BoxOffset[0].v(), vCenter);
1590 Corner = XMVectorAdd(XMVector3Rotate(XMVectorMultiply(Corner, VectorScale), Rotation), Translation);
1591
1592 let mut Min: XMVECTOR = Corner;
1593 let mut Max: XMVECTOR = Corner;
1594
1595 for i in 1 .. BoundingBox::CORNER_COUNT
1596 {
1597 Corner = XMVectorMultiplyAdd(vExtents, g_BoxOffset[i].v(), vCenter);
1598 Corner = XMVectorAdd(XMVector3Rotate(XMVectorMultiply(Corner, VectorScale), Rotation), Translation);
1599
1600 Min = XMVectorMin(Min, Corner);
1601 Max = XMVectorMax(Max, Corner);
1602 }
1603
1604 XMStoreFloat3(&mut Out.Center, XMVectorScale(XMVectorAdd(Min, Max), 0.5));
1606 XMStoreFloat3(&mut Out.Extents, XMVectorScale(XMVectorSubtract(Max, Min), 0.5));
1607 }
1608
1609 #[inline]
1623 pub fn ContainsPoint(&self, Point: FXMVECTOR) -> ContainmentType {
1624 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
1625 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
1626
1627 return if XMVector3InBounds(XMVectorSubtract(Point, vCenter), vExtents) { CONTAINS } else { DISJOINT };
1628 }
1629
1630 #[inline]
1648 pub fn ContainsTriangle(&self, V0: FXMVECTOR, V1: FXMVECTOR, V2: FXMVECTOR) -> ContainmentType {
1649 if (!self.IntersectsTriangle(V0, V1, V2)) {
1650 return DISJOINT;
1651 }
1652
1653 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
1654 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
1655
1656 let mut d: XMVECTOR = XMVectorAbs(XMVectorSubtract(V0, vCenter));
1657 let mut Inside: XMVECTOR = XMVectorLessOrEqual(d, vExtents);
1658
1659 d = XMVectorAbs(XMVectorSubtract(V1, vCenter));
1660 Inside = XMVectorAndInt(Inside, XMVectorLessOrEqual(d, vExtents));
1661
1662 d = XMVectorAbs(XMVectorSubtract(V2, vCenter));
1663 Inside = XMVectorAndInt(Inside, XMVectorLessOrEqual(d, vExtents));
1664
1665 return if (XMVector3EqualInt(Inside, XMVectorTrueInt())) { CONTAINS } else { INTERSECTS };
1666 }
1667
1668 #[inline]
1672 pub fn ContainsSphere(&self, sh: &BoundingSphere) -> ContainmentType {
1673 let SphereCenter: XMVECTOR = XMLoadFloat3(&sh.Center);
1674 let SphereRadius: XMVECTOR = XMVectorReplicatePtr(&sh.Radius);
1675
1676 let BoxCenter: XMVECTOR = XMLoadFloat3(&self.Center);
1677 let BoxExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
1678
1679 let BoxMin: XMVECTOR = XMVectorSubtract(BoxCenter, BoxExtents);
1680 let BoxMax: XMVECTOR = XMVectorAdd(BoxCenter, BoxExtents);
1681
1682 let mut d: XMVECTOR = XMVectorZero();
1688
1689 let LessThanMin: XMVECTOR = XMVectorLess(SphereCenter, BoxMin);
1691 let GreaterThanMax: XMVECTOR = XMVectorGreater(SphereCenter, BoxMax);
1692
1693 let MinDelta: XMVECTOR = XMVectorSubtract(SphereCenter, BoxMin);
1694 let MaxDelta: XMVECTOR = XMVectorSubtract(SphereCenter, BoxMax);
1695
1696 d = XMVectorSelect(d, MinDelta, LessThanMin);
1698 d = XMVectorSelect(d, MaxDelta, GreaterThanMax);
1699
1700 let d2: XMVECTOR = XMVector3Dot(d, d);
1702
1703 if (XMVector3Greater(d2, XMVectorMultiply(SphereRadius, SphereRadius))) {
1704 return DISJOINT;
1705 }
1706
1707 let mut InsideAll: XMVECTOR = XMVectorLessOrEqual(XMVectorAdd(BoxMin, SphereRadius), SphereCenter);
1708 InsideAll = XMVectorAndInt(InsideAll, XMVectorLessOrEqual(SphereCenter, XMVectorSubtract(BoxMax, SphereRadius)));
1709 InsideAll = XMVectorAndInt(InsideAll, XMVectorGreater(XMVectorSubtract(BoxMax, BoxMin), SphereRadius));
1710
1711 return if (XMVector3EqualInt(InsideAll, XMVectorTrueInt())) { CONTAINS } else { INTERSECTS };
1712 }
1713
1714 #[inline]
1718 pub fn ContainsBox(&self, box_: &BoundingBox) -> ContainmentType {
1719 let CenterA: XMVECTOR = XMLoadFloat3(&self.Center);
1720 let ExtentsA: XMVECTOR = XMLoadFloat3(&self.Extents);
1721
1722 let CenterB: XMVECTOR = XMLoadFloat3(&box_.Center);
1723 let ExtentsB: XMVECTOR = XMLoadFloat3(&box_.Extents);
1724
1725 let MinA: XMVECTOR = XMVectorSubtract(CenterA, ExtentsA);
1726 let MaxA: XMVECTOR = XMVectorAdd(CenterA, ExtentsA);
1727
1728 let MinB: XMVECTOR = XMVectorSubtract(CenterB, ExtentsB);
1729 let MaxB: XMVECTOR = XMVectorAdd(CenterB, ExtentsB);
1730
1731 let Disjoint: XMVECTOR = XMVectorOrInt(XMVectorGreater(MinA, MaxB), XMVectorGreater(MinB, MaxA));
1733
1734 if (internal::XMVector3AnyTrue(Disjoint)) {
1735 return DISJOINT;
1736 }
1737
1738 let Inside: XMVECTOR = XMVectorAndInt(XMVectorLessOrEqual(MinA, MinB), XMVectorLessOrEqual(MaxB, MaxA));
1740
1741 return if internal::XMVector3AllTrue(Inside) { CONTAINS } else { INTERSECTS };
1742 }
1743
1744 #[inline]
1748 pub fn ContainsOrientedBox(&self, box_: &BoundingOrientedBox) -> ContainmentType {
1749 if (!box_.IntersectsBox(self)) {
1750 return DISJOINT;
1751 }
1752
1753 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
1754 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
1755
1756 let oCenter: XMVECTOR = XMVectorSubtract(XMLoadFloat3(&box_.Center), vCenter);
1758
1759 let oExtents: XMVECTOR = XMLoadFloat3(&box_.Extents);
1760 let oOrientation: XMVECTOR = XMLoadFloat4(&box_.Orientation);
1761
1762 debug_assert!(internal::XMQuaternionIsUnit(oOrientation));
1763
1764 let mut Inside: XMVECTOR = XMVectorTrueInt();
1765
1766 for i in 0 .. BoundingOrientedBox::CORNER_COUNT
1768 {
1769 let C: XMVECTOR = XMVectorAdd(XMVector3Rotate(XMVectorMultiply(oExtents, g_BoxOffset[i].v()), oOrientation), oCenter);
1770 let d: XMVECTOR = XMVectorAbs(C);
1771 Inside = XMVectorAndInt(Inside, XMVectorLessOrEqual(d, vExtents));
1772 }
1773
1774 return if (XMVector3EqualInt(Inside, XMVectorTrueInt())) { CONTAINS } else { INTERSECTS };
1775 }
1776
1777 #[inline]
1781 pub fn ContainsFrustum(&self, fr: &BoundingFrustum) -> ContainmentType {
1782 if (!fr.IntersectsBox(self)) {
1783 return DISJOINT;
1784 }
1785
1786 let mut Corners: [XMFLOAT3; BoundingFrustum::CORNER_COUNT] = unsafe { undefined() };
1787 fr.GetCorners(&mut Corners);
1788
1789 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
1790 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
1791
1792 let mut Inside: XMVECTOR = XMVectorTrueInt();
1793
1794 for i in 0 ..BoundingFrustum::CORNER_COUNT
1795 {
1796 let Point: XMVECTOR = XMLoadFloat3(&Corners[i]);
1797 let d: XMVECTOR = XMVectorAbs(XMVectorSubtract(Point, vCenter));
1798 Inside = XMVectorAndInt(Inside, XMVectorLessOrEqual(d, vExtents));
1799 }
1800
1801 return if (XMVector3EqualInt(Inside, XMVectorTrueInt())) { CONTAINS } else { INTERSECTS };
1802 }
1803
1804 #[inline]
1808 pub fn IntersectsSphere(&self, sh: &BoundingSphere) -> bool {
1809 let SphereCenter: XMVECTOR = XMLoadFloat3(&sh.Center);
1810 let SphereRadius: XMVECTOR = XMVectorReplicatePtr(&sh.Radius);
1811
1812 let BoxCenter: XMVECTOR = XMLoadFloat3(&self.Center);
1813 let BoxExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
1814
1815 let BoxMin: XMVECTOR = XMVectorSubtract(BoxCenter, BoxExtents);
1816 let BoxMax: XMVECTOR = XMVectorAdd(BoxCenter, BoxExtents);
1817
1818 let mut d: XMVECTOR = XMVectorZero();
1824
1825 let LessThanMin: XMVECTOR = XMVectorLess(SphereCenter, BoxMin);
1827 let GreaterThanMax: XMVECTOR = XMVectorGreater(SphereCenter, BoxMax);
1828
1829 let MinDelta: XMVECTOR = XMVectorSubtract(SphereCenter, BoxMin);
1830 let MaxDelta: XMVECTOR = XMVectorSubtract(SphereCenter, BoxMax);
1831
1832 d = XMVectorSelect(d, MinDelta, LessThanMin);
1834 d = XMVectorSelect(d, MaxDelta, GreaterThanMax);
1835
1836 let d2: XMVECTOR = XMVector3Dot(d, d);
1838
1839 return XMVector3LessOrEqual(d2, XMVectorMultiply(SphereRadius, SphereRadius));
1840 }
1841
1842 #[inline]
1846 pub fn IntersectsBox(&self, box_: &BoundingBox) -> bool {
1847 let CenterA: XMVECTOR = XMLoadFloat3(&self.Center);
1848 let ExtentsA: XMVECTOR = XMLoadFloat3(&self.Extents);
1849
1850 let CenterB: XMVECTOR = XMLoadFloat3(&box_.Center);
1851 let ExtentsB: XMVECTOR = XMLoadFloat3(&box_.Extents);
1852
1853 let MinA: XMVECTOR = XMVectorSubtract(CenterA, ExtentsA);
1854 let MaxA: XMVECTOR = XMVectorAdd(CenterA, ExtentsA);
1855
1856 let MinB: XMVECTOR = XMVectorSubtract(CenterB, ExtentsB);
1857 let MaxB: XMVECTOR = XMVectorAdd(CenterB, ExtentsB);
1858
1859 let Disjoint: XMVECTOR = XMVectorOrInt(XMVectorGreater(MinA, MaxB), XMVectorGreater(MinB, MaxA));
1861
1862 return !internal::XMVector3AnyTrue(Disjoint);
1863 }
1864
1865 #[inline]
1869 pub fn IntersectsOrientedBox(&self, box_: &BoundingOrientedBox) -> bool {
1870 return box_.IntersectsBox(self);
1871 }
1872
1873 #[inline]
1877 pub fn IntersectsFrustum(&self, fr: &BoundingFrustum) -> bool {
1878 return fr.IntersectsBox(self);
1879 }
1880
1881 #[inline]
1899 pub fn IntersectsTriangle(&self, V0: FXMVECTOR, V1: FXMVECTOR, V2: FXMVECTOR) -> bool {
1900 let Zero: XMVECTOR = XMVectorZero();
1901
1902 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
1904 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
1905
1906 let BoxMin: XMVECTOR = XMVectorSubtract(vCenter, vExtents);
1907 let BoxMax: XMVECTOR = XMVectorAdd(vCenter, vExtents);
1908
1909 let TriMin: XMVECTOR = XMVectorMin(XMVectorMin(V0, V1), V2);
1912 let TriMax: XMVECTOR = XMVectorMax(XMVectorMax(V0, V1), V2);
1913
1914 let Disjoint: XMVECTOR = XMVectorOrInt(XMVectorGreater(TriMin, BoxMax), XMVectorGreater(BoxMin, TriMax));
1916 if (internal::XMVector3AnyTrue(Disjoint)) {
1917 return false;
1918 }
1919
1920 let Normal: XMVECTOR = XMVector3Cross(XMVectorSubtract(V1, V0), XMVectorSubtract(V2, V0));
1922 let Dist: XMVECTOR = XMVector3Dot(Normal, V0);
1923
1924 debug_assert!(!XMVector3Equal(Normal, Zero));
1926
1927 let NormalSelect: XMVECTOR = XMVectorGreater(Normal, Zero);
1930 let V_Min: XMVECTOR = XMVectorSelect(BoxMax, BoxMin, NormalSelect);
1931 let V_Max: XMVECTOR = XMVectorSelect(BoxMin, BoxMax, NormalSelect);
1932
1933 let MinDist: XMVECTOR = XMVector3Dot(V_Min, Normal);
1935 let MaxDist: XMVECTOR = XMVector3Dot(V_Max, Normal);
1936
1937 let mut NoIntersection: XMVECTOR = XMVectorGreater(MinDist, Dist);
1938 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(MaxDist, Dist));
1939
1940 let TV0: XMVECTOR = XMVectorSubtract(V0, vCenter);
1942 let TV1: XMVECTOR = XMVectorSubtract(V1, vCenter);
1943 let TV2: XMVECTOR = XMVectorSubtract(V2, vCenter);
1944
1945 let mut e0: XMVECTOR = XMVectorSubtract(TV1, TV0);
1947 let mut e1: XMVECTOR = XMVectorSubtract(TV2, TV1);
1948 let mut e2: XMVECTOR = XMVectorSubtract(TV0, TV2);
1949
1950 e0 = XMVectorInsert(e0, Zero, 0, 0, 0, 0, 1);
1953 e1 = XMVectorInsert(e1, Zero, 0, 0, 0, 0, 1);
1954 e2 = XMVectorInsert(e2, Zero, 0, 0, 0, 0, 1);
1955
1956 let mut Axis: XMVECTOR;
1957 let mut p0: XMVECTOR;
1958 let mut p1: XMVECTOR;
1959 let mut p2: XMVECTOR;
1960 let mut Min: XMVECTOR;
1961 let mut Max: XMVECTOR;
1962 let mut Radius: XMVECTOR;
1963
1964 Axis = <(XM_PERMUTE_0W, XM_PERMUTE_1Z, XM_PERMUTE_0Y, XM_PERMUTE_0X)>::XMVectorPermute(e0, XMVectorNegate(e0));
1966 p0 = XMVector3Dot(TV0, Axis);
1967 p2 = XMVector3Dot(TV2, Axis);
1969 Min = XMVectorMin(p0, p2);
1970 Max = XMVectorMax(p0, p2);
1971 Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
1972 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
1973 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));
1974
1975 Axis = <(XM_PERMUTE_0W, XM_PERMUTE_1Z, XM_PERMUTE_0Y, XM_PERMUTE_0X)>::XMVectorPermute(e1, XMVectorNegate(e1));
1977 p0 = XMVector3Dot(TV0, Axis);
1978 p1 = XMVector3Dot(TV1, Axis);
1979 Min = XMVectorMin(p0, p1);
1981 Max = XMVectorMax(p0, p1);
1982 Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
1983 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
1984 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));
1985
1986 Axis = <(XM_PERMUTE_0W, XM_PERMUTE_1Z, XM_PERMUTE_0Y, XM_PERMUTE_0X)>::XMVectorPermute(e2, XMVectorNegate(e2));
1988 p0 = XMVector3Dot(TV0, Axis);
1989 p1 = XMVector3Dot(TV1, Axis);
1990 Min = XMVectorMin(p0, p1);
1992 Max = XMVectorMax(p0, p1);
1993 Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
1994 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
1995 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));
1996
1997 Axis = <(XM_PERMUTE_0Z, XM_PERMUTE_0W, XM_PERMUTE_1X, XM_PERMUTE_0Y)>::XMVectorPermute(e0, XMVectorNegate(e0));
1999 p0 = XMVector3Dot(TV0, Axis);
2000 p2 = XMVector3Dot(TV2, Axis);
2002 Min = XMVectorMin(p0, p2);
2003 Max = XMVectorMax(p0, p2);
2004 Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
2005 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
2006 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));
2007
2008 Axis = <(XM_PERMUTE_0Z, XM_PERMUTE_0W, XM_PERMUTE_1X, XM_PERMUTE_0Y)>::XMVectorPermute(e1, XMVectorNegate(e1));
2010 p0 = XMVector3Dot(TV0, Axis);
2011 p1 = XMVector3Dot(TV1, Axis);
2012 Min = XMVectorMin(p0, p1);
2014 Max = XMVectorMax(p0, p1);
2015 Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
2016 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
2017 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));
2018
2019 Axis = <(XM_PERMUTE_0Z, XM_PERMUTE_0W, XM_PERMUTE_1X, XM_PERMUTE_0Y)>::XMVectorPermute(e2, XMVectorNegate(e2));
2021 p0 = XMVector3Dot(TV0, Axis);
2022 p1 = XMVector3Dot(TV1, Axis);
2023 Min = XMVectorMin(p0, p1);
2025 Max = XMVectorMax(p0, p1);
2026 Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
2027 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
2028 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));
2029
2030 Axis = <(XM_PERMUTE_1Y, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_0Z)>::XMVectorPermute(e0, XMVectorNegate(e0));
2032 p0 = XMVector3Dot(TV0, Axis);
2033 p2 = XMVector3Dot(TV2, Axis);
2035 Min = XMVectorMin(p0, p2);
2036 Max = XMVectorMax(p0, p2);
2037 Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
2038 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
2039 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));
2040
2041 Axis = <(XM_PERMUTE_1Y, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_0Z)>::XMVectorPermute(e1, XMVectorNegate(e1));
2043 p0 = XMVector3Dot(TV0, Axis);
2044 p1 = XMVector3Dot(TV1, Axis);
2045 Min = XMVectorMin(p0, p1);
2047 Max = XMVectorMax(p0, p1);
2048 Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
2049 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
2050 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));
2051
2052 Axis = <(XM_PERMUTE_1Y, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_0Z)>::XMVectorPermute(e2, XMVectorNegate(e2));
2054 p0 = XMVector3Dot(TV0, Axis);
2055 p1 = XMVector3Dot(TV1, Axis);
2056 Min = XMVectorMin(p0, p1);
2058 Max = XMVectorMax(p0, p1);
2059 Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
2060 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
2061 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));
2062
2063 return XMVector4NotEqualInt(NoIntersection, XMVectorTrueInt());
2064 }
2065
2066 #[inline]
2080 pub fn IntersectsPlane(&self, Plane: FXMVECTOR) -> PlaneIntersectionType {
2081 debug_assert!(internal::XMPlaneIsUnit(Plane));
2082
2083 let mut vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
2085 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
2086
2087 vCenter = XMVectorInsert(vCenter, XMVectorSplatOne(), 0, 0, 0, 0, 1);
2090
2091 let mut Outside: XMVECTOR = unsafe { undefined() };
2092 let mut Inside: XMVECTOR = unsafe { undefined() };
2093 internal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane, &mut Outside, &mut Inside);
2094
2095 if (XMVector4EqualInt(Outside, XMVectorTrueInt())) {
2097 return FRONT;
2098 }
2099
2100 if (XMVector4EqualInt(Inside, XMVectorTrueInt())) {
2102 return BACK;
2103 }
2104
2105 return INTERSECTING;
2107 }
2108
2109 #[inline]
2132 pub fn IntersectsRay(&self, Origin: FXMVECTOR, Direction: FXMVECTOR, Dist: &mut f32) -> bool {
2133 debug_assert!(internal::XMVector3IsUnit(Direction));
2134
2135 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
2137 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
2138
2139 let TOrigin: XMVECTOR = XMVectorSubtract(vCenter, Origin);
2141
2142 let AxisDotOrigin: XMVECTOR = TOrigin;
2145 let AxisDotDirection: XMVECTOR = Direction;
2146
2147 let IsParallel: XMVECTOR = XMVectorLessOrEqual(XMVectorAbs(AxisDotDirection), g_RayEpsilon.v());
2149
2150 let InverseAxisDotDirection: XMVECTOR = XMVectorReciprocal(AxisDotDirection);
2152 let t1: XMVECTOR = XMVectorMultiply(XMVectorSubtract(AxisDotOrigin, vExtents), InverseAxisDotDirection);
2153 let t2: XMVECTOR = XMVectorMultiply(XMVectorAdd(AxisDotOrigin, vExtents), InverseAxisDotDirection);
2154
2155 let mut t_min: XMVECTOR = XMVectorSelect(XMVectorMin(t1, t2), g_FltMin.v(), IsParallel);
2158 let mut t_max: XMVECTOR = XMVectorSelect(XMVectorMax(t1, t2), g_FltMax.v(), IsParallel);
2159
2160 t_min = XMVectorMax(t_min, XMVectorSplatY(t_min)); t_min = XMVectorMax(t_min, XMVectorSplatZ(t_min)); t_max = XMVectorMin(t_max, XMVectorSplatY(t_max)); t_max = XMVectorMin(t_max, XMVectorSplatZ(t_max)); let mut NoIntersection: XMVECTOR = XMVectorGreater(XMVectorSplatX(t_min), XMVectorSplatX(t_max));
2169
2170 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(XMVectorSplatX(t_max), XMVectorZero()));
2172
2173 let ParallelOverlap: XMVECTOR = XMVectorInBounds(AxisDotOrigin, vExtents);
2175 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorAndCInt(IsParallel, ParallelOverlap));
2176
2177 if (!internal::XMVector3AnyTrue(NoIntersection))
2178 {
2179 XMStoreFloat(Dist, t_min);
2181 return true;
2182 }
2183
2184 *Dist = 0.0;
2185 return false;
2186 }
2187
2188 #[inline]
2192 pub fn ContainedBy(
2193 &self,
2194 Plane0: FXMVECTOR,
2195 Plane1: FXMVECTOR,
2196 Plane2: GXMVECTOR,
2197 Plane3: HXMVECTOR,
2198 Plane4: HXMVECTOR,
2199 Plane5: HXMVECTOR,
2200 ) -> ContainmentType
2201 {
2202 let mut vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
2204 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
2205
2206 vCenter = XMVectorInsert(vCenter, XMVectorSplatOne(), 0, 0, 0, 0, 1);
2209
2210 let mut Outside: XMVECTOR = unsafe { undefined() };
2211 let mut Inside: XMVECTOR = unsafe { undefined() };
2212
2213 internal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane0, &mut Outside, &mut Inside);
2215
2216 let mut AnyOutside: XMVECTOR = Outside;
2217 let mut AllInside: XMVECTOR = Inside;
2218
2219 internal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane1, &mut Outside, &mut Inside);
2220 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
2221 AllInside = XMVectorAndInt(AllInside, Inside);
2222
2223 internal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane2, &mut Outside, &mut Inside);
2224 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
2225 AllInside = XMVectorAndInt(AllInside, Inside);
2226
2227 internal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane3, &mut Outside, &mut Inside);
2228 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
2229 AllInside = XMVectorAndInt(AllInside, Inside);
2230
2231 internal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane4, &mut Outside, &mut Inside);
2232 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
2233 AllInside = XMVectorAndInt(AllInside, Inside);
2234
2235 internal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane5, &mut Outside, &mut Inside);
2236 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
2237 AllInside = XMVectorAndInt(AllInside, Inside);
2238
2239 if (XMVector4EqualInt(AnyOutside, XMVectorTrueInt())) {
2241 return DISJOINT;
2242 }
2243
2244 if (XMVector4EqualInt(AllInside, XMVectorTrueInt())) {
2246 return CONTAINS;
2247 }
2248
2249 return INTERSECTS;
2251 }
2252
2253 #[inline]
2257 pub fn CreateMerged(Out: &mut Self, b1: &Self, b2: &Self) {
2258 let b1Center: XMVECTOR = XMLoadFloat3(&b1.Center);
2259 let b1Extents: XMVECTOR = XMLoadFloat3(&b1.Extents);
2260
2261 let b2Center: XMVECTOR = XMLoadFloat3(&b2.Center);
2262 let b2Extents: XMVECTOR = XMLoadFloat3(&b2.Extents);
2263
2264 let mut Min: XMVECTOR = XMVectorSubtract(b1Center, b1Extents);
2265 Min = XMVectorMin(Min, XMVectorSubtract(b2Center, b2Extents));
2266
2267 let mut Max: XMVECTOR = XMVectorAdd(b1Center, b1Extents);
2268 Max = XMVectorMax(Max, XMVectorAdd(b2Center, b2Extents));
2269
2270 debug_assert!(XMVector3LessOrEqual(Min, Max));
2271
2272 XMStoreFloat3(&mut Out.Center, XMVectorScale(XMVectorAdd(Min, Max), 0.5));
2273 XMStoreFloat3(&mut Out.Extents, XMVectorScale(XMVectorSubtract(Max, Min), 0.5));
2274 }
2275
2276 #[inline]
2280 pub fn CreateFromSphere(Out: &mut Self, sh: &BoundingSphere) {
2281 let spCenter: XMVECTOR = XMLoadFloat3(&sh.Center);
2282 let shRadius: XMVECTOR = XMVectorReplicatePtr(&sh.Radius);
2283
2284 let Min: XMVECTOR = XMVectorSubtract(spCenter, shRadius);
2285 let Max: XMVECTOR = XMVectorAdd(spCenter, shRadius);
2286
2287 debug_assert!(XMVector3LessOrEqual(Min, Max));
2288
2289 XMStoreFloat3(&mut Out.Center, XMVectorScale(XMVectorAdd(Min, Max), 0.5));
2290 XMStoreFloat3(&mut Out.Extents, XMVectorScale(XMVectorSubtract(Max, Min), 0.5));
2291 }
2292
2293 #[inline]
2297 pub fn CreateFromPoints<'a>(Out: &mut Self, pPoints: impl Iterator<Item=&'a XMFLOAT3>) {
2298 let mut vMin: XMVECTOR = g_XMInfinity.v();
2304 let mut vMax: XMVECTOR = g_XMNegInfinity.v();
2305
2306 for (i, pPoint) in pPoints.enumerate()
2307 {
2308 let Point: XMVECTOR = XMLoadFloat3(pPoint);
2309 if i == 0 {
2310 vMin = Point;
2311 vMax = Point;
2312 } else {
2313 vMin = XMVectorMin(vMin, Point);
2314 vMax = XMVectorMax(vMax, Point);
2315 }
2316 }
2317
2318 XMStoreFloat3(&mut Out.Center, XMVectorScale(XMVectorAdd(vMin, vMax), 0.5));
2320 XMStoreFloat3(&mut Out.Extents, XMVectorScale(XMVectorSubtract(vMax, vMin), 0.5));
2321 }
2322}
2323
2324impl BoundingOrientedBox {
2327 pub const CORNER_COUNT: usize = 8;
2328
2329 #[inline]
2345 pub fn TransformMatrix(&self, Out: &mut Self, M: FXMMATRIX) {
2346 let mut vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
2348 let mut vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
2349 let mut vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
2350
2351 debug_assert!(internal::XMQuaternionIsUnit(vOrientation));
2352
2353 unsafe {
2354 let mut nM: XMMATRIX = undefined();
2356 nM.r[0] = XMVector3Normalize(M.r[0]);
2357 nM.r[1] = XMVector3Normalize(M.r[1]);
2358 nM.r[2] = XMVector3Normalize(M.r[2]);
2359 nM.r[3] = g_XMIdentityR3.v;
2360 let Rotation: XMVECTOR = XMQuaternionRotationMatrix(nM);
2361 vOrientation = XMQuaternionMultiply(vOrientation, Rotation);
2362
2363 vCenter = XMVector3Transform(vCenter, M);
2365
2366 let dX: XMVECTOR = XMVector3Length(M.r[0]);
2368 let dY: XMVECTOR = XMVector3Length(M.r[1]);
2369 let dZ: XMVECTOR = XMVector3Length(M.r[2]);
2370
2371 let mut VectorScale: XMVECTOR = XMVectorSelect(dY, dX, g_XMSelect1000.v);
2372 VectorScale = XMVectorSelect(dZ, VectorScale, g_XMSelect1100.v);
2373 vExtents = XMVectorMultiply(vExtents, VectorScale);
2374 }
2375
2376 XMStoreFloat3(&mut Out.Center, vCenter);
2378 XMStoreFloat3(&mut Out.Extents, vExtents);
2379 XMStoreFloat4(&mut Out.Orientation, vOrientation);
2380 }
2381
2382 #[inline]
2402 pub fn TransformDecomposed(&self, Out: &mut Self, Scale: f32, Rotation: FXMVECTOR, Translation: FXMVECTOR) {
2403 debug_assert!(internal::XMQuaternionIsUnit(Rotation));
2404
2405 let mut vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
2407 let mut vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
2408 let mut vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
2409
2410 debug_assert!(internal::XMQuaternionIsUnit(vOrientation));
2411
2412 vOrientation = XMQuaternionMultiply(vOrientation, Rotation);
2414
2415 let VectorScale: XMVECTOR = XMVectorReplicate(Scale);
2417 vCenter = XMVectorAdd(XMVector3Rotate(XMVectorMultiply(vCenter, VectorScale), Rotation), Translation);
2418
2419 vExtents = XMVectorMultiply(vExtents, VectorScale);
2421
2422 XMStoreFloat3(&mut Out.Center, vCenter);
2424 XMStoreFloat3(&mut Out.Extents, vExtents);
2425 XMStoreFloat4(&mut Out.Orientation, vOrientation);
2426 }
2427
2428 #[inline]
2442 pub fn ContainsPoint(&self, Point: FXMVECTOR) -> ContainmentType {
2443 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
2444 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
2445 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
2446
2447 let TPoint: XMVECTOR = XMVector3InverseRotate(XMVectorSubtract(Point, vCenter), vOrientation);
2449
2450 return if XMVector3InBounds(TPoint, vExtents) { CONTAINS } else { DISJOINT };
2451 }
2452
2453 pub fn ContainsTriangle(&self, V0: FXMVECTOR, V1: FXMVECTOR, V2: FXMVECTOR) -> ContainmentType {
2471 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
2473 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
2474
2475 let TV0: XMVECTOR = XMVector3InverseRotate(XMVectorSubtract(V0, vCenter), vOrientation);
2477 let TV1: XMVECTOR = XMVector3InverseRotate(XMVectorSubtract(V1, vCenter), vOrientation);
2478 let TV2: XMVECTOR = XMVector3InverseRotate(XMVectorSubtract(V2, vCenter), vOrientation);
2479
2480 let mut box_: BoundingBox = BoundingBox::default();
2481 box_.Center = XMFLOAT3::set(0.0, 0.0, 0.0);
2482 box_.Extents = self.Extents;
2483
2484 return box_.ContainsTriangle(TV0, TV1, TV2);
2486 }
2487
2488 #[inline]
2492 pub fn ContainsSphere(&self, sh: &BoundingSphere) -> ContainmentType {
2493 let mut SphereCenter: XMVECTOR = XMLoadFloat3(&sh.Center);
2494 let SphereRadius: XMVECTOR = XMVectorReplicatePtr(&sh.Radius);
2495
2496 let BoxCenter: XMVECTOR = XMLoadFloat3(&self.Center);
2497 let BoxExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
2498 let BoxOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
2499
2500 debug_assert!(internal::XMQuaternionIsUnit(BoxOrientation));
2501
2502 SphereCenter = XMVector3InverseRotate(XMVectorSubtract(SphereCenter, BoxCenter), BoxOrientation);
2506
2507 let mut d: XMVECTOR = XMVectorZero();
2513
2514 let LessThanMin: XMVECTOR = XMVectorLess(SphereCenter, XMVectorNegate(BoxExtents));
2516 let GreaterThanMax: XMVECTOR = XMVectorGreater(SphereCenter, BoxExtents);
2517
2518 let MinDelta: XMVECTOR = XMVectorAdd(SphereCenter, BoxExtents);
2519 let MaxDelta: XMVECTOR = XMVectorSubtract(SphereCenter, BoxExtents);
2520
2521 d = XMVectorSelect(d, MinDelta, LessThanMin);
2523 d = XMVectorSelect(d, MaxDelta, GreaterThanMax);
2524
2525 let d2: XMVECTOR = XMVector3Dot(d, d);
2527 let SphereRadiusSq: XMVECTOR = XMVectorMultiply(SphereRadius, SphereRadius);
2528
2529 if (XMVector4Greater(d2, SphereRadiusSq)) {
2530 return DISJOINT;
2531 }
2532
2533 let SMin: XMVECTOR = XMVectorSubtract(SphereCenter, SphereRadius);
2535 let SMax: XMVECTOR = XMVectorAdd(SphereCenter, SphereRadius);
2536
2537 return if (XMVector3InBounds(SMin, BoxExtents) && XMVector3InBounds(SMax, BoxExtents)) { CONTAINS } else { INTERSECTS };
2538 }
2539
2540 #[inline]
2544 pub fn ContainsBox(&self, box_: &BoundingBox) -> ContainmentType {
2545 let obox = BoundingOrientedBox {
2547 Center: box_.Center,
2548 Extents: box_.Extents,
2549 Orientation: XMFLOAT4::set(0.0, 0.0, 0.0, 1.0),
2550 };
2551 return self.ContainsOrientedBox(&obox);
2552 }
2553
2554 #[inline]
2558 pub fn ContainsOrientedBox(&self, box_: &BoundingOrientedBox) -> ContainmentType {
2559 if (!self.IntersectsOrientedBox(box_)) {
2560 return DISJOINT;
2561 }
2562
2563 let aCenter: XMVECTOR = XMLoadFloat3(&self.Center);
2565 let aExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
2566 let aOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
2567
2568 debug_assert!(internal::XMQuaternionIsUnit(aOrientation));
2569
2570 let bCenter: XMVECTOR = XMLoadFloat3(&box_.Center);
2571 let bExtents: XMVECTOR = XMLoadFloat3(&box_.Extents);
2572 let bOrientation: XMVECTOR = XMLoadFloat4(&box_.Orientation);
2573
2574 debug_assert!(internal::XMQuaternionIsUnit(bOrientation));
2575
2576 let offset: XMVECTOR = XMVectorSubtract(bCenter, aCenter);
2577
2578 for i in 0..BoundingOrientedBox::CORNER_COUNT
2579 {
2580 let mut C: XMVECTOR = XMVectorAdd(XMVector3Rotate(XMVectorMultiply(bExtents, g_BoxOffset[i].v()), bOrientation), offset);
2584 C = XMVector3InverseRotate(C, aOrientation);
2585
2586 if (!XMVector3InBounds(C, aExtents)) {
2587 return INTERSECTS;
2588 }
2589 }
2590
2591 return CONTAINS;
2592 }
2593
2594 #[inline]
2598 pub fn ContainsFrustum(&self, fr: &BoundingFrustum) -> ContainmentType {
2599 if (!fr.IntersectsOrientedBox(self)) {
2600 return DISJOINT;
2601 }
2602
2603 let mut Corners: [XMFLOAT3; BoundingFrustum::CORNER_COUNT] = unsafe { undefined() };
2604 fr.GetCorners(&mut Corners);
2605
2606 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
2608 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
2609 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
2610
2611 debug_assert!(internal::XMQuaternionIsUnit(vOrientation));
2612
2613 for i in 0 .. BoundingFrustum::CORNER_COUNT
2614 {
2615 let C: XMVECTOR = XMVector3InverseRotate(XMVectorSubtract(XMLoadFloat3(&Corners[i]), vCenter), vOrientation);
2616
2617 if (!XMVector3InBounds(C, vExtents)) {
2618 return INTERSECTS;
2619 }
2620 }
2621
2622 return CONTAINS;
2623 }
2624
2625 #[inline]
2629 pub fn IntersectsSphere(&self, sh: &BoundingSphere) -> bool {
2630 let mut SphereCenter: XMVECTOR = XMLoadFloat3(&sh.Center);
2631 let SphereRadius: XMVECTOR = XMVectorReplicatePtr(&sh.Radius);
2632
2633 let BoxCenter: XMVECTOR = XMLoadFloat3(&self.Center);
2634 let BoxExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
2635 let BoxOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
2636
2637 debug_assert!(internal::XMQuaternionIsUnit(BoxOrientation));
2638
2639 SphereCenter = XMVector3InverseRotate(XMVectorSubtract(SphereCenter, BoxCenter), BoxOrientation);
2643
2644 let mut d: XMVECTOR = XMVectorZero();
2650
2651 let LessThanMin: XMVECTOR = XMVectorLess(SphereCenter, XMVectorNegate(BoxExtents));
2653 let GreaterThanMax: XMVECTOR = XMVectorGreater(SphereCenter, BoxExtents);
2654
2655 let MinDelta: XMVECTOR = XMVectorAdd(SphereCenter, BoxExtents);
2656 let MaxDelta: XMVECTOR = XMVectorSubtract(SphereCenter, BoxExtents);
2657
2658 d = XMVectorSelect(d, MinDelta, LessThanMin);
2660 d = XMVectorSelect(d, MaxDelta, GreaterThanMax);
2661
2662 let d2: XMVECTOR = XMVector3Dot(d, d);
2664
2665 return if XMVector4LessOrEqual(d2, XMVectorMultiply(SphereRadius, SphereRadius)) { true } else { false };
2666 }
2667
2668 #[inline]
2672 pub fn IntersectsBox(&self, box_: &BoundingBox) -> bool {
2673 let obox = BoundingOrientedBox {
2675 Center: box_.Center,
2676 Extents: box_.Extents,
2677 Orientation: XMFLOAT4::set(0.0, 0.0, 0.0, 1.0),
2678 };
2679 return self.IntersectsOrientedBox(&obox);
2680 }
2681
2682 #[inline]
2686 pub fn IntersectsOrientedBox(&self, box_: &BoundingOrientedBox) -> bool {
2687 let A_quat: XMVECTOR = XMLoadFloat4(&self.Orientation);
2689 let B_quat: XMVECTOR = XMLoadFloat4(&box_.Orientation);
2690
2691 debug_assert!(internal::XMQuaternionIsUnit(A_quat));
2692 debug_assert!(internal::XMQuaternionIsUnit(B_quat));
2693
2694 let Q: XMVECTOR = XMQuaternionMultiply(A_quat, XMQuaternionConjugate(B_quat));
2695 let R: XMMATRIX = XMMatrixRotationQuaternion(Q);
2696
2697 let A_cent: XMVECTOR = XMLoadFloat3(&self.Center);
2699 let B_cent: XMVECTOR = XMLoadFloat3(&box_.Center);
2700 let t: XMVECTOR = XMVector3InverseRotate(XMVectorSubtract(B_cent, A_cent), A_quat);
2701
2702 let h_A: XMVECTOR = XMLoadFloat3(&self.Extents);
2717 let h_B: XMVECTOR = XMLoadFloat3(&box_.Extents);
2718
2719 let R0X: XMVECTOR = unsafe { R.r[0] };
2721 let R1X: XMVECTOR = unsafe { R.r[1] };
2722 let R2X: XMVECTOR = unsafe { R.r[2] };
2723
2724 let R = XMMatrixTranspose(R);
2725
2726 let RX0: XMVECTOR = unsafe { R.r[0] };
2728 let RX1: XMVECTOR = unsafe { R.r[1] };
2729 let RX2: XMVECTOR = unsafe { R.r[2] };
2730
2731 let AR0X: XMVECTOR = XMVectorAbs(R0X);
2733 let AR1X: XMVECTOR = XMVectorAbs(R1X);
2734 let AR2X: XMVECTOR = XMVectorAbs(R2X);
2735
2736 let ARX0: XMVECTOR = XMVectorAbs(RX0);
2738 let ARX1: XMVECTOR = XMVectorAbs(RX1);
2739 let ARX2: XMVECTOR = XMVectorAbs(RX2);
2740
2741 let mut d: XMVECTOR;
2744 let mut d_A: XMVECTOR;
2745 let mut d_B: XMVECTOR;
2746
2747 d = XMVectorSplatX(t);
2752 d_A = XMVectorSplatX(h_A);
2753 d_B = XMVector3Dot(h_B, AR0X);
2754 let mut NoIntersection: XMVECTOR = XMVectorGreater(XMVectorAbs(d), XMVectorAdd(d_A, d_B));
2755
2756 d = XMVectorSplatY(t);
2761 d_A = XMVectorSplatY(h_A);
2762 d_B = XMVector3Dot(h_B, AR1X);
2763 NoIntersection = XMVectorOrInt(NoIntersection,
2764 XMVectorGreater(XMVectorAbs(d), XMVectorAdd(d_A, d_B)));
2765
2766 d = XMVectorSplatZ(t);
2771 d_A = XMVectorSplatZ(h_A);
2772 d_B = XMVector3Dot(h_B, AR2X);
2773 NoIntersection = XMVectorOrInt(NoIntersection,
2774 XMVectorGreater(XMVectorAbs(d), XMVectorAdd(d_A, d_B)));
2775
2776 d = XMVector3Dot(t, RX0);
2780 d_A = XMVector3Dot(h_A, ARX0);
2781 d_B = XMVectorSplatX(h_B);
2782 NoIntersection = XMVectorOrInt(NoIntersection,
2783 XMVectorGreater(XMVectorAbs(d), XMVectorAdd(d_A, d_B)));
2784
2785 d = XMVector3Dot(t, RX1);
2789 d_A = XMVector3Dot(h_A, ARX1);
2790 d_B = XMVectorSplatY(h_B);
2791 NoIntersection = XMVectorOrInt(NoIntersection,
2792 XMVectorGreater(XMVectorAbs(d), XMVectorAdd(d_A, d_B)));
2793
2794 d = XMVector3Dot(t, RX2);
2798 d_A = XMVector3Dot(h_A, ARX2);
2799 d_B = XMVectorSplatZ(h_B);
2800 NoIntersection = XMVectorOrInt(NoIntersection,
2801 XMVectorGreater(XMVectorAbs(d), XMVectorAdd(d_A, d_B)));
2802
2803 d = XMVector3Dot(t, <(XM_PERMUTE_0W, XM_PERMUTE_1Z, XM_PERMUTE_0Y, XM_PERMUTE_0X)>::XMVectorPermute(RX0, XMVectorNegate(RX0)));
2807 d_A = XMVector3Dot(h_A, <(XM_SWIZZLE_W, XM_SWIZZLE_Z, XM_SWIZZLE_Y, XM_SWIZZLE_X)>::XMVectorSwizzle(ARX0));
2808 d_B = XMVector3Dot(h_B, <(XM_SWIZZLE_W, XM_SWIZZLE_Z, XM_SWIZZLE_Y, XM_SWIZZLE_X)>::XMVectorSwizzle(AR0X));
2809 NoIntersection = XMVectorOrInt(NoIntersection,
2810 XMVectorGreater(XMVectorAbs(d), XMVectorAdd(d_A, d_B)));
2811
2812 d = XMVector3Dot(t, <(XM_PERMUTE_0W, XM_PERMUTE_1Z, XM_PERMUTE_0Y, XM_PERMUTE_0X)>::XMVectorPermute(RX1, XMVectorNegate(RX1)));
2816 d_A = XMVector3Dot(h_A, <(XM_SWIZZLE_W, XM_SWIZZLE_Z, XM_SWIZZLE_Y, XM_SWIZZLE_X)>::XMVectorSwizzle(ARX1));
2817 d_B = XMVector3Dot(h_B, <(XM_SWIZZLE_Z, XM_SWIZZLE_W, XM_SWIZZLE_X, XM_SWIZZLE_Y)>::XMVectorSwizzle(AR0X));
2818 NoIntersection = XMVectorOrInt(NoIntersection,
2819 XMVectorGreater(XMVectorAbs(d), XMVectorAdd(d_A, d_B)));
2820
2821 d = XMVector3Dot(t, <(XM_PERMUTE_0W, XM_PERMUTE_1Z, XM_PERMUTE_0Y, XM_PERMUTE_0X)>::XMVectorPermute(RX2, XMVectorNegate(RX2)));
2825 d_A = XMVector3Dot(h_A, <(XM_SWIZZLE_W, XM_SWIZZLE_Z, XM_SWIZZLE_Y, XM_SWIZZLE_X)>::XMVectorSwizzle(ARX2));
2826 d_B = XMVector3Dot(h_B, <(XM_SWIZZLE_Y, XM_SWIZZLE_X, XM_SWIZZLE_W, XM_SWIZZLE_Z)>::XMVectorSwizzle(AR0X));
2827 NoIntersection = XMVectorOrInt(NoIntersection,
2828 XMVectorGreater(XMVectorAbs(d), XMVectorAdd(d_A, d_B)));
2829
2830 d = XMVector3Dot(t, <(XM_PERMUTE_0Z, XM_PERMUTE_0W, XM_PERMUTE_1X, XM_PERMUTE_0Y)>::XMVectorPermute(RX0, XMVectorNegate(RX0)));
2834 d_A = XMVector3Dot(h_A, <(XM_SWIZZLE_Z, XM_SWIZZLE_W, XM_SWIZZLE_X, XM_SWIZZLE_Y)>::XMVectorSwizzle(ARX0));
2835 d_B = XMVector3Dot(h_B, <(XM_SWIZZLE_W, XM_SWIZZLE_Z, XM_SWIZZLE_Y, XM_SWIZZLE_X)>::XMVectorSwizzle(AR1X));
2836 NoIntersection = XMVectorOrInt(NoIntersection,
2837 XMVectorGreater(XMVectorAbs(d), XMVectorAdd(d_A, d_B)));
2838
2839 d = XMVector3Dot(t, <(XM_PERMUTE_0Z, XM_PERMUTE_0W, XM_PERMUTE_1X, XM_PERMUTE_0Y)>::XMVectorPermute(RX1, XMVectorNegate(RX1)));
2843 d_A = XMVector3Dot(h_A, <(XM_SWIZZLE_Z, XM_SWIZZLE_W, XM_SWIZZLE_X, XM_SWIZZLE_Y)>::XMVectorSwizzle(ARX1));
2844 d_B = XMVector3Dot(h_B, <(XM_SWIZZLE_Z, XM_SWIZZLE_W, XM_SWIZZLE_X, XM_SWIZZLE_Y)>::XMVectorSwizzle(AR1X));
2845 NoIntersection = XMVectorOrInt(NoIntersection,
2846 XMVectorGreater(XMVectorAbs(d), XMVectorAdd(d_A, d_B)));
2847
2848 d = XMVector3Dot(t, <(XM_PERMUTE_0Z, XM_PERMUTE_0W, XM_PERMUTE_1X, XM_PERMUTE_0Y)>::XMVectorPermute(RX2, XMVectorNegate(RX2)));
2852 d_A = XMVector3Dot(h_A, <(XM_SWIZZLE_Z, XM_SWIZZLE_W, XM_SWIZZLE_X, XM_SWIZZLE_Y)>::XMVectorSwizzle(ARX2));
2853 d_B = XMVector3Dot(h_B, <(XM_SWIZZLE_Y, XM_SWIZZLE_X, XM_SWIZZLE_W, XM_SWIZZLE_Z)>::XMVectorSwizzle(AR1X));
2854 NoIntersection = XMVectorOrInt(NoIntersection,
2855 XMVectorGreater(XMVectorAbs(d), XMVectorAdd(d_A, d_B)));
2856
2857 d = XMVector3Dot(t, <(XM_PERMUTE_1Y, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_0Z)>::XMVectorPermute(RX0, XMVectorNegate(RX0)));
2861 d_A = XMVector3Dot(h_A, <(XM_SWIZZLE_Y, XM_SWIZZLE_X, XM_SWIZZLE_W, XM_SWIZZLE_Z)>::XMVectorSwizzle(ARX0));
2862 d_B = XMVector3Dot(h_B, <(XM_SWIZZLE_W, XM_SWIZZLE_Z, XM_SWIZZLE_Y, XM_SWIZZLE_X)>::XMVectorSwizzle(AR2X));
2863 NoIntersection = XMVectorOrInt(NoIntersection,
2864 XMVectorGreater(XMVectorAbs(d), XMVectorAdd(d_A, d_B)));
2865
2866 d = XMVector3Dot(t, <(XM_PERMUTE_1Y, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_0Z)>::XMVectorPermute(RX1, XMVectorNegate(RX1)));
2870 d_A = XMVector3Dot(h_A, <(XM_SWIZZLE_Y, XM_SWIZZLE_X, XM_SWIZZLE_W, XM_SWIZZLE_Z)>::XMVectorSwizzle(ARX1));
2871 d_B = XMVector3Dot(h_B, <(XM_SWIZZLE_Z, XM_SWIZZLE_W, XM_SWIZZLE_X, XM_SWIZZLE_Y)>::XMVectorSwizzle(AR2X));
2872 NoIntersection = XMVectorOrInt(NoIntersection,
2873 XMVectorGreater(XMVectorAbs(d), XMVectorAdd(d_A, d_B)));
2874
2875 d = XMVector3Dot(t, <(XM_PERMUTE_1Y, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_0Z)>::XMVectorPermute(RX2, XMVectorNegate(RX2)));
2879 d_A = XMVector3Dot(h_A, <(XM_SWIZZLE_Y, XM_SWIZZLE_X, XM_SWIZZLE_W, XM_SWIZZLE_Z)>::XMVectorSwizzle(ARX2));
2880 d_B = XMVector3Dot(h_B, <(XM_SWIZZLE_Y, XM_SWIZZLE_X, XM_SWIZZLE_W, XM_SWIZZLE_Z)>::XMVectorSwizzle(AR2X));
2881 NoIntersection = XMVectorOrInt(NoIntersection,
2882 XMVectorGreater(XMVectorAbs(d), XMVectorAdd(d_A, d_B)));
2883
2884 return if XMVector4NotEqualInt(NoIntersection, XMVectorTrueInt()) { true } else { false };
2886 }
2887
2888 #[inline]
2892 pub fn IntersectsFrustum(&self, fr: &BoundingFrustum) -> bool {
2893 return fr.IntersectsOrientedBox(self);
2894 }
2895
2896 #[inline]
2914 pub fn IntersectsTriangle(&self, V0: FXMVECTOR, V1: FXMVECTOR, V2: FXMVECTOR) -> bool {
2915 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
2917 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
2918
2919 let TV0: XMVECTOR = XMVector3InverseRotate(XMVectorSubtract(V0, vCenter), vOrientation);
2921 let TV1: XMVECTOR = XMVector3InverseRotate(XMVectorSubtract(V1, vCenter), vOrientation);
2922 let TV2: XMVECTOR = XMVector3InverseRotate(XMVectorSubtract(V2, vCenter), vOrientation);
2923
2924 let mut box_: BoundingBox = BoundingBox::default();
2925 box_.Center = XMFLOAT3::set(0.0, 0.0, 0.0);
2926 box_.Extents = self.Extents;
2927
2928 return box_.IntersectsTriangle(TV0, TV1, TV2);
2930 }
2931
2932 #[inline]
2946 pub fn IntersectsPlane(&self, Plane: FXMVECTOR) -> PlaneIntersectionType {
2947 debug_assert!(internal::XMPlaneIsUnit(Plane));
2948
2949 let mut vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
2951 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
2952 let BoxOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
2953
2954 debug_assert!(internal::XMQuaternionIsUnit(BoxOrientation));
2955
2956 vCenter = XMVectorInsert(vCenter, XMVectorSplatOne(), 0, 0, 0, 0, 1);
2959
2960 let R: XMMATRIX = XMMatrixRotationQuaternion(BoxOrientation);
2962
2963 unsafe {
2964 let mut Outside: XMVECTOR = undefined();
2965 let mut Inside: XMVECTOR = undefined();
2966 internal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane, &mut Outside, &mut Inside);
2967
2968 if (XMVector4EqualInt(Outside, XMVectorTrueInt())) {
2970 return FRONT;
2971 }
2972
2973 if (XMVector4EqualInt(Inside, XMVectorTrueInt())) {
2975 return BACK;
2976 }
2977 }
2978
2979 return INTERSECTING;
2981 }
2982
2983 #[inline]
3006 pub fn IntersectsRay(&self, Origin: FXMVECTOR, Direction: FXMVECTOR, Dist: &mut f32) -> bool {
3007 unsafe {
3008 debug_assert!(internal::XMVector3IsUnit(Direction));
3009
3010 const SelectY: XMVECTORU32 = XMVECTORU32 { u: [ XM_SELECT_0, XM_SELECT_1, XM_SELECT_0, XM_SELECT_0 ] };
3011 const SelectZ: XMVECTORU32 = XMVECTORU32 { u: [ XM_SELECT_0, XM_SELECT_0, XM_SELECT_1, XM_SELECT_0 ] };
3012
3013 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
3015 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
3016 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
3017
3018 debug_assert!(internal::XMQuaternionIsUnit(vOrientation));
3019
3020 let R: XMMATRIX = XMMatrixRotationQuaternion(vOrientation);
3022
3023 let TOrigin: XMVECTOR = XMVectorSubtract(vCenter, Origin);
3025
3026 let mut AxisDotOrigin: XMVECTOR = XMVector3Dot(R.r[0], TOrigin);
3028 AxisDotOrigin = XMVectorSelect(AxisDotOrigin, XMVector3Dot(R.r[1], TOrigin), SelectY.v);
3029 AxisDotOrigin = XMVectorSelect(AxisDotOrigin, XMVector3Dot(R.r[2], TOrigin), SelectZ.v);
3030
3031 let mut AxisDotDirection: XMVECTOR = XMVector3Dot(R.r[0], Direction);
3032 AxisDotDirection = XMVectorSelect(AxisDotDirection, XMVector3Dot(R.r[1], Direction), SelectY.v);
3033 AxisDotDirection = XMVectorSelect(AxisDotDirection, XMVector3Dot(R.r[2], Direction), SelectZ.v);
3034
3035 let IsParallel: XMVECTOR = XMVectorLessOrEqual(XMVectorAbs(AxisDotDirection), g_RayEpsilon.v);
3037
3038 let InverseAxisDotDirection: XMVECTOR = XMVectorReciprocal(AxisDotDirection);
3040 let t1: XMVECTOR = XMVectorMultiply(XMVectorSubtract(AxisDotOrigin, vExtents), InverseAxisDotDirection);
3041 let t2: XMVECTOR = XMVectorMultiply(XMVectorAdd(AxisDotOrigin, vExtents), InverseAxisDotDirection);
3042
3043 let mut t_min: XMVECTOR = XMVectorSelect(XMVectorMin(t1, t2), g_FltMin.v, IsParallel);
3046 let mut t_max: XMVECTOR = XMVectorSelect(XMVectorMax(t1, t2), g_FltMax.v, IsParallel);
3047
3048 t_min = XMVectorMax(t_min, XMVectorSplatY(t_min)); t_min = XMVectorMax(t_min, XMVectorSplatZ(t_min)); t_max = XMVectorMin(t_max, XMVectorSplatY(t_max)); t_max = XMVectorMin(t_max, XMVectorSplatZ(t_max)); let mut NoIntersection: XMVECTOR = XMVectorGreater(XMVectorSplatX(t_min), XMVectorSplatX(t_max));
3057
3058 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(XMVectorSplatX(t_max), XMVectorZero()));
3060
3061 let ParallelOverlap: XMVECTOR = XMVectorInBounds(AxisDotOrigin, vExtents);
3063 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorAndCInt(IsParallel, ParallelOverlap));
3064
3065 if (!internal::XMVector3AnyTrue(NoIntersection))
3066 {
3067 XMStoreFloat(Dist, t_min);
3069 return true;
3070 }
3071
3072 *Dist = 0.0;
3073 return false;
3074 }
3075 }
3076
3077 #[inline]
3081 pub fn ContainedBy(
3082 &self,
3083 Plane0: FXMVECTOR,
3084 Plane1: FXMVECTOR,
3085 Plane2: GXMVECTOR,
3086 Plane3: HXMVECTOR,
3087 Plane4: HXMVECTOR,
3088 Plane5: HXMVECTOR,
3089 ) -> ContainmentType
3090 {
3091 let mut vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
3093 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
3094 let BoxOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
3095
3096 debug_assert!(internal::XMQuaternionIsUnit(BoxOrientation));
3097
3098 vCenter = XMVectorInsert(vCenter, XMVectorSplatOne(), 0, 0, 0, 0, 1);
3101
3102 let R: XMMATRIX = XMMatrixRotationQuaternion(BoxOrientation);
3104
3105 unsafe {
3106 let mut Outside: XMVECTOR = undefined();
3107 let mut Inside: XMVECTOR = undefined();
3108
3109 internal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane0, &mut Outside, &mut Inside);
3111
3112 let mut AnyOutside: XMVECTOR = Outside;
3113 let mut AllInside: XMVECTOR = Inside;
3114
3115 internal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane1, &mut Outside, &mut Inside);
3116 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
3117 AllInside = XMVectorAndInt(AllInside, Inside);
3118
3119 internal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane2, &mut Outside, &mut Inside);
3120 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
3121 AllInside = XMVectorAndInt(AllInside, Inside);
3122
3123 internal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane3, &mut Outside, &mut Inside);
3124 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
3125 AllInside = XMVectorAndInt(AllInside, Inside);
3126
3127 internal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane4, &mut Outside, &mut Inside);
3128 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
3129 AllInside = XMVectorAndInt(AllInside, Inside);
3130
3131 internal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane5, &mut Outside, &mut Inside);
3132 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
3133 AllInside = XMVectorAndInt(AllInside, Inside);
3134
3135 if (XMVector4EqualInt(AnyOutside, XMVectorTrueInt())) {
3137 return DISJOINT;
3138 }
3139
3140 if (XMVector4EqualInt(AllInside, XMVectorTrueInt())) {
3142 return CONTAINS;
3143 }
3144 }
3145
3146 return INTERSECTS;
3148 }
3149
3150 #[inline]
3154 pub fn CreateFromBoundingBox(Out: &mut Self, box_: &BoundingBox) {
3155 Out.Center = box_.Center;
3156 Out.Extents = box_.Extents;
3157 Out.Orientation = XMFLOAT4::set(0.0, 0.0, 0.0, 1.0);
3158 }
3159
3160 #[inline]
3164 pub fn CreateFromPoints<'a>(Out: &mut Self, pPoints: impl Iterator<Item=&'a XMFLOAT3> + Clone) {
3165 let Count = pPoints.clone().count();
3178
3179 if Count == 0 {
3180 Out.Extents = XMFLOAT3::set(std::f32::NAN, std::f32::NAN, std::f32::NAN);
3181 Out.Orientation = XMFLOAT4::set(0.0, 0.0, 0.0, 1.0);
3182 return;
3183 }
3184
3185 let mut CenterOfMass: XMVECTOR = XMVectorZero();
3189
3190 for point in pPoints.clone()
3193 {
3194 let Point: XMVECTOR = XMLoadFloat3(point);
3196
3197 CenterOfMass = XMVectorAdd(CenterOfMass, Point);
3198 }
3199
3200 CenterOfMass = XMVectorMultiply(CenterOfMass, XMVectorReciprocal(XMVectorReplicate(Count as f32)));
3201
3202 let mut XX_YY_ZZ: XMVECTOR = XMVectorZero();
3206 let mut XY_XZ_YZ: XMVECTOR = XMVectorZero();
3207
3208 for point in pPoints.clone().into_iter()
3210 {
3211 let Point: XMVECTOR = XMVectorSubtract(XMLoadFloat3(point), CenterOfMass);
3212
3213 XX_YY_ZZ = XMVectorAdd(XX_YY_ZZ, XMVectorMultiply(Point, Point));
3214
3215 let XXY: XMVECTOR = <(XM_SWIZZLE_X, XM_SWIZZLE_X, XM_SWIZZLE_Y, XM_SWIZZLE_W)>::XMVectorSwizzle(Point);
3216 let YZZ: XMVECTOR = <(XM_SWIZZLE_Y, XM_SWIZZLE_Z, XM_SWIZZLE_Z, XM_SWIZZLE_W)>::XMVectorSwizzle(Point);
3217
3218 XY_XZ_YZ = XMVectorAdd(XY_XZ_YZ, XMVectorMultiply(XXY, YZZ));
3219 }
3220
3221 let mut v1: XMVECTOR = unsafe { undefined() };
3222 let mut v2: XMVECTOR = unsafe { undefined() };
3223 let mut v3: XMVECTOR = unsafe { undefined() };
3224
3225 internal::CalculateEigenVectorsFromCovarianceMatrix(XMVectorGetX(XX_YY_ZZ), XMVectorGetY(XX_YY_ZZ),
3227 XMVectorGetZ(XX_YY_ZZ),
3228 XMVectorGetX(XY_XZ_YZ), XMVectorGetY(XY_XZ_YZ),
3229 XMVectorGetZ(XY_XZ_YZ),
3230 &mut v1, &mut v2, &mut v3);
3231
3232 let mut R: XMMATRIX = unsafe { undefined() };
3234
3235 unsafe {
3236 R.r[0] = XMVectorSetW(v1, 0.0);
3237 R.r[1] = XMVectorSetW(v2, 0.0);
3238 R.r[2] = XMVectorSetW(v3, 0.0);
3239 R.r[3] = g_XMIdentityR3.v;
3240 }
3241
3242 let Det: XMVECTOR = XMMatrixDeterminant(R);
3247
3248 if (XMVector4Less(Det, XMVectorZero()))
3249 {
3250 unsafe {
3251 R.r[0] = XMVectorMultiply(R.r[0], g_XMNegativeOne.v);
3252 R.r[1] = XMVectorMultiply(R.r[1], g_XMNegativeOne.v);
3253 R.r[2] = XMVectorMultiply(R.r[2], g_XMNegativeOne.v);
3254 }
3255 }
3256
3257 let mut vOrientation: XMVECTOR = XMQuaternionRotationMatrix(R);
3259
3260 vOrientation = XMQuaternionNormalize(vOrientation);
3262
3263 R = XMMatrixRotationQuaternion(vOrientation);
3265
3266 let InverseR: XMMATRIX = XMMatrixTranspose(R);
3268
3269 let mut vMin: XMVECTOR = XMVectorZero();
3271 let mut vMax: XMVECTOR = XMVectorZero();
3272
3273 for (i, point) in pPoints.enumerate()
3275 {
3276 let Point: XMVECTOR = XMLoadFloat3(point);
3277
3278 if i == 0 {
3279 vMin = XMVector3TransformNormal(Point, InverseR);
3280 vMax = vMin;
3281 } else {
3282 vMin = XMVectorMin(vMin, Point);
3283 vMax = XMVectorMax(vMax, Point);
3284 }
3285 }
3286
3287 let mut vCenter: XMVECTOR = XMVectorScale(XMVectorAdd(vMin, vMax), 0.5);
3289 vCenter = XMVector3TransformNormal(vCenter, R);
3290
3291 XMStoreFloat3(&mut Out.Center, vCenter);
3293 XMStoreFloat3(&mut Out.Extents, XMVectorScale(XMVectorSubtract(vMax, vMin), 0.5));
3294 XMStoreFloat4(&mut Out.Orientation, vOrientation);
3295 }
3296
3297 #[inline]
3301 pub fn GetCorners(&self, Corners: &mut [XMFLOAT3; 8]) {
3302 let vCenter: XMVECTOR = XMLoadFloat3(&self.Center);
3304 let vExtents: XMVECTOR = XMLoadFloat3(&self.Extents);
3305 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
3306
3307 debug_assert!(internal::XMQuaternionIsUnit(vOrientation));
3308
3309 for i in 0 .. Self::CORNER_COUNT
3311 {
3312 let C: XMVECTOR = XMVectorAdd(XMVector3Rotate(XMVectorMultiply(vExtents, g_BoxOffset[i].v()), vOrientation), vCenter);
3313 XMStoreFloat3(&mut Corners[i], C);
3314 }
3315 }
3316}
3317
3318#[test]
3319fn test_BoundingOrientedBox_CreateFromPoints() {
3320 let mut bounds: BoundingOrientedBox = BoundingOrientedBox::default();
3321 let points = &[
3322 XMFLOAT3::set(-1.0, -1.0, -1.0),
3323 XMFLOAT3::set( 1.0, 1.0, 1.0),
3324 ];
3325 BoundingOrientedBox::CreateFromPoints(&mut bounds, points.iter());
3326 assert_eq!(ContainmentType::CONTAINS, bounds.ContainsPoint(XMVectorSet(0.0, 0.0, 0.0, 0.0)));
3327 assert_eq!(ContainmentType::CONTAINS, bounds.ContainsPoint(XMVectorSet(1.0, 1.0, 1.0, 0.0)));
3328 assert_eq!(ContainmentType::DISJOINT, bounds.ContainsPoint(XMVectorSet(2.0, 2.0, 2.0, 0.0)));
3329
3330 let mut bounds: BoundingOrientedBox = BoundingOrientedBox::default();
3331 let points = &[];
3332 BoundingOrientedBox::CreateFromPoints(&mut bounds, points.iter());
3333 assert_eq!(ContainmentType::DISJOINT, bounds.ContainsPoint(XMVectorSet(0.0, 0.0, 0.0, 0.0)));
3334}
3335
3336impl BoundingFrustum {
3339 pub const CORNER_COUNT: usize = 8;
3341
3342 #[inline]
3360 pub fn TransformMatrix(&self, Out: &mut Self, M: FXMMATRIX) {
3361 let mut vOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
3363 let mut vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
3364
3365 debug_assert!(internal::XMQuaternionIsUnit(vOrientation));
3366
3367 unsafe {
3368 let mut nM: XMMATRIX = undefined();
3370 nM.r[0] = XMVector3Normalize(M.r[0]);
3371 nM.r[1] = XMVector3Normalize(M.r[1]);
3372 nM.r[2] = XMVector3Normalize(M.r[2]);
3373 nM.r[3] = g_XMIdentityR3.v;
3374 let Rotation: XMVECTOR = XMQuaternionRotationMatrix(nM);
3375 vOrientation = XMQuaternionMultiply(vOrientation, Rotation);
3376
3377 vOrigin = XMVector3Transform(vOrigin, M);
3379
3380 XMStoreFloat3(&mut Out.Origin, vOrigin);
3382 XMStoreFloat4(&mut Out.Orientation, vOrientation);
3383
3384 let dX: XMVECTOR = XMVector3Dot(M.r[0], M.r[0]);
3386 let dY: XMVECTOR = XMVector3Dot(M.r[1], M.r[1]);
3387 let dZ: XMVECTOR = XMVector3Dot(M.r[2], M.r[2]);
3388
3389 let d: XMVECTOR = XMVectorMax(dX, XMVectorMax(dY, dZ));
3390 let Scale: f32 = sqrtf(XMVectorGetX(d));
3391
3392 Out.Near = self.Near * Scale;
3393 Out.Far = self.Far * Scale;
3394 }
3395
3396 Out.RightSlope = self.RightSlope;
3398 Out.LeftSlope = self.LeftSlope;
3399 Out.TopSlope = self.TopSlope;
3400 Out.BottomSlope = self.BottomSlope;
3401 }
3402
3403 #[inline]
3423 pub fn TransformDecomposed(&self, Out: &mut Self, Scale: f32, Rotation: FXMVECTOR, Translation: FXMVECTOR) {
3424 debug_assert!(internal::XMQuaternionIsUnit(Rotation));
3425
3426 let mut vOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
3428 let mut vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
3429
3430 debug_assert!(internal::XMQuaternionIsUnit(vOrientation));
3431
3432 vOrientation = XMQuaternionMultiply(vOrientation, Rotation);
3434
3435 vOrigin = XMVectorAdd(XMVector3Rotate(XMVectorScale(vOrigin, Scale), Rotation), Translation);
3437
3438 XMStoreFloat3(&mut Out.Origin, vOrigin);
3440 XMStoreFloat4(&mut Out.Orientation, vOrientation);
3441
3442 Out.Near = self.Near * Scale;
3444 Out.Far = self.Far * Scale;
3445
3446 Out.RightSlope = self.RightSlope;
3448 Out.LeftSlope = self.LeftSlope;
3449 Out.TopSlope = self.TopSlope;
3450 Out.BottomSlope = self.BottomSlope;
3451 }
3452
3453 #[inline]
3467 pub fn ContainsPoint(&self, Point: FXMVECTOR) -> ContainmentType {
3468 let mut Planes: [XMVECTOR; 6] = unsafe { undefined() };
3470 Planes[0] = XMVectorSet(0.0, 0.0, -1.0, self.Near);
3471 Planes[1] = XMVectorSet(0.0, 0.0, 1.0, -self.Far);
3472 Planes[2] = XMVectorSet(1.0, 0.0, -self.RightSlope, 0.0);
3473 Planes[3] = XMVectorSet(-1.0, 0.0, self.LeftSlope, 0.0);
3474 Planes[4] = XMVectorSet(0.0, 1.0, -self.TopSlope, 0.0);
3475 Planes[5] = XMVectorSet(0.0, -1.0, self.BottomSlope, 0.0);
3476
3477 let vOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
3479 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
3480
3481 debug_assert!(internal::XMQuaternionIsUnit(vOrientation));
3482
3483 let mut TPoint: XMVECTOR = XMVector3InverseRotate(XMVectorSubtract(Point, vOrigin), vOrientation);
3485
3486 TPoint = XMVectorInsert(TPoint, XMVectorSplatOne(), 0, 0, 0, 0, 1);
3489
3490 let Zero: XMVECTOR = XMVectorZero();
3491 let mut Outside: XMVECTOR = Zero;
3492
3493 for i in 0 .. 6
3496 {
3497 let Dot: XMVECTOR = XMVector4Dot(TPoint, Planes[i]);
3498 Outside = XMVectorOrInt(Outside, XMVectorGreater(Dot, Zero));
3499 }
3500
3501 return if XMVector4NotEqualInt(Outside, XMVectorTrueInt()) { CONTAINS } else { DISJOINT };
3502 }
3503
3504 #[inline]
3522 pub fn ContainsTriangle(&self, V0: FXMVECTOR, V1: FXMVECTOR, V2: FXMVECTOR) -> ContainmentType {
3523 let vOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
3525 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
3526
3527 let mut NearPlane: XMVECTOR = XMVectorSet(0.0, 0.0, -1.0, self.Near);
3529 NearPlane = internal::XMPlaneTransform(NearPlane, vOrientation, vOrigin);
3530 NearPlane = XMPlaneNormalize(NearPlane);
3531
3532 let mut FarPlane: XMVECTOR = XMVectorSet(0.0, 0.0, 1.0, -self.Far);
3533 FarPlane = internal::XMPlaneTransform(FarPlane, vOrientation, vOrigin);
3534 FarPlane = XMPlaneNormalize(FarPlane);
3535
3536 let mut RightPlane: XMVECTOR = XMVectorSet(1.0, 0.0, -self.RightSlope, 0.0);
3537 RightPlane = internal::XMPlaneTransform(RightPlane, vOrientation, vOrigin);
3538 RightPlane = XMPlaneNormalize(RightPlane);
3539
3540 let mut LeftPlane: XMVECTOR = XMVectorSet(-1.0, 0.0, self.LeftSlope, 0.0);
3541 LeftPlane = internal::XMPlaneTransform(LeftPlane, vOrientation, vOrigin);
3542 LeftPlane = XMPlaneNormalize(LeftPlane);
3543
3544 let mut TopPlane: XMVECTOR = XMVectorSet(0.0, 1.0, -self.TopSlope, 0.0);
3545 TopPlane = internal::XMPlaneTransform(TopPlane, vOrientation, vOrigin);
3546 TopPlane = XMPlaneNormalize(TopPlane);
3547
3548 let mut BottomPlane: XMVECTOR = XMVectorSet(0.0, -1.0, self.BottomSlope, 0.0);
3549 BottomPlane = internal::XMPlaneTransform(BottomPlane, vOrientation, vOrigin);
3550 BottomPlane = XMPlaneNormalize(BottomPlane);
3551
3552 return triangle_tests::ContainedBy(V0, V1, V2, NearPlane, FarPlane, RightPlane, &LeftPlane, &TopPlane, &BottomPlane);
3553 }
3554
3555 #[inline]
3559 pub fn ContainsSphere(&self, sh: &BoundingSphere) -> ContainmentType {
3560 let vOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
3562 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
3563
3564 let mut NearPlane: XMVECTOR = XMVectorSet(0.0, 0.0, -1.0, self.Near);
3566 NearPlane = internal::XMPlaneTransform(NearPlane, vOrientation, vOrigin);
3567 NearPlane = XMPlaneNormalize(NearPlane);
3568
3569 let mut FarPlane: XMVECTOR = XMVectorSet(0.0, 0.0, 1.0, -self.Far);
3570 FarPlane = internal::XMPlaneTransform(FarPlane, vOrientation, vOrigin);
3571 FarPlane = XMPlaneNormalize(FarPlane);
3572
3573 let mut RightPlane: XMVECTOR = XMVectorSet(1.0, 0.0, -self.RightSlope, 0.0);
3574 RightPlane = internal::XMPlaneTransform(RightPlane, vOrientation, vOrigin);
3575 RightPlane = XMPlaneNormalize(RightPlane);
3576
3577 let mut LeftPlane: XMVECTOR = XMVectorSet(-1.0, 0.0, self.LeftSlope, 0.0);
3578 LeftPlane = internal::XMPlaneTransform(LeftPlane, vOrientation, vOrigin);
3579 LeftPlane = XMPlaneNormalize(LeftPlane);
3580
3581 let mut TopPlane: XMVECTOR = XMVectorSet(0.0, 1.0, -self.TopSlope, 0.0);
3582 TopPlane = internal::XMPlaneTransform(TopPlane, vOrientation, vOrigin);
3583 TopPlane = XMPlaneNormalize(TopPlane);
3584
3585 let mut BottomPlane: XMVECTOR = XMVectorSet(0.0, -1.0, self.BottomSlope, 0.0);
3586 BottomPlane = internal::XMPlaneTransform(BottomPlane, vOrientation, vOrigin);
3587 BottomPlane = XMPlaneNormalize(BottomPlane);
3588
3589 return sh.ContainedBy(NearPlane, FarPlane, RightPlane, LeftPlane, TopPlane, BottomPlane);
3590 }
3591
3592 #[inline]
3596 pub fn ContainsBox(&self, box_: &BoundingBox) -> ContainmentType {
3597 let vOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
3599 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
3600
3601 let mut NearPlane: XMVECTOR = XMVectorSet(0.0, 0.0, -1.0, self.Near);
3603 NearPlane = internal::XMPlaneTransform(NearPlane, vOrientation, vOrigin);
3604 NearPlane = XMPlaneNormalize(NearPlane);
3605
3606 let mut FarPlane: XMVECTOR = XMVectorSet(0.0, 0.0, 1.0, -self.Far);
3607 FarPlane = internal::XMPlaneTransform(FarPlane, vOrientation, vOrigin);
3608 FarPlane = XMPlaneNormalize(FarPlane);
3609
3610 let mut RightPlane: XMVECTOR = XMVectorSet(1.0, 0.0, -self.RightSlope, 0.0);
3611 RightPlane = internal::XMPlaneTransform(RightPlane, vOrientation, vOrigin);
3612 RightPlane = XMPlaneNormalize(RightPlane);
3613
3614 let mut LeftPlane: XMVECTOR = XMVectorSet(-1.0, 0.0, self.LeftSlope, 0.0);
3615 LeftPlane = internal::XMPlaneTransform(LeftPlane, vOrientation, vOrigin);
3616 LeftPlane = XMPlaneNormalize(LeftPlane);
3617
3618 let mut TopPlane: XMVECTOR = XMVectorSet(0.0, 1.0, -self.TopSlope, 0.0);
3619 TopPlane = internal::XMPlaneTransform(TopPlane, vOrientation, vOrigin);
3620 TopPlane = XMPlaneNormalize(TopPlane);
3621
3622 let mut BottomPlane: XMVECTOR = XMVectorSet(0.0, -1.0, self.BottomSlope, 0.0);
3623 BottomPlane = internal::XMPlaneTransform(BottomPlane, vOrientation, vOrigin);
3624 BottomPlane = XMPlaneNormalize(BottomPlane);
3625
3626 return box_.ContainedBy(NearPlane, FarPlane, RightPlane, LeftPlane, TopPlane, BottomPlane);
3627 }
3628
3629 #[inline]
3633 pub fn ContainsOrientedBox(&self, box_: &BoundingOrientedBox) -> ContainmentType {
3634 let vOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
3636 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
3637
3638 let mut NearPlane: XMVECTOR = XMVectorSet(0.0, 0.0, -1.0, self.Near);
3640 NearPlane = internal::XMPlaneTransform(NearPlane, vOrientation, vOrigin);
3641 NearPlane = XMPlaneNormalize(NearPlane);
3642
3643 let mut FarPlane: XMVECTOR = XMVectorSet(0.0, 0.0, 1.0, -self.Far);
3644 FarPlane = internal::XMPlaneTransform(FarPlane, vOrientation, vOrigin);
3645 FarPlane = XMPlaneNormalize(FarPlane);
3646
3647 let mut RightPlane: XMVECTOR = XMVectorSet(1.0, 0.0, -self.RightSlope, 0.0);
3648 RightPlane = internal::XMPlaneTransform(RightPlane, vOrientation, vOrigin);
3649 RightPlane = XMPlaneNormalize(RightPlane);
3650
3651 let mut LeftPlane: XMVECTOR = XMVectorSet(-1.0, 0.0, self.LeftSlope, 0.0);
3652 LeftPlane = internal::XMPlaneTransform(LeftPlane, vOrientation, vOrigin);
3653 LeftPlane = XMPlaneNormalize(LeftPlane);
3654
3655 let mut TopPlane: XMVECTOR = XMVectorSet(0.0, 1.0, -self.TopSlope, 0.0);
3656 TopPlane = internal::XMPlaneTransform(TopPlane, vOrientation, vOrigin);
3657 TopPlane = XMPlaneNormalize(TopPlane);
3658
3659 let mut BottomPlane: XMVECTOR = XMVectorSet(0.0, -1.0, self.BottomSlope, 0.0);
3660 BottomPlane = internal::XMPlaneTransform(BottomPlane, vOrientation, vOrigin);
3661 BottomPlane = XMPlaneNormalize(BottomPlane);
3662
3663 return box_.ContainedBy(NearPlane, FarPlane, RightPlane, LeftPlane, TopPlane, BottomPlane);
3664 }
3665
3666 #[inline]
3670 pub fn ContainsFrustum(&self, fr: &BoundingFrustum) -> ContainmentType {
3671 let vOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
3673 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
3674
3675 let mut NearPlane: XMVECTOR = XMVectorSet(0.0, 0.0, -1.0, self.Near);
3677 NearPlane = internal::XMPlaneTransform(NearPlane, vOrientation, vOrigin);
3678 NearPlane = XMPlaneNormalize(NearPlane);
3679
3680 let mut FarPlane: XMVECTOR = XMVectorSet(0.0, 0.0, 1.0, -self.Far);
3681 FarPlane = internal::XMPlaneTransform(FarPlane, vOrientation, vOrigin);
3682 FarPlane = XMPlaneNormalize(FarPlane);
3683
3684 let mut RightPlane: XMVECTOR = XMVectorSet(1.0, 0.0, -self.RightSlope, 0.0);
3685 RightPlane = internal::XMPlaneTransform(RightPlane, vOrientation, vOrigin);
3686 RightPlane = XMPlaneNormalize(RightPlane);
3687
3688 let mut LeftPlane: XMVECTOR = XMVectorSet(-1.0, 0.0, self.LeftSlope, 0.0);
3689 LeftPlane = internal::XMPlaneTransform(LeftPlane, vOrientation, vOrigin);
3690 LeftPlane = XMPlaneNormalize(LeftPlane);
3691
3692 let mut TopPlane: XMVECTOR = XMVectorSet(0.0, 1.0, -self.TopSlope, 0.0);
3693 TopPlane = internal::XMPlaneTransform(TopPlane, vOrientation, vOrigin);
3694 TopPlane = XMPlaneNormalize(TopPlane);
3695
3696 let mut BottomPlane: XMVECTOR = XMVectorSet(0.0, -1.0, self.BottomSlope, 0.0);
3697 BottomPlane = internal::XMPlaneTransform(BottomPlane, vOrientation, vOrigin);
3698 BottomPlane = XMPlaneNormalize(BottomPlane);
3699
3700 return fr.ContainedBy(NearPlane, FarPlane, RightPlane, LeftPlane, TopPlane, BottomPlane);
3701 }
3702
3703 #[inline]
3707 pub fn IntersectsSphere(&self, sh: &BoundingSphere) -> bool {
3708 let Zero: XMVECTOR = XMVectorZero();
3717
3718 let mut Planes: [XMVECTOR; 6] = unsafe { undefined() };
3720 Planes[0] = XMVectorSet(0.0, 0.0, -1.0, self.Near);
3721 Planes[1] = XMVectorSet(0.0, 0.0, 1.0, -self.Far);
3722 Planes[2] = XMVectorSet(1.0, 0.0, -self.RightSlope, 0.0);
3723 Planes[3] = XMVectorSet(-1.0, 0.0, self.LeftSlope, 0.0);
3724 Planes[4] = XMVectorSet(0.0, 1.0, -self.TopSlope, 0.0);
3725 Planes[5] = XMVectorSet(0.0, -1.0, self.BottomSlope, 0.0);
3726
3727 Planes[2] = XMVector3Normalize(Planes[2]);
3729 Planes[3] = XMVector3Normalize(Planes[3]);
3730 Planes[4] = XMVector3Normalize(Planes[4]);
3731 Planes[5] = XMVector3Normalize(Planes[5]);
3732
3733 let vOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
3735 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
3736
3737 debug_assert!(internal::XMQuaternionIsUnit(vOrientation));
3738
3739 let mut vCenter: XMVECTOR = XMLoadFloat3(&sh.Center);
3741 let vRadius: XMVECTOR = XMVectorReplicatePtr(&sh.Radius);
3742
3743 vCenter = XMVector3InverseRotate(XMVectorSubtract(vCenter, vOrigin), vOrientation);
3745
3746 vCenter = XMVectorInsert(vCenter, XMVectorSplatOne(), 0, 0, 0, 0, 1);
3748
3749 let mut Outside: XMVECTOR = XMVectorFalseInt();
3751 let mut InsideAll: XMVECTOR = XMVectorTrueInt();
3752 let mut CenterInsideAll: XMVECTOR = XMVectorTrueInt();
3753
3754 let mut Dist: [XMVECTOR; 6] = unsafe { undefined() };
3755
3756 for i in 0 .. 6
3758 {
3759 Dist[i] = XMVector4Dot(vCenter, Planes[i]);
3760
3761 Outside = XMVectorOrInt(Outside, XMVectorGreater(Dist[i], vRadius));
3763
3764 InsideAll = XMVectorAndInt(InsideAll, XMVectorLessOrEqual(Dist[i], XMVectorNegate(vRadius)));
3766
3767 CenterInsideAll = XMVectorAndInt(CenterInsideAll, XMVectorLessOrEqual(Dist[i], Zero));
3769 }
3770
3771 if (XMVector4EqualInt(Outside, XMVectorTrueInt())) {
3773 return false;
3774 }
3775
3776 if (XMVector4EqualInt(InsideAll, XMVectorTrueInt())) {
3778 return true;
3779 }
3780
3781 if (XMVector4EqualInt(CenterInsideAll, XMVectorTrueInt())) {
3784 return true;
3785 }
3786
3787 const adjacent_faces: [[usize; 4]; 6] = [
3794 [ 2, 3, 4, 5 ], [ 2, 3, 4, 5 ], [ 0, 1, 4, 5 ], [ 0, 1, 4, 5 ], [ 0, 1, 2, 3 ], [ 0, 1, 2, 3 ]
3800 ]; let mut Intersects: XMVECTOR = XMVectorFalseInt();
3803
3804 for i in 0 .. 6
3807 {
3808 let mut Point: XMVECTOR = XMVectorNegativeMultiplySubtract(Planes[i], Dist[i], vCenter);
3810
3811 Point = XMVectorInsert(Point, XMVectorSplatOne(), 0, 0, 0, 0, 1);
3813
3814 let mut InsideFace: XMVECTOR = XMVectorTrueInt();
3817
3818 for j in 0 .. 4
3820 {
3821 let plane_index: usize = adjacent_faces[i][j];
3822
3823 InsideFace = XMVectorAndInt(InsideFace,
3824 XMVectorLessOrEqual(XMVector4Dot(Point, Planes[plane_index]), Zero));
3825 }
3826
3827 Intersects = XMVectorOrInt(Intersects,
3830 XMVectorAndInt(XMVectorGreater(Dist[i], Zero), InsideFace));
3831 }
3832
3833 if (XMVector4EqualInt(Intersects, XMVectorTrueInt())) {
3834 return true;
3835 }
3836
3837 let vRightTop: XMVECTOR = XMVectorSet(self.RightSlope, self.TopSlope, 1.0, 0.0);
3839 let vRightBottom: XMVECTOR = XMVectorSet(self.RightSlope, self.BottomSlope, 1.0, 0.0);
3840 let vLeftTop: XMVECTOR = XMVectorSet(self.LeftSlope, self.TopSlope, 1.0, 0.0);
3841 let vLeftBottom: XMVECTOR = XMVectorSet(self.LeftSlope, self.BottomSlope, 1.0, 0.0);
3842 let vNear: XMVECTOR = XMVectorReplicatePtr(&self.Near);
3843 let vFar: XMVECTOR = XMVectorReplicatePtr(&self.Far);
3844
3845 let mut Corners: [XMVECTOR; BoundingFrustum::CORNER_COUNT] = unsafe { undefined() };
3846 Corners[0] = XMVectorMultiply(vRightTop, vNear);
3847 Corners[1] = XMVectorMultiply(vRightBottom, vNear);
3848 Corners[2] = XMVectorMultiply(vLeftTop, vNear);
3849 Corners[3] = XMVectorMultiply(vLeftBottom, vNear);
3850 Corners[4] = XMVectorMultiply(vRightTop, vFar);
3851 Corners[5] = XMVectorMultiply(vRightBottom, vFar);
3852 Corners[6] = XMVectorMultiply(vLeftTop, vFar);
3853 Corners[7] = XMVectorMultiply(vLeftBottom, vFar);
3854
3855 const edges: [[usize; 2]; 12] =
3858 [
3859 [ 0, 1 ], [ 2, 3 ], [ 0, 2 ], [ 1, 3 ], [ 4, 5 ], [ 6, 7 ], [ 4, 6 ], [ 5, 7 ], [ 0, 4 ], [ 1, 5 ], [ 2, 6 ], [ 3, 7 ],
3862 ]; let RadiusSq: XMVECTOR = XMVectorMultiply(vRadius, vRadius);
3865
3866 for i in 0 .. 12
3869 {
3870 let ei0: usize = edges[i][0];
3871 let ei1: usize = edges[i][1];
3872
3873 let Point: XMVECTOR = internal::PointOnLineSegmentNearestPoint(Corners[ei0], Corners[ei1], vCenter);
3876
3877 let Delta: XMVECTOR = XMVectorSubtract(vCenter, Point);
3878
3879 let DistSq: XMVECTOR = XMVector3Dot(Delta, Delta);
3880
3881 Intersects = XMVectorOrInt(Intersects, XMVectorLessOrEqual(DistSq, RadiusSq));
3884 }
3885
3886 if (XMVector4EqualInt(Intersects, XMVectorTrueInt())) {
3887 return true;
3888 }
3889
3890 return false;
3892 }
3893
3894 #[inline]
3898 pub fn IntersectsBox(&self, box_: &BoundingBox) -> bool {
3899 let obox = BoundingOrientedBox {
3901 Center: box_.Center,
3902 Extents: box_.Extents,
3903 Orientation: XMFLOAT4::set(0.0, 0.0, 0.0, 1.0)
3904 };
3905 return self.IntersectsOrientedBox(&obox);
3906 }
3907
3908 #[inline]
3912 pub fn IntersectsOrientedBox(&self, box_: &BoundingOrientedBox) -> bool {
3913 const SelectY: XMVECTOR = unsafe { XMVECTORU32 { u: [ XM_SELECT_0, XM_SELECT_1, XM_SELECT_0, XM_SELECT_0 ] }.v };
3914 const SelectZ: XMVECTOR = unsafe { XMVECTORU32 { u: [ XM_SELECT_0, XM_SELECT_0, XM_SELECT_1, XM_SELECT_0 ] }.v };
3915
3916 let Zero: XMVECTOR = XMVectorZero();
3917
3918 let mut Planes: [XMVECTOR; 6] = unsafe { undefined() };
3920 Planes[0] = XMVectorSet(0.0, 0.0, -1.0, self.Near);
3921 Planes[1] = XMVectorSet(0.0, 0.0, 1.0, -self.Far);
3922 Planes[2] = XMVectorSet(1.0, 0.0, -self.RightSlope, 0.0);
3923 Planes[3] = XMVectorSet(-1.0, 0.0, self.LeftSlope, 0.0);
3924 Planes[4] = XMVectorSet(0.0, 1.0, -self.TopSlope, 0.0);
3925 Planes[5] = XMVectorSet(0.0, -1.0, self.BottomSlope, 0.0);
3926
3927 let vOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
3929 let FrustumOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
3930
3931 debug_assert!(internal::XMQuaternionIsUnit(FrustumOrientation));
3932
3933 let mut Center: XMVECTOR = XMLoadFloat3(&box_.Center);
3935 let Extents: XMVECTOR = XMLoadFloat3(&box_.Extents);
3936 let mut BoxOrientation: XMVECTOR = XMLoadFloat4(&box_.Orientation);
3937
3938 debug_assert!(internal::XMQuaternionIsUnit(BoxOrientation));
3939
3940 Center = XMVector3InverseRotate(XMVectorSubtract(Center, vOrigin), FrustumOrientation);
3943 BoxOrientation = XMQuaternionMultiply(BoxOrientation, XMQuaternionConjugate(FrustumOrientation));
3944
3945 Center = XMVectorInsert(Center, XMVectorSplatOne(), 0, 0, 0, 0, 1);
3947
3948 let R: XMMATRIX = XMMatrixRotationQuaternion(BoxOrientation);
3950
3951 let mut Outside: XMVECTOR = XMVectorFalseInt();
3953 let mut InsideAll: XMVECTOR = XMVectorTrueInt();
3954 let mut CenterInsideAll: XMVECTOR = XMVectorTrueInt();
3955
3956 for i in 0 .. 6
3958 {
3959 let Dist: XMVECTOR = XMVector4Dot(Center, Planes[i]);
3961
3962 unsafe {
3968 let mut Radius: XMVECTOR = XMVector3Dot(Planes[i], R.r[0]);
3969 Radius = XMVectorSelect(Radius, XMVector3Dot(Planes[i], R.r[1]), SelectY);
3970 Radius = XMVectorSelect(Radius, XMVector3Dot(Planes[i], R.r[2]), SelectZ);
3971 Radius = XMVector3Dot(Extents, XMVectorAbs(Radius));
3972
3973 Outside = XMVectorOrInt(Outside, XMVectorGreater(Dist, Radius));
3975
3976 InsideAll = XMVectorAndInt(InsideAll, XMVectorLessOrEqual(Dist, XMVectorNegate(Radius)));
3978
3979 CenterInsideAll = XMVectorAndInt(CenterInsideAll, XMVectorLessOrEqual(Dist, Zero));
3981 }
3982 }
3983
3984 if (XMVector4EqualInt(Outside, XMVectorTrueInt())) {
3986 return false;
3987 }
3988
3989 if (XMVector4EqualInt(InsideAll, XMVectorTrueInt())) {
3991 return true;
3992 }
3993
3994 if (XMVector4EqualInt(CenterInsideAll, XMVectorTrueInt())) {
3997 return true;
3998 }
3999
4000 let vRightTop: XMVECTOR = XMVectorSet(self.RightSlope, self.TopSlope, 1.0, 0.0);
4002 let vRightBottom: XMVECTOR = XMVectorSet(self.RightSlope, self.BottomSlope, 1.0, 0.0);
4003 let vLeftTop: XMVECTOR = XMVectorSet(self.LeftSlope, self.TopSlope, 1.0, 0.0);
4004 let vLeftBottom: XMVECTOR = XMVectorSet(self.LeftSlope, self.BottomSlope, 1.0, 0.0);
4005 let vNear: XMVECTOR = XMVectorReplicatePtr(&self.Near);
4006 let vFar: XMVECTOR = XMVectorReplicatePtr(&self.Far);
4007
4008 let mut Corners: [XMVECTOR; Self::CORNER_COUNT] = unsafe { undefined() };
4009 Corners[0] = XMVectorMultiply(vRightTop, vNear);
4010 Corners[1] = XMVectorMultiply(vRightBottom, vNear);
4011 Corners[2] = XMVectorMultiply(vLeftTop, vNear);
4012 Corners[3] = XMVectorMultiply(vLeftBottom, vNear);
4013 Corners[4] = XMVectorMultiply(vRightTop, vFar);
4014 Corners[5] = XMVectorMultiply(vRightBottom, vFar);
4015 Corners[6] = XMVectorMultiply(vLeftTop, vFar);
4016 Corners[7] = XMVectorMultiply(vLeftBottom, vFar);
4017
4018 unsafe {
4019 {
4021 let mut FrustumMin: XMVECTOR;
4023 let mut FrustumMax: XMVECTOR;
4024
4025 FrustumMin = XMVector3Dot(Corners[0], R.r[0]);
4026 FrustumMin = XMVectorSelect(FrustumMin, XMVector3Dot(Corners[0], R.r[1]), SelectY);
4027 FrustumMin = XMVectorSelect(FrustumMin, XMVector3Dot(Corners[0], R.r[2]), SelectZ);
4028 FrustumMax = FrustumMin;
4029
4030 for i in 1 .. BoundingOrientedBox::CORNER_COUNT
4032 {
4033 let mut Temp: XMVECTOR = XMVector3Dot(Corners[i], R.r[0]);
4034 Temp = XMVectorSelect(Temp, XMVector3Dot(Corners[i], R.r[1]), SelectY);
4035 Temp = XMVectorSelect(Temp, XMVector3Dot(Corners[i], R.r[2]), SelectZ);
4036
4037 FrustumMin = XMVectorMin(FrustumMin, Temp);
4038 FrustumMax = XMVectorMax(FrustumMax, Temp);
4039 }
4040
4041 let mut BoxDist: XMVECTOR = XMVector3Dot(Center, R.r[0]);
4043 BoxDist = XMVectorSelect(BoxDist, XMVector3Dot(Center, R.r[1]), SelectY);
4044 BoxDist = XMVectorSelect(BoxDist, XMVector3Dot(Center, R.r[2]), SelectZ);
4045
4046 let Result: XMVECTOR = XMVectorOrInt(XMVectorGreater(FrustumMin, XMVectorAdd(BoxDist, Extents)),
4049 XMVectorLess(FrustumMax, XMVectorSubtract(BoxDist, Extents)));
4050
4051 if (internal::XMVector3AnyTrue(Result)) {
4052 return false;
4053 }
4054 }
4055
4056 let mut FrustumEdgeAxis: [XMVECTOR; 6] = undefined();
4058
4059 FrustumEdgeAxis[0] = vRightTop;
4060 FrustumEdgeAxis[1] = vRightBottom;
4061 FrustumEdgeAxis[2] = vLeftTop;
4062 FrustumEdgeAxis[3] = vLeftBottom;
4063 FrustumEdgeAxis[4] = XMVectorSubtract(vRightTop, vLeftTop);
4064 FrustumEdgeAxis[5] = XMVectorSubtract(vLeftBottom, vLeftTop);
4065
4066 for i in 0 .. 3
4068 {
4069 for j in 0 .. 6
4071 {
4072 let Axis: XMVECTOR = XMVector3Cross(R.r[i], FrustumEdgeAxis[j]);
4074
4075 let mut FrustumMin: XMVECTOR;
4077 let mut FrustumMax: XMVECTOR;
4078
4079 FrustumMin = XMVector3Dot(Axis, Corners[0]);
4080 FrustumMax = FrustumMin;
4081
4082 for k in 1 .. Self::CORNER_COUNT
4084 {
4085 let Temp: XMVECTOR = XMVector3Dot(Axis, Corners[k]);
4086 FrustumMin = XMVectorMin(FrustumMin, Temp);
4087 FrustumMax = XMVectorMax(FrustumMax, Temp);
4088 }
4089
4090 let Dist: XMVECTOR = XMVector3Dot(Center, Axis);
4092
4093 let mut Radius: XMVECTOR = XMVector3Dot(Axis, R.r[0]);
4095 Radius = XMVectorSelect(Radius, XMVector3Dot(Axis, R.r[1]), SelectY);
4096 Radius = XMVectorSelect(Radius, XMVector3Dot(Axis, R.r[2]), SelectZ);
4097 Radius = XMVector3Dot(Extents, XMVectorAbs(Radius));
4098
4099 Outside = XMVectorOrInt(Outside, XMVectorGreater(Dist, XMVectorAdd(FrustumMax, Radius)));
4101 Outside = XMVectorOrInt(Outside, XMVectorLess(Dist, XMVectorSubtract(FrustumMin, Radius)));
4102 }
4103 }
4104 }
4105
4106 if (XMVector4EqualInt(Outside, XMVectorTrueInt())) {
4107 return false;
4108 }
4109
4110 return true;
4112 }
4113
4114 #[inline]
4118 pub fn IntersectsFrustum(&self, fr: &BoundingFrustum) -> bool {
4119 let OriginB: XMVECTOR = XMLoadFloat3(&self.Origin);
4121 let OrientationB: XMVECTOR = XMLoadFloat4(&self.Orientation);
4122
4123 debug_assert!(internal::XMQuaternionIsUnit(OrientationB));
4124
4125 let mut AxisB: [XMVECTOR; 6] = unsafe { undefined() };
4127 AxisB[0] = XMVectorSet(0.0, 0.0, -1.0, 0.0);
4128 AxisB[1] = XMVectorSet(0.0, 0.0, 1.0, 0.0);
4129 AxisB[2] = XMVectorSet(1.0, 0.0, -self.RightSlope, 0.0);
4130 AxisB[3] = XMVectorSet(-1.0, 0.0, self.LeftSlope, 0.0);
4131 AxisB[4] = XMVectorSet(0.0, 1.0, -self.TopSlope, 0.0);
4132 AxisB[5] = XMVectorSet(0.0, -1.0, self.BottomSlope, 0.0);
4133
4134 let mut PlaneDistB: [XMVECTOR; 6] = unsafe { undefined() };
4135 PlaneDistB[0] = XMVectorNegate(XMVectorReplicatePtr(&self.Near));
4136 PlaneDistB[1] = XMVectorReplicatePtr(&self.Far);
4137 PlaneDistB[2] = XMVectorZero();
4138 PlaneDistB[3] = XMVectorZero();
4139 PlaneDistB[4] = XMVectorZero();
4140 PlaneDistB[5] = XMVectorZero();
4141
4142 let mut OriginA: XMVECTOR = XMLoadFloat3(&fr.Origin);
4144 let mut OrientationA: XMVECTOR = XMLoadFloat4(&fr.Orientation);
4145
4146 debug_assert!(internal::XMQuaternionIsUnit(OrientationA));
4147
4148 OriginA = XMVector3InverseRotate(XMVectorSubtract(OriginA, OriginB), OrientationB);
4151 OrientationA = XMQuaternionMultiply(OrientationA, XMQuaternionConjugate(OrientationB));
4152
4153 let mut RightTopA: XMVECTOR = XMVectorSet(fr.RightSlope, fr.TopSlope, 1.0, 0.0);
4155 let mut RightBottomA: XMVECTOR = XMVectorSet(fr.RightSlope, fr.BottomSlope, 1.0, 0.0);
4156 let mut LeftTopA: XMVECTOR = XMVectorSet(fr.LeftSlope, fr.TopSlope, 1.0, 0.0);
4157 let mut LeftBottomA: XMVECTOR = XMVectorSet(fr.LeftSlope, fr.BottomSlope, 1.0, 0.0);
4158 let NearA: XMVECTOR = XMVectorReplicatePtr(&fr.Near);
4159 let FarA: XMVECTOR = XMVectorReplicatePtr(&fr.Far);
4160
4161 RightTopA = XMVector3Rotate(RightTopA, OrientationA);
4162 RightBottomA = XMVector3Rotate(RightBottomA, OrientationA);
4163 LeftTopA = XMVector3Rotate(LeftTopA, OrientationA);
4164 LeftBottomA = XMVector3Rotate(LeftBottomA, OrientationA);
4165
4166 let mut CornersA: [XMVECTOR; Self::CORNER_COUNT] = unsafe { undefined() };
4167 CornersA[0] = XMVectorMultiplyAdd(RightTopA, NearA, OriginA);
4168 CornersA[1] = XMVectorMultiplyAdd(RightBottomA, NearA, OriginA);
4169 CornersA[2] = XMVectorMultiplyAdd(LeftTopA, NearA, OriginA);
4170 CornersA[3] = XMVectorMultiplyAdd(LeftBottomA, NearA, OriginA);
4171 CornersA[4] = XMVectorMultiplyAdd(RightTopA, FarA, OriginA);
4172 CornersA[5] = XMVectorMultiplyAdd(RightBottomA, FarA, OriginA);
4173 CornersA[6] = XMVectorMultiplyAdd(LeftTopA, FarA, OriginA);
4174 CornersA[7] = XMVectorMultiplyAdd(LeftBottomA, FarA, OriginA);
4175
4176 let mut Outside: XMVECTOR = XMVectorFalseInt();
4178 let mut InsideAll: XMVECTOR = XMVectorTrueInt();
4179
4180 for i in 0 .. 6
4182 {
4183 let mut Min: XMVECTOR;
4185 let mut Max: XMVECTOR;
4186
4187 Min = XMVector3Dot(AxisB[i], CornersA[0]);
4188 Max = Min;
4189
4190 for j in 1 .. Self::CORNER_COUNT
4192 {
4193 let Temp: XMVECTOR = XMVector3Dot(AxisB[i], CornersA[j]);
4194 Min = XMVectorMin(Min, Temp);
4195 Max = XMVectorMax(Max, Temp);
4196 }
4197
4198 Outside = XMVectorOrInt(Outside, XMVectorGreater(Min, PlaneDistB[i]));
4200
4201 InsideAll = XMVectorAndInt(InsideAll, XMVectorLessOrEqual(Max, PlaneDistB[i]));
4203 }
4204
4205 if (XMVector4EqualInt(Outside, XMVectorTrueInt())) {
4207 return false;
4208 }
4209
4210 if (XMVector4EqualInt(InsideAll, XMVectorTrueInt())) {
4212 return true;
4213 }
4214
4215 let RightTopB: XMVECTOR = XMVectorSet(self.RightSlope, self.TopSlope, 1.0, 0.0);
4217 let RightBottomB: XMVECTOR = XMVectorSet(self.RightSlope, self.BottomSlope, 1.0, 0.0);
4218 let LeftTopB: XMVECTOR = XMVectorSet(self.LeftSlope, self.TopSlope, 1.0, 0.0);
4219 let LeftBottomB: XMVECTOR = XMVectorSet(self.LeftSlope, self.BottomSlope, 1.0, 0.0);
4220 let NearB: XMVECTOR = XMVectorReplicatePtr(&self.Near);
4221 let FarB: XMVECTOR = XMVectorReplicatePtr(&self.Far);
4222
4223 let mut CornersB: [XMVECTOR; BoundingFrustum::CORNER_COUNT] = unsafe { undefined() };
4224 CornersB[0] = XMVectorMultiply(RightTopB, NearB);
4225 CornersB[1] = XMVectorMultiply(RightBottomB, NearB);
4226 CornersB[2] = XMVectorMultiply(LeftTopB, NearB);
4227 CornersB[3] = XMVectorMultiply(LeftBottomB, NearB);
4228 CornersB[4] = XMVectorMultiply(RightTopB, FarB);
4229 CornersB[5] = XMVectorMultiply(RightBottomB, FarB);
4230 CornersB[6] = XMVectorMultiply(LeftTopB, FarB);
4231 CornersB[7] = XMVectorMultiply(LeftBottomB, FarB);
4232
4233 let mut AxisA: [XMVECTOR; 6] = unsafe { undefined() };
4235 let mut PlaneDistA: [XMVECTOR; 6] = unsafe { undefined() };
4236
4237 AxisA[0] = XMVectorSet(0.0, 0.0, -1.0, 0.0);
4238 AxisA[1] = XMVectorSet(0.0, 0.0, 1.0, 0.0);
4239 AxisA[2] = XMVectorSet(1.0, 0.0, -fr.RightSlope, 0.0);
4240 AxisA[3] = XMVectorSet(-1.0, 0.0, fr.LeftSlope, 0.0);
4241 AxisA[4] = XMVectorSet(0.0, 1.0, -fr.TopSlope, 0.0);
4242 AxisA[5] = XMVectorSet(0.0, -1.0, fr.BottomSlope, 0.0);
4243
4244 AxisA[0] = XMVector3Rotate(AxisA[0], OrientationA);
4245 AxisA[1] = XMVectorNegate(AxisA[0]);
4246 AxisA[2] = XMVector3Rotate(AxisA[2], OrientationA);
4247 AxisA[3] = XMVector3Rotate(AxisA[3], OrientationA);
4248 AxisA[4] = XMVector3Rotate(AxisA[4], OrientationA);
4249 AxisA[5] = XMVector3Rotate(AxisA[5], OrientationA);
4250
4251 PlaneDistA[0] = XMVector3Dot(AxisA[0], CornersA[0]); PlaneDistA[1] = XMVector3Dot(AxisA[1], CornersA[4]); PlaneDistA[2] = XMVector3Dot(AxisA[2], OriginA);
4254 PlaneDistA[3] = XMVector3Dot(AxisA[3], OriginA);
4255 PlaneDistA[4] = XMVector3Dot(AxisA[4], OriginA);
4256 PlaneDistA[5] = XMVector3Dot(AxisA[5], OriginA);
4257
4258 for i in 0 .. 6
4261 {
4262 let mut Min: XMVECTOR;
4264
4265 Min = XMVector3Dot(AxisA[i], CornersB[0]);
4266
4267 for j in 0 .. Self::CORNER_COUNT
4269 {
4270 let Temp: XMVECTOR = XMVector3Dot(AxisA[i], CornersB[j]);
4271 Min = XMVectorMin(Min, Temp);
4272 }
4273
4274 Outside = XMVectorOrInt(Outside, XMVectorGreater(Min, PlaneDistA[i]));
4276 }
4277
4278 if (XMVector4EqualInt(Outside, XMVectorTrueInt())) {
4280 return false;
4281 }
4282
4283 let mut FrustumEdgeAxisA: [XMVECTOR; 6] = unsafe { undefined() };
4285 FrustumEdgeAxisA[0] = RightTopA;
4286 FrustumEdgeAxisA[1] = RightBottomA;
4287 FrustumEdgeAxisA[2] = LeftTopA;
4288 FrustumEdgeAxisA[3] = LeftBottomA;
4289 FrustumEdgeAxisA[4] = XMVectorSubtract(RightTopA, LeftTopA);
4290 FrustumEdgeAxisA[5] = XMVectorSubtract(LeftBottomA, LeftTopA);
4291
4292 let mut FrustumEdgeAxisB: [XMVECTOR; 6] = unsafe { undefined() };
4293 FrustumEdgeAxisB[0] = RightTopB;
4294 FrustumEdgeAxisB[1] = RightBottomB;
4295 FrustumEdgeAxisB[2] = LeftTopB;
4296 FrustumEdgeAxisB[3] = LeftBottomB;
4297 FrustumEdgeAxisB[4] = XMVectorSubtract(RightTopB, LeftTopB);
4298 FrustumEdgeAxisB[5] = XMVectorSubtract(LeftBottomB, LeftTopB);
4299
4300 for i in 0 .. 6
4302 {
4303 for j in 0 .. 6
4305 {
4306 let Axis: XMVECTOR = XMVector3Cross(FrustumEdgeAxisA[i], FrustumEdgeAxisB[j]);
4308
4309 let mut MinA: XMVECTOR; let mut MaxA: XMVECTOR;
4311 let mut MinB: XMVECTOR; let mut MaxB: XMVECTOR;
4312
4313 MinA = XMVector3Dot(Axis, CornersA[0]);
4314 MaxA = MinA;
4315 MinB = XMVector3Dot(Axis, CornersB[0]);
4316 MaxB = MinB;
4317
4318 for k in 1 .. Self::CORNER_COUNT
4320 {
4321 let TempA: XMVECTOR = XMVector3Dot(Axis, CornersA[k]);
4322 MinA = XMVectorMin(MinA, TempA);
4323 MaxA = XMVectorMax(MaxA, TempA);
4324
4325 let TempB: XMVECTOR = XMVector3Dot(Axis, CornersB[k]);
4326 MinB = XMVectorMin(MinB, TempB);
4327 MaxB = XMVectorMax(MaxB, TempB);
4328 }
4329
4330 Outside = XMVectorOrInt(Outside, XMVectorGreater(MinA, MaxB));
4332 Outside = XMVectorOrInt(Outside, XMVectorGreater(MinB, MaxA));
4333 }
4334 }
4335
4336 if (XMVector4EqualInt(Outside, XMVectorTrueInt())) {
4338 return false;
4339 }
4340
4341 return true;
4343 }
4344
4345 #[inline]
4363 pub fn IntersectsTriangle(&self, V0: FXMVECTOR, V1: FXMVECTOR, V2: FXMVECTOR) -> bool {
4364 let mut Planes: [XMVECTOR; 6] = unsafe { undefined() };
4366 Planes[0] = XMVectorSet(0.0, 0.0, -1.0, -self.Near);
4367 Planes[1] = XMVectorSet(0.0, 0.0, 1.0, self.Far);
4368 Planes[2] = XMVectorSet(1.0, 0.0, -self.RightSlope, 0.0);
4369 Planes[3] = XMVectorSet(-1.0, 0.0, self.LeftSlope, 0.0);
4370 Planes[4] = XMVectorSet(0.0, 1.0, -self.TopSlope, 0.0);
4371 Planes[5] = XMVectorSet(0.0, -1.0, self.BottomSlope, 0.0);
4372
4373 let vOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
4375 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
4376
4377 debug_assert!(internal::XMQuaternionIsUnit(vOrientation));
4378
4379 let TV0: XMVECTOR = XMVector3InverseRotate(XMVectorSubtract(V0, vOrigin), vOrientation);
4381 let TV1: XMVECTOR = XMVector3InverseRotate(XMVectorSubtract(V1, vOrigin), vOrientation);
4382 let TV2: XMVECTOR = XMVector3InverseRotate(XMVectorSubtract(V2, vOrigin), vOrientation);
4383
4384 let mut Outside: XMVECTOR = XMVectorFalseInt();
4386 let mut InsideAll: XMVECTOR = XMVectorTrueInt();
4387
4388 for i in 0 .. 6
4389 {
4390 let Dist0: XMVECTOR = XMVector3Dot(TV0, Planes[i]);
4391 let Dist1: XMVECTOR = XMVector3Dot(TV1, Planes[i]);
4392 let Dist2: XMVECTOR = XMVector3Dot(TV2, Planes[i]);
4393
4394 let mut MinDist: XMVECTOR = XMVectorMin(Dist0, Dist1);
4395 MinDist = XMVectorMin(MinDist, Dist2);
4396 let mut MaxDist: XMVECTOR = XMVectorMax(Dist0, Dist1);
4397 MaxDist = XMVectorMax(MaxDist, Dist2);
4398
4399 let PlaneDist: XMVECTOR = XMVectorSplatW(Planes[i]);
4400
4401 Outside = XMVectorOrInt(Outside, XMVectorGreater(MinDist, PlaneDist));
4403
4404 InsideAll = XMVectorAndInt(InsideAll, XMVectorLessOrEqual(MaxDist, PlaneDist));
4406 }
4407
4408 if (XMVector4EqualInt(Outside, XMVectorTrueInt())) {
4410 return false;
4411 }
4412
4413 if (XMVector4EqualInt(InsideAll, XMVectorTrueInt())) {
4415 return true;
4416 }
4417
4418 let vRightTop: XMVECTOR = XMVectorSet(self.RightSlope, self.TopSlope, 1.0, 0.0);
4420 let vRightBottom: XMVECTOR = XMVectorSet(self.RightSlope, self.BottomSlope, 1.0, 0.0);
4421 let vLeftTop: XMVECTOR = XMVectorSet(self.LeftSlope, self.TopSlope, 1.0, 0.0);
4422 let vLeftBottom: XMVECTOR = XMVectorSet(self.LeftSlope, self.BottomSlope, 1.0, 0.0);
4423 let vNear: XMVECTOR = XMVectorReplicatePtr(&self.Near);
4424 let vFar: XMVECTOR = XMVectorReplicatePtr(&self.Far);
4425
4426 let mut Corners: [XMVECTOR; Self::CORNER_COUNT] = unsafe { undefined() };
4427 Corners[0] = XMVectorMultiply(vRightTop, vNear);
4428 Corners[1] = XMVectorMultiply(vRightBottom, vNear);
4429 Corners[2] = XMVectorMultiply(vLeftTop, vNear);
4430 Corners[3] = XMVectorMultiply(vLeftBottom, vNear);
4431 Corners[4] = XMVectorMultiply(vRightTop, vFar);
4432 Corners[5] = XMVectorMultiply(vRightBottom, vFar);
4433 Corners[6] = XMVectorMultiply(vLeftTop, vFar);
4434 Corners[7] = XMVectorMultiply(vLeftBottom, vFar);
4435
4436 let Normal: XMVECTOR = XMVector3Cross(XMVectorSubtract(V1, V0), XMVectorSubtract(V2, V0));
4438 let Dist: XMVECTOR = XMVector3Dot(Normal, V0);
4439
4440 let mut MinDist: XMVECTOR;
4441 let mut MaxDist: XMVECTOR;
4442
4443 MinDist = XMVector3Dot(Corners[0], Normal);
4444 MaxDist = MinDist;
4445
4446 for i in 1 .. Self::CORNER_COUNT
4447 {
4448 let Temp: XMVECTOR = XMVector3Dot(Corners[i], Normal);
4449 MinDist = XMVectorMin(MinDist, Temp);
4450 MaxDist = XMVectorMax(MaxDist, Temp);
4451 }
4452
4453 Outside = XMVectorOrInt(XMVectorGreater(MinDist, Dist), XMVectorLess(MaxDist, Dist));
4454 if (XMVector4EqualInt(Outside, XMVectorTrueInt())) {
4455 return false;
4456 }
4457
4458 let mut TriangleEdgeAxis: [XMVECTOR; 3] = unsafe { undefined() };
4460 TriangleEdgeAxis[0] = XMVectorSubtract(V1, V0);
4461 TriangleEdgeAxis[1] = XMVectorSubtract(V2, V1);
4462 TriangleEdgeAxis[2] = XMVectorSubtract(V0, V2);
4463
4464 let mut FrustumEdgeAxis: [XMVECTOR; 6] = unsafe { undefined() };
4465 FrustumEdgeAxis[0] = vRightTop;
4466 FrustumEdgeAxis[1] = vRightBottom;
4467 FrustumEdgeAxis[2] = vLeftTop;
4468 FrustumEdgeAxis[3] = vLeftBottom;
4469 FrustumEdgeAxis[4] = XMVectorSubtract(vRightTop, vLeftTop);
4470 FrustumEdgeAxis[5] = XMVectorSubtract(vLeftBottom, vLeftTop);
4471
4472 for i in 0 .. 3
4473 {
4474 for j in 0 .. 6
4475 {
4476 let Axis: XMVECTOR = XMVector3Cross(TriangleEdgeAxis[i], FrustumEdgeAxis[j]);
4478
4479 let mut MinA: XMVECTOR;
4481 let mut MaxA: XMVECTOR;
4482
4483 let Dist0: XMVECTOR = XMVector3Dot(V0, Axis);
4484 let Dist1: XMVECTOR = XMVector3Dot(V1, Axis);
4485 let Dist2: XMVECTOR = XMVector3Dot(V2, Axis);
4486
4487 MinA = XMVectorMin(Dist0, Dist1);
4488 MinA = XMVectorMin(MinA, Dist2);
4489 MaxA = XMVectorMax(Dist0, Dist1);
4490 MaxA = XMVectorMax(MaxA, Dist2);
4491
4492 let mut MinB: XMVECTOR;
4494 let mut MaxB: XMVECTOR;
4495
4496 MinB = XMVector3Dot(Axis, Corners[0]);
4497 MaxB = MinB;
4498
4499 for k in 1 .. Self::CORNER_COUNT
4501 {
4502 let Temp: XMVECTOR = XMVector3Dot(Axis, Corners[k]);
4503 MinB = XMVectorMin(MinB, Temp);
4504 MaxB = XMVectorMax(MaxB, Temp);
4505 }
4506
4507 Outside = XMVectorOrInt(Outside, XMVectorGreater(MinA, MaxB));
4509 Outside = XMVectorOrInt(Outside, XMVectorGreater(MinB, MaxA));
4510 }
4511 }
4512
4513 if (XMVector4EqualInt(Outside, XMVectorTrueInt())) {
4514 return false;
4515 }
4516
4517 return true;
4519 }
4520
4521 #[inline]
4535 pub fn IntersectsPlane(&self, Plane: FXMVECTOR) -> PlaneIntersectionType {
4536 debug_assert!(internal::XMPlaneIsUnit(Plane));
4537
4538 let mut vOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
4540 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
4541
4542 debug_assert!(internal::XMQuaternionIsUnit(vOrientation));
4543
4544 vOrigin = XMVectorInsert(vOrigin, XMVectorSplatOne(), 0, 0, 0, 0, 1);
4547
4548 let mut RightTop: XMVECTOR = XMVectorSet(self.RightSlope, self.TopSlope, 1.0, 0.0);
4550 let mut RightBottom: XMVECTOR = XMVectorSet(self.RightSlope, self.BottomSlope, 1.0, 0.0);
4551 let mut LeftTop: XMVECTOR = XMVectorSet(self.LeftSlope, self.TopSlope, 1.0, 0.0);
4552 let mut LeftBottom: XMVECTOR = XMVectorSet(self.LeftSlope, self.BottomSlope, 1.0, 0.0);
4553 let vNear: XMVECTOR = XMVectorReplicatePtr(&self.Near);
4554 let vFar: XMVECTOR = XMVectorReplicatePtr(&self.Far);
4555
4556 RightTop = XMVector3Rotate(RightTop, vOrientation);
4557 RightBottom = XMVector3Rotate(RightBottom, vOrientation);
4558 LeftTop = XMVector3Rotate(LeftTop, vOrientation);
4559 LeftBottom = XMVector3Rotate(LeftBottom, vOrientation);
4560
4561 let Corners0: XMVECTOR = XMVectorMultiplyAdd(RightTop, vNear, vOrigin);
4562 let Corners1: XMVECTOR = XMVectorMultiplyAdd(RightBottom, vNear, vOrigin);
4563 let Corners2: XMVECTOR = XMVectorMultiplyAdd(LeftTop, vNear, vOrigin);
4564 let Corners3: XMVECTOR = XMVectorMultiplyAdd(LeftBottom, vNear, vOrigin);
4565 let Corners4: XMVECTOR = XMVectorMultiplyAdd(RightTop, vFar, vOrigin);
4566 let Corners5: XMVECTOR = XMVectorMultiplyAdd(RightBottom, vFar, vOrigin);
4567 let Corners6: XMVECTOR = XMVectorMultiplyAdd(LeftTop, vFar, vOrigin);
4568 let Corners7: XMVECTOR = XMVectorMultiplyAdd(LeftBottom, vFar, vOrigin);
4569
4570 let mut Inside: XMVECTOR = unsafe { undefined() };
4571 let mut Outside: XMVECTOR = unsafe { undefined() };
4572
4573 internal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3,
4574 Corners4, Corners5, &Corners6, &Corners7,
4575 &Plane, &mut Outside, &mut Inside);
4576
4577 if (XMVector4EqualInt(Outside, XMVectorTrueInt())) {
4579 return FRONT;
4580 }
4581
4582 if (XMVector4EqualInt(Inside, XMVectorTrueInt())) {
4584 return BACK;
4585 }
4586
4587 return INTERSECTING;
4589 }
4590
4591 #[inline]
4614 pub fn IntersectsRay(&self, rayOrigin: FXMVECTOR, Direction: FXMVECTOR, Dist: &mut f32) -> bool {
4615 if (self.ContainsPoint(rayOrigin) == CONTAINS)
4617 {
4618 *Dist = 0.0;
4619 return true;
4620 }
4621
4622 let mut Planes: [XMVECTOR; 6] = unsafe { undefined() };
4624 Planes[0] = XMVectorSet(0.0, 0.0, -1.0, self.Near);
4625 Planes[1] = XMVectorSet(0.0, 0.0, 1.0, -self.Far);
4626 Planes[2] = XMVectorSet(1.0, 0.0, -self.RightSlope, 0.0);
4627 Planes[3] = XMVectorSet(-1.0, 0.0, self.LeftSlope, 0.0);
4628 Planes[4] = XMVectorSet(0.0, 1.0, -self.TopSlope, 0.0);
4629 Planes[5] = XMVectorSet(0.0, -1.0, self.BottomSlope, 0.0);
4630
4631 let frOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
4633 let frOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
4634
4635 let mut tnear: f32 = -FLT_MAX;
4637 let mut tfar: f32 = FLT_MAX;
4638
4639 for i in 0 .. 6
4641 {
4642 let mut Plane: XMVECTOR = internal::XMPlaneTransform(Planes[i], frOrientation, frOrigin);
4643 Plane = XMPlaneNormalize(Plane);
4644
4645 let AxisDotOrigin: XMVECTOR = XMPlaneDotCoord(Plane, rayOrigin);
4646 let AxisDotDirection: XMVECTOR = XMVector3Dot(Plane, Direction);
4647
4648 if (XMVector3LessOrEqual(XMVectorAbs(AxisDotDirection), g_RayEpsilon.v()))
4649 {
4650 if (XMVector3Greater(AxisDotOrigin, g_XMZero.v()))
4652 {
4653 *Dist = 0.0;
4655 return false;
4656 }
4657 }
4658 else
4659 {
4660 let vd: f32 = XMVectorGetX(AxisDotDirection);
4662 let vn: f32 = XMVectorGetX(AxisDotOrigin);
4663 let t: f32 = -vn / vd;
4664 if (vd < 0.0)
4665 {
4666 if (t > tfar)
4668 {
4669 *Dist = 0.0;
4670 return false;
4671 }
4672 if (t > tnear)
4673 {
4674 tnear = t;
4676 }
4677 }
4678 else
4679 {
4680 if (t < tnear)
4682 {
4683 *Dist = 0.0;
4684 return false;
4685 }
4686 if (t < tfar)
4687 {
4688 tfar = t;
4690 }
4691 }
4692 }
4693 }
4694
4695 let distance: f32 = if (tnear >= 0.00) { tnear } else { tfar };
4699 if (distance >= 0.0)
4700 {
4701 *Dist = distance;
4702 return true;
4703 }
4704
4705 *Dist = 0.0;
4706 return false;
4707 }
4708
4709 #[inline]
4733 pub fn ContainedBy(
4734 &self,
4735 Plane0: FXMVECTOR,
4736 Plane1: FXMVECTOR,
4737 Plane2: GXMVECTOR,
4738 Plane3: HXMVECTOR,
4739 Plane4: HXMVECTOR,
4740 Plane5: HXMVECTOR,
4741 ) -> ContainmentType
4742 {
4743 let mut vOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
4745 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
4746
4747 debug_assert!(internal::XMQuaternionIsUnit(vOrientation));
4748
4749 vOrigin = XMVectorInsert(vOrigin, XMVectorSplatOne(), 0, 0, 0, 0, 1);
4752
4753 let mut RightTop: XMVECTOR = XMVectorSet(self.RightSlope, self.TopSlope, 1.0, 0.0);
4755 let mut RightBottom: XMVECTOR = XMVectorSet(self.RightSlope, self.BottomSlope, 1.0, 0.0);
4756 let mut LeftTop: XMVECTOR = XMVectorSet(self.LeftSlope, self.TopSlope, 1.0, 0.0);
4757 let mut LeftBottom: XMVECTOR = XMVectorSet(self.LeftSlope, self.BottomSlope, 1.0, 0.0);
4758 let vNear: XMVECTOR = XMVectorReplicatePtr(&self.Near);
4759 let vFar: XMVECTOR = XMVectorReplicatePtr(&self.Far);
4760
4761 RightTop = XMVector3Rotate(RightTop, vOrientation);
4762 RightBottom = XMVector3Rotate(RightBottom, vOrientation);
4763 LeftTop = XMVector3Rotate(LeftTop, vOrientation);
4764 LeftBottom = XMVector3Rotate(LeftBottom, vOrientation);
4765
4766 let Corners0: XMVECTOR = XMVectorMultiplyAdd(RightTop, vNear, vOrigin);
4767 let Corners1: XMVECTOR = XMVectorMultiplyAdd(RightBottom, vNear, vOrigin);
4768 let Corners2: XMVECTOR = XMVectorMultiplyAdd(LeftTop, vNear, vOrigin);
4769 let Corners3: XMVECTOR = XMVectorMultiplyAdd(LeftBottom, vNear, vOrigin);
4770 let Corners4: XMVECTOR = XMVectorMultiplyAdd(RightTop, vFar, vOrigin);
4771 let Corners5: XMVECTOR = XMVectorMultiplyAdd(RightBottom, vFar, vOrigin);
4772 let Corners6: XMVECTOR = XMVectorMultiplyAdd(LeftTop, vFar, vOrigin);
4773 let Corners7: XMVECTOR = XMVectorMultiplyAdd(LeftBottom, vFar, vOrigin);
4774
4775 let mut Inside: XMVECTOR = unsafe { undefined() };
4776 let mut Outside: XMVECTOR = unsafe { undefined() };
4777
4778 internal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3,
4780 Corners4, Corners5, &Corners6, &Corners7,
4781 &Plane0, &mut Outside, &mut Inside);
4782
4783 let mut AnyOutside: XMVECTOR = Outside;
4784 let mut AllInside: XMVECTOR = Inside;
4785
4786 internal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3,
4787 Corners4, Corners5, &Corners6, &Corners7,
4788 &Plane1, &mut Outside, &mut Inside);
4789
4790 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
4791 AllInside = XMVectorAndInt(AllInside, Inside);
4792
4793 internal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3,
4794 Corners4, Corners5, &Corners6, &Corners7,
4795 &Plane2, &mut Outside, &mut Inside);
4796
4797 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
4798 AllInside = XMVectorAndInt(AllInside, Inside);
4799
4800 internal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3,
4801 Corners4, Corners5, &Corners6, &Corners7,
4802 &Plane3, &mut Outside, &mut Inside);
4803
4804 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
4805 AllInside = XMVectorAndInt(AllInside, Inside);
4806
4807 internal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3,
4808 Corners4, Corners5, &Corners6, &Corners7,
4809 &Plane4, &mut Outside, &mut Inside);
4810
4811 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
4812 AllInside = XMVectorAndInt(AllInside, Inside);
4813
4814 internal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3,
4815 Corners4, Corners5, &Corners6, &Corners7,
4816 &Plane5, &mut Outside, &mut Inside);
4817
4818 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
4819 AllInside = XMVectorAndInt(AllInside, Inside);
4820
4821 if (XMVector4EqualInt(AnyOutside, XMVectorTrueInt())) {
4823 return DISJOINT;
4824 }
4825
4826 if (XMVector4EqualInt(AllInside, XMVectorTrueInt())) {
4828 return CONTAINS;
4829 }
4830
4831 return INTERSECTS;
4833 }
4834
4835 #[inline]
4854 pub fn CreateFromMatrix(Out: &mut Self, Projection: FXMMATRIX, rhcoords: bool) {
4855 const HomogenousPoints: [XMVECTORF32; 6] =
4857 [
4858 XMVECTORF32 { f: [ 1.0, 0.0, 1.0, 1.0 ] }, XMVECTORF32 { f: [ -1.0, 0.0, 1.0, 1.0 ] }, XMVECTORF32 { f: [ 0.0, 1.0, 1.0, 1.0 ] }, XMVECTORF32 { f: [ 0.0, -1.0, 1.0, 1.0 ] }, XMVECTORF32 { f: [ 0.0, 0.0, 0.0, 1.0 ] }, XMVECTORF32 { f: [ 0.0, 0.0, 1.0, 1.0 ] } ];
4866
4867 let mut Determinant: XMVECTOR = unsafe { undefined() };
4868 let matInverse: XMMATRIX = XMMatrixInverse(Some(&mut Determinant), Projection);
4869
4870 let mut Points: [XMVECTOR; 6] = unsafe { undefined() };
4872
4873 for i in 0 .. 6
4875 {
4876 Points[i] = XMVector4Transform(HomogenousPoints[i].v(), matInverse);
4878 }
4879
4880 Out.Origin = XMFLOAT3::set(0.0, 0.0, 0.0);
4881 Out.Orientation = XMFLOAT4::set(0.0, 0.0, 0.0, 1.0);
4882
4883 Points[0] = XMVectorMultiply(Points[0], XMVectorReciprocal(XMVectorSplatZ(Points[0])));
4885 Points[1] = XMVectorMultiply(Points[1], XMVectorReciprocal(XMVectorSplatZ(Points[1])));
4886 Points[2] = XMVectorMultiply(Points[2], XMVectorReciprocal(XMVectorSplatZ(Points[2])));
4887 Points[3] = XMVectorMultiply(Points[3], XMVectorReciprocal(XMVectorSplatZ(Points[3])));
4888
4889 Out.RightSlope = XMVectorGetX(Points[0]);
4890 Out.LeftSlope = XMVectorGetX(Points[1]);
4891 Out.TopSlope = XMVectorGetY(Points[2]);
4892 Out.BottomSlope = XMVectorGetY(Points[3]);
4893
4894 Points[4] = XMVectorMultiply(Points[4], XMVectorReciprocal(XMVectorSplatW(Points[4])));
4896 Points[5] = XMVectorMultiply(Points[5], XMVectorReciprocal(XMVectorSplatW(Points[5])));
4897
4898 if (rhcoords)
4899 {
4900 Out.Near = XMVectorGetZ(Points[5]);
4901 Out.Far = XMVectorGetZ(Points[4]);
4902 }
4903 else
4904 {
4905 Out.Near = XMVectorGetZ(Points[4]);
4906 Out.Far = XMVectorGetZ(Points[5]);
4907 }
4908 }
4909
4910 #[inline]
4934 pub fn GetPlanes(
4935 &self,
4936 NearPlane: Option<&mut XMVECTOR>,
4937 FarPlane: Option<&mut XMVECTOR>,
4938 RightPlane: Option<&mut XMVECTOR>,
4939 LeftPlane: Option<&mut XMVECTOR>,
4940 TopPlane: Option<&mut XMVECTOR>,
4941 BottomPlane: Option<&mut XMVECTOR>,
4942 ) {
4943 let vOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
4956 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
4957
4958 if let Some(NearPlane) = NearPlane
4959 {
4960 let mut vNearPlane: XMVECTOR = XMVectorSet(0.0, 0.0, -1.0, self.Near);
4961 vNearPlane = internal::XMPlaneTransform(vNearPlane, vOrientation, vOrigin);
4962 *NearPlane = XMPlaneNormalize(vNearPlane);
4963 }
4964
4965 if let Some(FarPlane) = FarPlane
4966 {
4967 let mut vFarPlane: XMVECTOR = XMVectorSet(0.0, 0.0, 1.0, -self.Far);
4968 vFarPlane = internal::XMPlaneTransform(vFarPlane, vOrientation, vOrigin);
4969 *FarPlane = XMPlaneNormalize(vFarPlane);
4970 }
4971
4972 if let Some(RightPlane) = RightPlane
4973 {
4974 let mut vRightPlane: XMVECTOR = XMVectorSet(1.0, 0.0, -self.RightSlope, 0.0);
4975 vRightPlane = internal::XMPlaneTransform(vRightPlane, vOrientation, vOrigin);
4976 *RightPlane = XMPlaneNormalize(vRightPlane);
4977 }
4978
4979 if let Some(LeftPlane) = LeftPlane
4980 {
4981 let mut vLeftPlane: XMVECTOR = XMVectorSet(-1.0, 0.0, self.LeftSlope, 0.0);
4982 vLeftPlane = internal::XMPlaneTransform(vLeftPlane, vOrientation, vOrigin);
4983 *LeftPlane = XMPlaneNormalize(vLeftPlane);
4984 }
4985
4986 if let Some(TopPlane) = TopPlane
4987 {
4988 let mut vTopPlane: XMVECTOR = XMVectorSet(0.0, 1.0, -self.TopSlope, 0.0);
4989 vTopPlane = internal::XMPlaneTransform(vTopPlane, vOrientation, vOrigin);
4990 *TopPlane = XMPlaneNormalize(vTopPlane);
4991 }
4992
4993 if let Some(BottomPlane) = BottomPlane
4994 {
4995 let mut vBottomPlane: XMVECTOR = XMVectorSet(0.0, -1.0, self.BottomSlope, 0.0);
4996 vBottomPlane = internal::XMPlaneTransform(vBottomPlane, vOrientation, vOrigin);
4997 *BottomPlane = XMPlaneNormalize(vBottomPlane);
4998 }
4999 }
5000
5001 #[inline]
5020 pub fn GetCorners(&self, Corners: &mut [XMFLOAT3; BoundingFrustum::CORNER_COUNT]) {
5021 let vOrigin: XMVECTOR = XMLoadFloat3(&self.Origin);
5025 let vOrientation: XMVECTOR = XMLoadFloat4(&self.Orientation);
5026
5027 debug_assert!(internal::XMQuaternionIsUnit(vOrientation));
5028
5029 let vRightTop: XMVECTOR = XMVectorSet(self.RightSlope, self.TopSlope, 1.0, 0.0);
5031 let vRightBottom: XMVECTOR = XMVectorSet(self.RightSlope, self.BottomSlope, 1.0, 0.0);
5032 let vLeftTop: XMVECTOR = XMVectorSet(self.LeftSlope, self.TopSlope, 1.0, 0.0);
5033 let vLeftBottom: XMVECTOR = XMVectorSet(self.LeftSlope, self.BottomSlope, 1.0, 0.0);
5034 let vNear: XMVECTOR = XMVectorReplicatePtr(&self.Near);
5035 let vFar: XMVECTOR = XMVectorReplicatePtr(&self.Far);
5036
5037 let mut vCorners: [XMVECTOR; Self::CORNER_COUNT] = unsafe { undefined() };
5045 vCorners[0] = XMVectorMultiply(vLeftTop, vNear);
5046 vCorners[1] = XMVectorMultiply(vRightTop, vNear);
5047 vCorners[2] = XMVectorMultiply(vRightBottom, vNear);
5048 vCorners[3] = XMVectorMultiply(vLeftBottom, vNear);
5049 vCorners[4] = XMVectorMultiply(vLeftTop, vFar);
5050 vCorners[5] = XMVectorMultiply(vRightTop, vFar);
5051 vCorners[6] = XMVectorMultiply(vRightBottom, vFar);
5052 vCorners[7] = XMVectorMultiply(vLeftBottom, vFar);
5053
5054 for i in 0.. Self::CORNER_COUNT
5055 {
5056 let C: XMVECTOR = XMVectorAdd(XMVector3Rotate(vCorners[i], vOrientation), vOrigin);
5057 XMStoreFloat3(&mut Corners[i], C);
5058 }
5059 }
5060}
5061
5062pub mod triangle_tests {
5064 use crate::*;
5065 use super::*;
5066
5067 #[inline]
5096 pub fn IntersectsRay(Origin: FXMVECTOR, Direction: FXMVECTOR, V0: FXMVECTOR, V1: GXMVECTOR, V2: HXMVECTOR, Dist: &mut f32) -> bool {
5097 debug_assert!(internal::XMVector3IsUnit(Direction));
5098
5099 let Zero: XMVECTOR = XMVectorZero();
5100
5101 let e1: XMVECTOR = XMVectorSubtract(V1, V0);
5102 let e2: XMVECTOR = XMVectorSubtract(V2, V0);
5103
5104 let p: XMVECTOR = XMVector3Cross(Direction, e2);
5106
5107 let det: XMVECTOR = XMVector3Dot(e1, p);
5109
5110 let u: XMVECTOR;
5111 let v: XMVECTOR;
5112 let mut t: XMVECTOR;
5113
5114 if (XMVector3GreaterOrEqual(det, g_RayEpsilon.v()))
5115 {
5116 let s: XMVECTOR = XMVectorSubtract(Origin, V0);
5118
5119 u = XMVector3Dot(s, p);
5121
5122 let mut NoIntersection: XMVECTOR = XMVectorLess(u, Zero);
5123 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(u, det));
5124
5125 let q: XMVECTOR = XMVector3Cross(s, e1);
5127
5128 v = XMVector3Dot(Direction, q);
5130
5131 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(v, Zero));
5132 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(XMVectorAdd(u, v), det));
5133
5134 t = XMVector3Dot(e2, q);
5136
5137 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(t, Zero));
5138
5139 if (XMVector4EqualInt(NoIntersection, XMVectorTrueInt()))
5140 {
5141 *Dist = 0.0;
5142 return false;
5143 }
5144 }
5145 else if (XMVector3LessOrEqual(det, g_RayNegEpsilon.v()))
5146 {
5147 let s: XMVECTOR = XMVectorSubtract(Origin, V0);
5149
5150 u = XMVector3Dot(s, p);
5152
5153 let mut NoIntersection: XMVECTOR = XMVectorGreater(u, Zero);
5154 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(u, det));
5155
5156 let q: XMVECTOR = XMVector3Cross(s, e1);
5158
5159 v = XMVector3Dot(Direction, q);
5161
5162 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(v, Zero));
5163 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(XMVectorAdd(u, v), det));
5164
5165 t = XMVector3Dot(e2, q);
5167
5168 NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(t, Zero));
5169
5170 if (XMVector4EqualInt(NoIntersection, XMVectorTrueInt()))
5171 {
5172 *Dist = 0.0;
5173 return false;
5174 }
5175 }
5176 else
5177 {
5178 *Dist = 0.0;
5180 return false;
5181 }
5182
5183 t = XMVectorDivide(t, det);
5184
5185 XMStoreFloat(Dist, t);
5189
5190 return true;
5191 }
5192
5193 #[allow(clippy::cognitive_complexity)]
5217 #[inline]
5218 pub fn IntersectsTriangle(
5219 A0: FXMVECTOR,
5220 A1: FXMVECTOR,
5221 A2: FXMVECTOR,
5222 B0: GXMVECTOR,
5223 B1: HXMVECTOR,
5224 B2: HXMVECTOR,
5225 ) -> bool {
5226 const SelectY: XMVECTORU32 = XMVECTORU32 { u: [ XM_SELECT_0, XM_SELECT_1, XM_SELECT_0, XM_SELECT_0 ] };
5227 const SelectZ: XMVECTORU32 = XMVECTORU32 { u: [ XM_SELECT_0, XM_SELECT_0, XM_SELECT_1, XM_SELECT_0 ] };
5228 const Select0111: XMVECTORU32 = XMVECTORU32 { u: [ XM_SELECT_0, XM_SELECT_1, XM_SELECT_1, XM_SELECT_1 ] };
5229 const Select1011: XMVECTORU32 = XMVECTORU32 { u: [ XM_SELECT_1, XM_SELECT_0, XM_SELECT_1, XM_SELECT_1 ] };
5230 const Select1101: XMVECTORU32 = XMVECTORU32 { u: [ XM_SELECT_1, XM_SELECT_1, XM_SELECT_0, XM_SELECT_1 ] };
5231
5232 let Zero: XMVECTOR = XMVectorZero();
5233
5234 let N1: XMVECTOR = XMVector3Cross(XMVectorSubtract(A1, A0), XMVectorSubtract(A2, A0));
5236
5237 debug_assert!(!XMVector3Equal(N1, Zero));
5239
5240 let mut BDist: XMVECTOR = XMVector3Dot(N1, XMVectorSubtract(B0, A0));
5242 BDist = XMVectorSelect(BDist, XMVector3Dot(N1, XMVectorSubtract(B1, A0)), SelectY.v());
5243 BDist = XMVectorSelect(BDist, XMVector3Dot(N1, XMVectorSubtract(B2, A0)), SelectZ.v());
5244
5245 let mut BDistIsZeroCR: u32 = unsafe { undefined() };
5247 let BDistIsZero: XMVECTOR = XMVectorGreaterR(&mut BDistIsZeroCR, g_RayEpsilon.v(), XMVectorAbs(BDist));
5248 BDist = XMVectorSelect(BDist, Zero, BDistIsZero);
5249
5250 let mut BDistIsLessCR: u32 = unsafe { undefined() };
5251 let BDistIsLess: XMVECTOR = XMVectorGreaterR(&mut BDistIsLessCR, Zero, BDist);
5252
5253 let mut BDistIsGreaterCR: u32 = unsafe { undefined() };
5254 let BDistIsGreater: XMVECTOR = XMVectorGreaterR(&mut BDistIsGreaterCR, BDist, Zero);
5255
5256 if (XMComparisonAllTrue(BDistIsLessCR) || XMComparisonAllTrue(BDistIsGreaterCR)) {
5258 return false;
5259 }
5260
5261 let N2: XMVECTOR = XMVector3Cross(XMVectorSubtract(B1, B0), XMVectorSubtract(B2, B0));
5263
5264 debug_assert!(!XMVector3Equal(N2, Zero));
5266
5267 let mut ADist: XMVECTOR = XMVector3Dot(N2, XMVectorSubtract(A0, B0));
5269 ADist = XMVectorSelect(ADist, XMVector3Dot(N2, XMVectorSubtract(A1, B0)), SelectY.v());
5270 ADist = XMVectorSelect(ADist, XMVector3Dot(N2, XMVectorSubtract(A2, B0)), SelectZ.v());
5271
5272 let mut ADistIsZeroCR: u32 = unsafe { undefined() };
5274 let ADistIsZero: XMVECTOR = XMVectorGreaterR(&mut ADistIsZeroCR, g_RayEpsilon.v(), XMVectorAbs(BDist));
5275 ADist = XMVectorSelect(ADist, Zero, ADistIsZero);
5276
5277 let mut ADistIsLessCR: u32 = unsafe { undefined() };
5278 let ADistIsLess: XMVECTOR = XMVectorGreaterR(&mut ADistIsLessCR, Zero, ADist);
5279
5280 let mut ADistIsGreaterCR: u32 = unsafe { undefined() };
5281 let ADistIsGreater: XMVECTOR = XMVectorGreaterR(&mut ADistIsGreaterCR, ADist, Zero);
5282
5283 if (XMComparisonAllTrue(ADistIsLessCR) || XMComparisonAllTrue(ADistIsGreaterCR)) {
5285 return false;
5286 }
5287
5288 if (XMComparisonAllTrue(ADistIsZeroCR) || XMComparisonAllTrue(BDistIsZeroCR))
5290 {
5291 let mut Axis: XMVECTOR;
5292 let mut Dist: XMVECTOR;
5293 let mut MinDist: XMVECTOR;
5294
5295 Axis = XMVector3Cross(N1, XMVectorSubtract(A1, A0));
5297 Dist = XMVector3Dot(Axis, A0);
5298
5299 MinDist = XMVector3Dot(B0, Axis);
5301 MinDist = XMVectorMin(MinDist, XMVector3Dot(B1, Axis));
5302 MinDist = XMVectorMin(MinDist, XMVector3Dot(B2, Axis));
5303 if (XMVector4GreaterOrEqual(MinDist, Dist)) {
5304 return false;
5305 }
5306
5307 Axis = XMVector3Cross(N1, XMVectorSubtract(A2, A1));
5309 Dist = XMVector3Dot(Axis, A1);
5310
5311 MinDist = XMVector3Dot(B0, Axis);
5312 MinDist = XMVectorMin(MinDist, XMVector3Dot(B1, Axis));
5313 MinDist = XMVectorMin(MinDist, XMVector3Dot(B2, Axis));
5314 if (XMVector4GreaterOrEqual(MinDist, Dist)) {
5315 return false;
5316 }
5317
5318 Axis = XMVector3Cross(N1, XMVectorSubtract(A0, A2));
5320 Dist = XMVector3Dot(Axis, A2);
5321
5322 MinDist = XMVector3Dot(B0, Axis);
5323 MinDist = XMVectorMin(MinDist, XMVector3Dot(B1, Axis));
5324 MinDist = XMVectorMin(MinDist, XMVector3Dot(B2, Axis));
5325 if (XMVector4GreaterOrEqual(MinDist, Dist)) {
5326 return false;
5327 }
5328
5329 Axis = XMVector3Cross(N2, XMVectorSubtract(B1, B0));
5331 Dist = XMVector3Dot(Axis, B0);
5332
5333 MinDist = XMVector3Dot(A0, Axis);
5334 MinDist = XMVectorMin(MinDist, XMVector3Dot(A1, Axis));
5335 MinDist = XMVectorMin(MinDist, XMVector3Dot(A2, Axis));
5336 if (XMVector4GreaterOrEqual(MinDist, Dist)) {
5337 return false;
5338 }
5339
5340 Axis = XMVector3Cross(N2, XMVectorSubtract(B2, B1));
5342 Dist = XMVector3Dot(Axis, B1);
5343
5344 MinDist = XMVector3Dot(A0, Axis);
5345 MinDist = XMVectorMin(MinDist, XMVector3Dot(A1, Axis));
5346 MinDist = XMVectorMin(MinDist, XMVector3Dot(A2, Axis));
5347 if (XMVector4GreaterOrEqual(MinDist, Dist)) {
5348 return false;
5349 }
5350
5351 Axis = XMVector3Cross(N2, XMVectorSubtract(B0, B2));
5353 Dist = XMVector3Dot(Axis, B2);
5354
5355 MinDist = XMVector3Dot(A0, Axis);
5356 MinDist = XMVectorMin(MinDist, XMVector3Dot(A1, Axis));
5357 MinDist = XMVectorMin(MinDist, XMVector3Dot(A2, Axis));
5358 if (XMVector4GreaterOrEqual(MinDist, Dist)) {
5359 return false;
5360 }
5361
5362 return true;
5363 }
5364
5365 let ADistIsLessEqual: XMVECTOR = XMVectorOrInt(ADistIsLess, ADistIsZero);
5380 let ADistIsGreaterEqual: XMVECTOR = XMVectorOrInt(ADistIsGreater, ADistIsZero);
5381
5382 let AA0: XMVECTOR;
5383 let AA1: XMVECTOR;
5384 let AA2: XMVECTOR;
5385 let bPositiveA: bool;
5386
5387 if (internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreaterEqual, ADistIsLess, Select0111.v())) ||
5388 internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreater, ADistIsLessEqual, Select0111.v())))
5389 {
5390 AA0 = A0; AA1 = A1; AA2 = A2;
5392 bPositiveA = true;
5393 }
5394 else if (internal::XMVector3AllTrue(XMVectorSelect(ADistIsLessEqual, ADistIsGreater, Select0111.v())) ||
5395 internal::XMVector3AllTrue(XMVectorSelect(ADistIsLess, ADistIsGreaterEqual, Select0111.v())))
5396 {
5397 AA0 = A0; AA1 = A2; AA2 = A1;
5399 bPositiveA = false;
5400 }
5401 else if (internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreaterEqual, ADistIsLess, Select1011.v())) ||
5402 internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreater, ADistIsLessEqual, Select1011.v())))
5403 {
5404 AA0 = A1; AA1 = A2; AA2 = A0;
5406 bPositiveA = true;
5407 }
5408 else if (internal::XMVector3AllTrue(XMVectorSelect(ADistIsLessEqual, ADistIsGreater, Select1011.v())) ||
5409 internal::XMVector3AllTrue(XMVectorSelect(ADistIsLess, ADistIsGreaterEqual, Select1011.v())))
5410 {
5411 AA0 = A1; AA1 = A0; AA2 = A2;
5413 bPositiveA = false;
5414 }
5415 else if (internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreaterEqual, ADistIsLess, Select1101.v())) ||
5416 internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreater, ADistIsLessEqual, Select1101.v())))
5417 {
5418 AA0 = A2; AA1 = A0; AA2 = A1;
5420 bPositiveA = true;
5421 }
5422 else if (internal::XMVector3AllTrue(XMVectorSelect(ADistIsLessEqual, ADistIsGreater, Select1101.v())) ||
5423 internal::XMVector3AllTrue(XMVectorSelect(ADistIsLess, ADistIsGreaterEqual, Select1101.v())))
5424 {
5425 AA0 = A2; AA1 = A1; AA2 = A0;
5427 bPositiveA = false;
5428 }
5429 else
5430 {
5431 debug_assert!(false);
5432 return false;
5433 }
5434
5435 let BDistIsLessEqual: XMVECTOR = XMVectorOrInt(BDistIsLess, BDistIsZero);
5436 let BDistIsGreaterEqual: XMVECTOR = XMVectorOrInt(BDistIsGreater, BDistIsZero);
5437
5438 let BB0: XMVECTOR;
5439 let BB1: XMVECTOR;
5440 let BB2: XMVECTOR;
5441 let bPositiveB: bool;
5442
5443 if (internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreaterEqual, BDistIsLess, Select0111.v())) ||
5444 internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreater, BDistIsLessEqual, Select0111.v())))
5445 {
5446 BB0 = B0; BB1 = B1; BB2 = B2;
5448 bPositiveB = true;
5449 }
5450 else if (internal::XMVector3AllTrue(XMVectorSelect(BDistIsLessEqual, BDistIsGreater, Select0111.v())) ||
5451 internal::XMVector3AllTrue(XMVectorSelect(BDistIsLess, BDistIsGreaterEqual, Select0111.v())))
5452 {
5453 BB0 = B0; BB1 = B2; BB2 = B1;
5455 bPositiveB = false;
5456 }
5457 else if (internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreaterEqual, BDistIsLess, Select1011.v())) ||
5458 internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreater, BDistIsLessEqual, Select1011.v())))
5459 {
5460 BB0 = B1; BB1 = B2; BB2 = B0;
5462 bPositiveB = true;
5463 }
5464 else if (internal::XMVector3AllTrue(XMVectorSelect(BDistIsLessEqual, BDistIsGreater, Select1011.v())) ||
5465 internal::XMVector3AllTrue(XMVectorSelect(BDistIsLess, BDistIsGreaterEqual, Select1011.v())))
5466 {
5467 BB0 = B1; BB1 = B0; BB2 = B2;
5469 bPositiveB = false;
5470 }
5471 else if (internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreaterEqual, BDistIsLess, Select1101.v())) ||
5472 internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreater, BDistIsLessEqual, Select1101.v())))
5473 {
5474 BB0 = B2; BB1 = B0; BB2 = B1;
5476 bPositiveB = true;
5477 }
5478 else if (internal::XMVector3AllTrue(XMVectorSelect(BDistIsLessEqual, BDistIsGreater, Select1101.v())) ||
5479 internal::XMVector3AllTrue(XMVectorSelect(BDistIsLess, BDistIsGreaterEqual, Select1101.v())))
5480 {
5481 BB0 = B2; BB1 = B1; BB2 = B0;
5483 bPositiveB = false;
5484 }
5485 else
5486 {
5487 debug_assert!(false);
5488 return false;
5489 }
5490
5491 let Delta0: XMVECTOR;
5492 let Delta1: XMVECTOR;
5493
5494 if (bPositiveA ^ bPositiveB)
5497 {
5498 Delta0 = XMVectorSubtract(BB0, AA0);
5499 Delta1 = XMVectorSubtract(AA0, BB0);
5500 }
5501 else
5502 {
5503 Delta0 = XMVectorSubtract(AA0, BB0);
5504 Delta1 = XMVectorSubtract(BB0, AA0);
5505 }
5506
5507 let Dist0: XMVECTOR = XMVector3Dot(Delta0, XMVector3Cross(XMVectorSubtract(BB2, BB0), XMVectorSubtract(AA2, AA0)));
5510 if (XMVector4Greater(Dist0, Zero)) {
5511 return false;
5512 }
5513
5514 let Dist1: XMVECTOR = XMVector3Dot(Delta1, XMVector3Cross(XMVectorSubtract(BB1, BB0), XMVectorSubtract(AA1, AA0)));
5515 if (XMVector4Greater(Dist1, Zero)) {
5516 return false;
5517 }
5518
5519 return true;
5520 }
5521
5522 #[inline]
5542 pub fn IntersectsPlane(
5543 V0: FXMVECTOR,
5544 V1: FXMVECTOR,
5545 V2: FXMVECTOR,
5546 Plane: GXMVECTOR,
5547 ) -> PlaneIntersectionType {
5548 let One: XMVECTOR = XMVectorSplatOne();
5549
5550 debug_assert!(internal::XMPlaneIsUnit(Plane));
5551
5552 let TV0: XMVECTOR = XMVectorInsert(V0, One, 0, 0, 0, 0, 1);
5555 let TV1: XMVECTOR = XMVectorInsert(V1, One, 0, 0, 0, 0, 1);
5556 let TV2: XMVECTOR = XMVectorInsert(V2, One, 0, 0, 0, 0, 1);
5557
5558 let mut Outside: XMVECTOR = unsafe { undefined() };
5559 let mut Inside: XMVECTOR = unsafe { undefined() };
5560
5561 internal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane, &mut Outside, &mut Inside);
5562
5563 if (XMVector4EqualInt(Outside, XMVectorTrueInt())) {
5565 return FRONT;
5566 }
5567
5568 if (XMVector4EqualInt(Inside, XMVectorTrueInt())) {
5570 return BACK;
5571 }
5572
5573 return INTERSECTING;
5575 }
5576
5577 #[inline]
5611 pub fn ContainedBy(
5612 V0: FXMVECTOR,
5613 V1: FXMVECTOR,
5614 V2: FXMVECTOR,
5615 Plane0: GXMVECTOR,
5616 Plane1: HXMVECTOR,
5617 Plane2: HXMVECTOR,
5618 Plane3: CXMVECTOR,
5619 Plane4: CXMVECTOR,
5620 Plane5: CXMVECTOR,
5621 ) -> ContainmentType {
5622 let One: XMVECTOR = XMVectorSplatOne();
5623
5624 let TV0: XMVECTOR = XMVectorInsert(V0, One, 0, 0, 0, 0, 1);
5627 let TV1: XMVECTOR = XMVectorInsert(V1, One, 0, 0, 0, 0, 1);
5628 let TV2: XMVECTOR = XMVectorInsert(V2, One, 0, 0, 0, 0, 1);
5629
5630 let mut Outside: XMVECTOR = unsafe { undefined() };
5631 let mut Inside: XMVECTOR = unsafe { undefined() };
5632
5633 internal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane0, &mut Outside, &mut Inside);
5635
5636 let mut AnyOutside: XMVECTOR = Outside;
5637 let mut AllInside: XMVECTOR = Inside;
5638
5639 internal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane1, &mut Outside, &mut Inside);
5640 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
5641 AllInside = XMVectorAndInt(AllInside, Inside);
5642
5643 internal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane2, &mut Outside, &mut Inside);
5644 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
5645 AllInside = XMVectorAndInt(AllInside, Inside);
5646
5647 internal::FastIntersectTrianglePlane(TV0, TV1, TV2, *Plane3, &mut Outside, &mut Inside);
5648 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
5649 AllInside = XMVectorAndInt(AllInside, Inside);
5650
5651 internal::FastIntersectTrianglePlane(TV0, TV1, TV2, *Plane4, &mut Outside, &mut Inside);
5652 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
5653 AllInside = XMVectorAndInt(AllInside, Inside);
5654
5655 internal::FastIntersectTrianglePlane(TV0, TV1, TV2, *Plane5, &mut Outside, &mut Inside);
5656 AnyOutside = XMVectorOrInt(AnyOutside, Outside);
5657 AllInside = XMVectorAndInt(AllInside, Inside);
5658
5659 if (XMVector4EqualInt(AnyOutside, XMVectorTrueInt())) {
5661 return DISJOINT;
5662 }
5663
5664 if (XMVector4EqualInt(AllInside, XMVectorTrueInt())) {
5666 return CONTAINS;
5667 }
5668
5669 return INTERSECTS;
5671 }
5672}