1 | /* |
2 | * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. |
3 | * |
4 | * NVIDIA CORPORATION and its licensors retain all intellectual property |
5 | * and proprietary rights in and to this software, related documentation |
6 | * and any modifications thereto. Any use, reproduction, disclosure or |
7 | * distribution of this software and related documentation without an express |
8 | * license agreement from NVIDIA CORPORATION is strictly prohibited. |
9 | */ |
10 | // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. |
11 | // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. |
12 | |
13 | |
14 | #ifndef PX_FOUNDATION_PX_TRANSFORM_H |
15 | #define PX_FOUNDATION_PX_TRANSFORM_H |
16 | /** \addtogroup foundation |
17 | @{ |
18 | */ |
19 | |
20 | #include "foundation/PxQuat.h" |
21 | #include "foundation/PxPlane.h" |
22 | |
23 | #ifndef PX_DOXYGEN |
24 | namespace physx |
25 | { |
26 | #endif |
27 | |
28 | /*! |
29 | \brief class representing a rigid euclidean transform as a quaternion and a vector |
30 | */ |
31 | |
32 | class PxTransform |
33 | { |
34 | public: |
35 | PxQuat q; |
36 | PxVec3 p; |
37 | |
38 | //#define PXTRANSFORM_DEFAULT_CONSTRUCT_NAN |
39 | |
40 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform() |
41 | #ifdef PXTRANSFORM_DEFAULT_CONSTRUCT_IDENTITY |
42 | : q(0, 0, 0, 1), p(0, 0, 0) |
43 | #elif defined(PXTRANSFORM_DEFAULT_CONSTRUCT_NAN) |
44 | #define invalid PxSqrt(-1.0f) |
45 | : q(invalid, invalid, invalid, invalid), p(invalid, invalid, invalid) |
46 | #undef invalid |
47 | #endif |
48 | { |
49 | } |
50 | |
51 | PX_CUDA_CALLABLE PX_FORCE_INLINE explicit PxTransform(const PxVec3& position): q(PxIdentity), p(position) |
52 | { |
53 | } |
54 | |
55 | PX_CUDA_CALLABLE PX_FORCE_INLINE explicit PxTransform(PxIDENTITY r) |
56 | : q(PxIdentity), p(PxZero) |
57 | { |
58 | PX_UNUSED(r); |
59 | } |
60 | |
61 | PX_CUDA_CALLABLE PX_FORCE_INLINE explicit PxTransform(const PxQuat& orientation): q(orientation), p(0) |
62 | { |
63 | PX_ASSERT(orientation.isSane()); |
64 | } |
65 | |
66 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform(PxReal x, PxReal y, PxReal z, PxQuat aQ = PxQuat(PxIdentity)) |
67 | : q(aQ), p(x, y, z) |
68 | { |
69 | } |
70 | |
71 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform(const PxVec3& p0, const PxQuat& q0): q(q0), p(p0) |
72 | { |
73 | PX_ASSERT(q0.isSane()); |
74 | } |
75 | |
76 | PX_CUDA_CALLABLE PX_FORCE_INLINE explicit PxTransform(const PxMat44& m); // defined in PxMat44.h |
77 | |
78 | /** |
79 | \brief returns true if the two transforms are exactly equal |
80 | */ |
81 | PX_CUDA_CALLABLE PX_INLINE bool operator==(const PxTransform& t) const { return p == t.p && q == t.q; } |
82 | |
83 | |
84 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform operator*(const PxTransform& x) const |
85 | { |
86 | PX_ASSERT(x.isSane()); |
87 | return transform(x); |
88 | } |
89 | |
90 | //! Equals matrix multiplication |
91 | PX_CUDA_CALLABLE PX_INLINE PxTransform& operator*=(PxTransform &other) |
92 | { |
93 | *this = *this * other; |
94 | return *this; |
95 | } |
96 | |
97 | |
98 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform getInverse() const |
99 | { |
100 | PX_ASSERT(isFinite()); |
101 | return PxTransform(q.rotateInv(-p),q.getConjugate()); |
102 | } |
103 | |
104 | |
105 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 transform(const PxVec3& input) const |
106 | { |
107 | PX_ASSERT(isFinite()); |
108 | return q.rotate(input) + p; |
109 | } |
110 | |
111 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 transformInv(const PxVec3& input) const |
112 | { |
113 | PX_ASSERT(isFinite()); |
114 | return q.rotateInv(input-p); |
115 | } |
116 | |
117 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 rotate(const PxVec3& input) const |
118 | { |
119 | PX_ASSERT(isFinite()); |
120 | return q.rotate(input); |
121 | } |
122 | |
123 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 rotateInv(const PxVec3& input) const |
124 | { |
125 | PX_ASSERT(isFinite()); |
126 | return q.rotateInv(input); |
127 | } |
128 | |
129 | //! Transform transform to parent (returns compound transform: first src, then *this) |
130 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform transform(const PxTransform& src) const |
131 | { |
132 | PX_ASSERT(src.isSane()); |
133 | PX_ASSERT(isSane()); |
134 | // src = [srct, srcr] -> [r*srct + t, r*srcr] |
135 | return PxTransform(q.rotate(src.p) + p, q*src.q); |
136 | } |
137 | |
138 | /** |
139 | \brief returns true if finite and q is a unit quaternion |
140 | */ |
141 | |
142 | PX_CUDA_CALLABLE bool isValid() const |
143 | { |
144 | return p.isFinite() && q.isFinite() && q.isUnit(); |
145 | } |
146 | |
147 | /** |
148 | \brief returns true if finite and quat magnitude is reasonably close to unit to allow for some accumulation of error vs isValid |
149 | */ |
150 | |
151 | PX_CUDA_CALLABLE bool isSane() const |
152 | { |
153 | return isFinite() && q.isSane(); |
154 | } |
155 | |
156 | |
157 | /** |
158 | \brief returns true if all elems are finite (not NAN or INF, etc.) |
159 | */ |
160 | PX_CUDA_CALLABLE PX_FORCE_INLINE bool isFinite() const { return p.isFinite() && q.isFinite(); } |
161 | |
162 | //! Transform transform from parent (returns compound transform: first src, then this->inverse) |
163 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform transformInv(const PxTransform& src) const |
164 | { |
165 | PX_ASSERT(src.isSane()); |
166 | PX_ASSERT(isFinite()); |
167 | // src = [srct, srcr] -> [r^-1*(srct-t), r^-1*srcr] |
168 | PxQuat qinv = q.getConjugate(); |
169 | return PxTransform(qinv.rotate(src.p - p), qinv*src.q); |
170 | } |
171 | |
172 | |
173 | |
174 | /** |
175 | \deprecated |
176 | \brief deprecated - use PxTransform(PxIdentity) |
177 | */ |
178 | |
179 | PX_DEPRECATED static PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform createIdentity() |
180 | { |
181 | return PxTransform(PxIdentity); |
182 | } |
183 | |
184 | /** |
185 | \brief transform plane |
186 | */ |
187 | |
188 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxPlane transform(const PxPlane& plane) const |
189 | { |
190 | PxVec3 transformedNormal = rotate(plane.n); |
191 | return PxPlane(transformedNormal, plane.d - p.dot(transformedNormal)); |
192 | } |
193 | |
194 | /** |
195 | \brief inverse-transform plane |
196 | */ |
197 | |
198 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxPlane inverseTransform(const PxPlane& plane) const |
199 | { |
200 | PxVec3 transformedNormal = rotateInv(plane.n); |
201 | return PxPlane(transformedNormal, plane.d + p.dot(plane.n)); |
202 | } |
203 | |
204 | |
205 | /** |
206 | \brief return a normalized transform (i.e. one in which the quaternion has unit magnitude) |
207 | */ |
208 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform getNormalized() const |
209 | { |
210 | return PxTransform(p, q.getNormalized()); |
211 | } |
212 | |
213 | }; |
214 | |
215 | #ifndef PX_DOXYGEN |
216 | } // namespace physx |
217 | #endif |
218 | |
219 | /** @} */ |
220 | #endif // PX_FOUNDATION_PX_TRANSFORM_H |
221 | |