1 | // |
2 | // Redistribution and use in source and binary forms, with or without |
3 | // modification, are permitted provided that the following conditions |
4 | // are met: |
5 | // * Redistributions of source code must retain the above copyright |
6 | // notice, this list of conditions and the following disclaimer. |
7 | // * Redistributions in binary form must reproduce the above copyright |
8 | // notice, this list of conditions and the following disclaimer in the |
9 | // documentation and/or other materials provided with the distribution. |
10 | // * Neither the name of NVIDIA CORPORATION nor the names of its |
11 | // contributors may be used to endorse or promote products derived |
12 | // from this software without specific prior written permission. |
13 | // |
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY |
15 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
17 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
18 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
19 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
20 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
21 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
22 | // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
24 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | // |
26 | // Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved. |
27 | // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. |
28 | // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. |
29 | |
30 | #ifndef GU_BOX_H |
31 | #define GU_BOX_H |
32 | |
33 | /** \addtogroup geomutils |
34 | @{ |
35 | */ |
36 | |
37 | #include "foundation/PxTransform.h" |
38 | #include "foundation/PxMat33.h" |
39 | #include "common/PxPhysXCommonConfig.h" |
40 | #include "CmPhysXCommon.h" |
41 | #include "CmScaling.h" |
42 | |
43 | namespace physx |
44 | { |
45 | namespace Gu |
46 | { |
47 | class Capsule; |
48 | |
49 | PX_PHYSX_COMMON_API void computeOBBPoints(PxVec3* PX_RESTRICT pts, const PxVec3& center, const PxVec3& extents, const PxVec3& base0, const PxVec3& base1, const PxVec3& base2); |
50 | |
51 | |
52 | /** |
53 | \brief Represents an oriented bounding box. |
54 | |
55 | As a center point, extents(radii) and a rotation. i.e. the center of the box is at the center point, |
56 | the box is rotated around this point with the rotation and it is 2*extents in width, height and depth. |
57 | */ |
58 | |
59 | /** |
60 | Box geometry |
61 | |
62 | The rot member describes the world space orientation of the box. |
63 | The center member gives the world space position of the box. |
64 | The extents give the local space coordinates of the box corner in the positive octant. |
65 | Dimensions of the box are: 2*extent. |
66 | Transformation to world space is: worldPoint = rot * localPoint + center |
67 | Transformation to local space is: localPoint = T(rot) * (worldPoint - center) |
68 | Where T(M) denotes the transpose of M. |
69 | */ |
70 | #if PX_VC |
71 | #pragma warning(push) |
72 | #pragma warning( disable : 4251 ) // class needs to have dll-interface to be used by clients of class |
73 | #endif |
74 | class PX_PHYSX_COMMON_API Box |
75 | { |
76 | public: |
77 | /** |
78 | \brief Constructor |
79 | */ |
80 | PX_FORCE_INLINE Box() |
81 | { |
82 | } |
83 | |
84 | /** |
85 | \brief Constructor |
86 | |
87 | \param origin Center of the OBB |
88 | \param extent Extents/radii of the obb. |
89 | \param base rotation to apply to the obb. |
90 | */ |
91 | //! Construct from center, extent and rotation |
92 | PX_FORCE_INLINE Box(const PxVec3& origin, const PxVec3& extent, const PxMat33& base) : rot(base), center(origin), extents(extent) |
93 | {} |
94 | |
95 | //! Copy constructor |
96 | PX_FORCE_INLINE Box(const Box& other) : rot(other.rot), center(other.center), extents(other.extents) |
97 | {} |
98 | |
99 | /** |
100 | \brief Destructor |
101 | */ |
102 | PX_FORCE_INLINE ~Box() |
103 | { |
104 | } |
105 | |
106 | //! Assignment operator |
107 | PX_FORCE_INLINE const Box& operator=(const Box& other) |
108 | { |
109 | rot = other.rot; |
110 | center = other.center; |
111 | extents = other.extents; |
112 | return *this; |
113 | } |
114 | |
115 | /** |
116 | \brief Setups an empty box. |
117 | */ |
118 | PX_INLINE void setEmpty() |
119 | { |
120 | center = PxVec3(0); |
121 | extents = PxVec3(-PX_MAX_REAL, -PX_MAX_REAL, -PX_MAX_REAL); |
122 | rot = PxMat33(PxIdentity); |
123 | } |
124 | |
125 | /** |
126 | \brief Checks the box is valid. |
127 | |
128 | \return true if the box is valid |
129 | */ |
130 | PX_INLINE bool isValid() const |
131 | { |
132 | // Consistency condition for (Center, Extents) boxes: Extents >= 0.0f |
133 | if(extents.x < 0.0f) return false; |
134 | if(extents.y < 0.0f) return false; |
135 | if(extents.z < 0.0f) return false; |
136 | return true; |
137 | } |
138 | |
139 | ///////////// |
140 | PX_FORCE_INLINE void setAxes(const PxVec3& axis0, const PxVec3& axis1, const PxVec3& axis2) |
141 | { |
142 | rot.column0 = axis0; |
143 | rot.column1 = axis1; |
144 | rot.column2 = axis2; |
145 | } |
146 | |
147 | PX_FORCE_INLINE PxVec3 rotate(const PxVec3& src) const |
148 | { |
149 | return rot * src; |
150 | } |
151 | |
152 | PX_FORCE_INLINE PxVec3 rotateInv(const PxVec3& src) const |
153 | { |
154 | return rot.transformTranspose(other: src); |
155 | } |
156 | |
157 | PX_FORCE_INLINE PxVec3 transform(const PxVec3& src) const |
158 | { |
159 | return rot * src + center; |
160 | } |
161 | |
162 | PX_FORCE_INLINE PxTransform getTransform() const |
163 | { |
164 | return PxTransform(center, PxQuat(rot)); |
165 | } |
166 | |
167 | PX_INLINE PxVec3 computeAABBExtent() const |
168 | { |
169 | const PxReal a00 = PxAbs(a: rot[0][0]); |
170 | const PxReal a01 = PxAbs(a: rot[0][1]); |
171 | const PxReal a02 = PxAbs(a: rot[0][2]); |
172 | |
173 | const PxReal a10 = PxAbs(a: rot[1][0]); |
174 | const PxReal a11 = PxAbs(a: rot[1][1]); |
175 | const PxReal a12 = PxAbs(a: rot[1][2]); |
176 | |
177 | const PxReal a20 = PxAbs(a: rot[2][0]); |
178 | const PxReal a21 = PxAbs(a: rot[2][1]); |
179 | const PxReal a22 = PxAbs(a: rot[2][2]); |
180 | |
181 | const PxReal ex = extents.x; |
182 | const PxReal ey = extents.y; |
183 | const PxReal ez = extents.z; |
184 | |
185 | return PxVec3( a00 * ex + a10 * ey + a20 * ez, |
186 | a01 * ex + a11 * ey + a21 * ez, |
187 | a02 * ex + a12 * ey + a22 * ez); |
188 | } |
189 | |
190 | /** |
191 | Computes the obb points. |
192 | \param pts [out] 8 box points |
193 | */ |
194 | PX_FORCE_INLINE void computeBoxPoints(PxVec3* PX_RESTRICT pts) const |
195 | { |
196 | Gu::computeOBBPoints(pts, center, extents, base0: rot.column0, base1: rot.column1, base2: rot.column2); |
197 | } |
198 | |
199 | void create(const Gu::Capsule& capsule); |
200 | |
201 | PxMat33 rot; |
202 | PxVec3 center; |
203 | PxVec3 extents; |
204 | }; |
205 | PX_COMPILE_TIME_ASSERT(sizeof(Gu::Box) == 60); |
206 | |
207 | //! A padded version of Gu::Box, to safely load its data using SIMD |
208 | class BoxPadded : public Box |
209 | { |
210 | public: |
211 | PX_FORCE_INLINE BoxPadded() {} |
212 | PX_FORCE_INLINE ~BoxPadded() {} |
213 | PxU32 padding; |
214 | }; |
215 | PX_COMPILE_TIME_ASSERT(sizeof(Gu::BoxPadded) == 64); |
216 | |
217 | //! Transforms a shape space AABB to a vertex space AABB (conservative). |
218 | PX_FORCE_INLINE void computeVertexSpaceAABB(Gu::Box& vertexSpaceOBB, const PxBounds3& worldBounds, const PxTransform& world2Shape, const Cm::FastVertex2ShapeScaling& scaling, bool idtScaleMesh) |
219 | { |
220 | PX_ASSERT(!worldBounds.isEmpty()); |
221 | const PxBounds3 boundsInMesh = PxBounds3::transformFast(transform: world2Shape, bounds: worldBounds); // transform bounds from world to shape (excluding mesh scale) |
222 | |
223 | vertexSpaceOBB.rot = PxMat33(PxIdentity); |
224 | if(idtScaleMesh) |
225 | { |
226 | vertexSpaceOBB.center = boundsInMesh.getCenter(); |
227 | vertexSpaceOBB.extents = boundsInMesh.getExtents(); |
228 | } |
229 | else |
230 | { |
231 | const PxBounds3 bounds = PxBounds3::basisExtent(center: scaling.getShape2VertexSkew() * boundsInMesh.getCenter(), basis: scaling.getShape2VertexSkew(), extent: boundsInMesh.getExtents()); |
232 | vertexSpaceOBB.center = bounds.getCenter(); |
233 | vertexSpaceOBB.extents = bounds.getExtents(); |
234 | } |
235 | } |
236 | |
237 | #if PX_VC |
238 | #pragma warning(pop) |
239 | #endif |
240 | |
241 | } |
242 | |
243 | } |
244 | |
245 | /** @} */ |
246 | #endif |
247 | |