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
24namespace physx
25{
26#endif
27
28/*!
29\brief class representing a rigid euclidean transform as a quaternion and a vector
30*/
31
32class PxTransform
33{
34public:
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