1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "Prerequisites/BsPrerequisitesUtil.h"
6#include "Math/BsVector4.h"
7#include "Math/BsAABox.h"
8#include "Math/BsSphere.h"
9#include "Math/BsRect2.h"
10
11#define SIMDPP_ARCH_X86_SSE4_1
12
13#if BS_COMPILER == BS_COMPILER_MSVC
14#pragma warning(disable: 4244)
15#endif
16
17#include "ThirdParty/simdpp/simd.h"
18
19#if BS_COMPILER == BS_COMPILER_MSVC
20#pragma warning(default: 4244)
21#endif
22
23namespace bs
24{
25 namespace simd
26 {
27 using namespace simdpp;
28
29 /** @addtogroup Math
30 * @{
31 */
32
33 /**
34 * Version of bs::AABox suitable for SIMD use. Takes up a bit more memory than standard AABox and is always 16-byte
35 * aligned.
36 */
37 struct AABox
38 {
39 /** Center of the bounds, W component unused. */
40 SIMDPP_ALIGN(16) Vector4 center;
41
42 /** Extents (half-size) of the bounds, W component unused. */
43 SIMDPP_ALIGN(16) Vector4 extents;
44
45 AABox() = default;
46
47 /** Initializes bounds from an AABox. */
48 AABox(const bs::AABox& box)
49 {
50 center = Vector4(box.getCenter());
51 extents = Vector4(box.getHalfSize());
52 }
53
54 /** Initializes bounds from a Sphere. */
55 AABox(const Sphere& sphere)
56 {
57 center = Vector4(sphere.getCenter());
58
59 float radius = sphere.getRadius();
60 extents = Vector4(radius, radius, radius, 0.0f);
61 }
62
63 /** Initializes bounds from a vector representing the center and equal extents in all directions. */
64 AABox(const Vector3& center, float extent)
65 {
66 this->center = Vector4(center);
67 extents = Vector4(extent, extent, extent, 0.0f);
68 }
69
70 /** Returns true if the current bounds object intersects the provided object. */
71 bool intersects(const AABox& other) const
72 {
73 auto myCenter = load<float32x4>(&center);
74 auto otherCenter = load<float32x4>(&other.center);
75
76 float32x4 diff = abs(sub(myCenter, otherCenter));
77
78 auto myExtents = simd::load<float32x4>(&extents);
79 auto otherExtents = simd::load<float32x4>(&other.extents);
80
81 float32x4 extents = add(myExtents, otherExtents);
82
83 return test_bits_any(bit_cast<uint32x4>(cmp_gt(diff, extents))) == false;
84 }
85 };
86
87 /**
88 * Version of bs::Rect2 suitable for SIMD use.
89 */
90 struct Rect2
91 {
92 /** Center of the bounds. Z and W component unused.*/
93 SIMDPP_ALIGN(16) Vector4 center;
94
95 /** Extents (half-size) of the bounds. Z and W component unused. */
96 SIMDPP_ALIGN(16) Vector4 extents;
97
98 Rect2() = default;
99
100 /** Initializes bounds from an Rect2. */
101 Rect2(const bs::Rect2& rect)
102 {
103 center = Vector4(rect.getCenter().x, rect.getCenter().y, 0.0f, 0.0f);
104 extents = Vector4(rect.getHalfSize().x, rect.getHalfSize().y, 0.0f, 0.0f);
105 }
106
107 /** Initializes bounds from a vector representing the center and equal extents in all directions. */
108 Rect2(const Vector2& center, float extent)
109 {
110 this->center = Vector4(center.x, center.y, 0.0f, 0.0f);
111 extents = Vector4(extent, extent, 0.0f, 0.0f);
112 }
113
114 /** Returns true if the current bounds object intersects the provided object. */
115 bool overlaps(const Rect2& other) const
116 {
117 auto myCenter = load<float32x4>(&center);
118 auto otherCenter = load<float32x4>(&other.center);
119
120 float32x4 diff = abs(sub(myCenter, otherCenter));
121
122 auto myExtents = simd::load<float32x4>(&extents);
123 auto otherExtents = simd::load<float32x4>(&other.extents);
124
125 float32x4 extents = add(myExtents, otherExtents);
126
127 return test_bits_any(bit_cast<uint32x4>(cmp_gt(diff, extents))) == false;
128 }
129 };
130
131 /** @} */
132 }
133}
134