PxQuat.h
Go to the documentation of this file.
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 
15 #ifndef PX_FOUNDATION_PX_QUAT_H
16 #define PX_FOUNDATION_PX_QUAT_H
17 
22 #include "foundation/PxVec3.h"
23 #ifndef PX_DOXYGEN
24 namespace physx
25 {
26 #endif
27 
34 class PxQuat
35 {
36 public:
41 
42 
45  : x(0.0f), y(0.0f), z(0.0f), w(1.0f)
46  {
47  PX_UNUSED(r);
48  }
49 
54  : x(0.0f), y(0.0f), z(0.0f), w(r)
55  {
56  }
57 
61  PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat(PxReal nx, PxReal ny, PxReal nz, PxReal nw) : x(nx),y(ny),z(nz),w(nw) {}
62 
72  PX_CUDA_CALLABLE PX_INLINE PxQuat(PxReal angleRadians, const PxVec3& unitAxis)
73  {
74  PX_ASSERT(PxAbs(1.0f-unitAxis.magnitude())<1e-3f);
75  const PxReal a = angleRadians * 0.5f;
76  const PxReal s = PxSin(a);
77  w = PxCos(a);
78  x = unitAxis.x * s;
79  y = unitAxis.y * s;
80  z = unitAxis.z * s;
81  }
82 
86  PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat(const PxQuat& v): x(v.x), y(v.y), z(v.z), w(v.w) {}
87 
93  PX_CUDA_CALLABLE PX_INLINE explicit PxQuat(const PxMat33& m); /* defined in PxMat33.h */
94 
98  PX_CUDA_CALLABLE bool isFinite() const
99  {
100  return PxIsFinite(x)
101  && PxIsFinite(y)
102  && PxIsFinite(z)
103  && PxIsFinite(w);
104  }
105 
106 
111  PX_CUDA_CALLABLE bool isUnit() const
112  {
113  const PxReal unitTolerance = 1e-4f;
114  return isFinite() && PxAbs(magnitude()-1)<unitTolerance;
115  }
116 
117 
122  PX_CUDA_CALLABLE bool isSane() const
123  {
124  const PxReal unitTolerance = 1e-2f;
125  return isFinite() && PxAbs(magnitude()-1)<unitTolerance;
126  }
127 
131  PX_CUDA_CALLABLE PX_INLINE bool operator==(const PxQuat&q) const { return x == q.x && y == q.y && z == q.z && w == q.w; }
132 
133 
138  PX_CUDA_CALLABLE PX_INLINE void toRadiansAndUnitAxis(PxReal& angle, PxVec3& axis) const
139  {
140  const PxReal quatEpsilon = 1.0e-8f;
141  const PxReal s2 = x*x+y*y+z*z;
142  if(s2<quatEpsilon*quatEpsilon) // can't extract a sensible axis
143  {
144  angle = 0.0f;
145  axis = PxVec3(1.0f,0.0f,0.0f);
146  }
147  else
148  {
149  const PxReal s = PxRecipSqrt(s2);
150  axis = PxVec3(x,y,z) * s;
151  angle = PxAbs(w)<quatEpsilon ? PxPi : PxAtan2(s2*s, w) * 2.0f;
152  }
153 
154  }
155 
162  {
163  return PxAcos(w) * 2.0f;
164  }
165 
166 
172  PX_CUDA_CALLABLE PX_INLINE PxReal getAngle(const PxQuat& q) const
173  {
174  return PxAcos(dot(q)) * 2.0f;
175  }
176 
177 
181  PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal magnitudeSquared() const
182  {
183  return x*x + y*y + z*z + w*w;
184  }
185 
190  {
191  return x * v.x + y * v.y + z * v.z + w * v.w;
192  }
193 
194  PX_CUDA_CALLABLE PX_INLINE PxQuat getNormalized() const
195  {
196  const PxReal s = 1.0f/magnitude();
197  return PxQuat(x*s, y*s, z*s, w*s);
198  }
199 
200 
201  PX_CUDA_CALLABLE PX_INLINE float magnitude() const
202  {
203  return PxSqrt(magnitudeSquared());
204  }
205 
206  //modifiers:
210  PX_CUDA_CALLABLE PX_INLINE PxReal normalize() // convert this PxQuat to a unit quaternion
211  {
212  const PxReal mag = magnitude();
213  if (mag)
214  {
215  const PxReal imag = 1.0f / mag;
216 
217  x *= imag;
218  y *= imag;
219  z *= imag;
220  w *= imag;
221  }
222  return mag;
223  }
224 
225  /*
226  \brief returns the conjugate.
227 
228  \note for unit quaternions, this is the inverse.
229  */
230  PX_CUDA_CALLABLE PX_INLINE PxQuat getConjugate() const
231  {
232  return PxQuat(-x,-y,-z,w);
233  }
234 
235  /*
236  \brief returns imaginary part.
237  */
238  PX_CUDA_CALLABLE PX_INLINE PxVec3 getImaginaryPart() const
239  {
240  return PxVec3(x,y,z);
241  }
242 
244  PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 getBasisVector0() const
245  {
246  const PxF32 x2 = x*2.0f;
247  const PxF32 w2 = w*2.0f;
248  return PxVec3( (w * w2) - 1.0f + x*x2,
249  (z * w2) + y*x2,
250  (-y * w2) + z*x2);
251  }
252 
254  PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 getBasisVector1() const
255  {
256  const PxF32 y2 = y*2.0f;
257  const PxF32 w2 = w*2.0f;
258  return PxVec3( (-z * w2) + x*y2,
259  (w * w2) - 1.0f + y*y2,
260  (x * w2) + z*y2);
261  }
262 
263 
265  PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 getBasisVector2() const
266  {
267  const PxF32 z2 = z*2.0f;
268  const PxF32 w2 = w*2.0f;
269  return PxVec3( (y * w2) + x*z2,
270  (-x * w2) + y*z2,
271  (w * w2) - 1.0f + z*z2);
272  }
273 
277  PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3 rotate(const PxVec3& v) const
278  {
279  const PxF32 vx = 2.0f*v.x;
280  const PxF32 vy = 2.0f*v.y;
281  const PxF32 vz = 2.0f*v.z;
282  const PxF32 w2 = w*w-0.5f;
283  const PxF32 dot2 = (x*vx + y*vy +z*vz);
284  return PxVec3
285  (
286  (vx*w2 + (y * vz - z * vy)*w + x*dot2),
287  (vy*w2 + (z * vx - x * vz)*w + y*dot2),
288  (vz*w2 + (x * vy - y * vx)*w + z*dot2)
289  );
290  }
291 
295  PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3 rotateInv(const PxVec3& v) const
296  {
297  const PxF32 vx = 2.0f*v.x;
298  const PxF32 vy = 2.0f*v.y;
299  const PxF32 vz = 2.0f*v.z;
300  const PxF32 w2 = w*w-0.5f;
301  const PxF32 dot2 = (x*vx + y*vy +z*vz);
302  return PxVec3
303  (
304  (vx*w2 - (y * vz - z * vy)*w + x*dot2),
305  (vy*w2 - (z * vx - x * vz)*w + y*dot2),
306  (vz*w2 - (x * vy - y * vx)*w + z*dot2)
307  );
308  }
309 
313  PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat& operator=(const PxQuat& p) { x = p.x; y = p.y; z = p.z; w = p.w; return *this; }
314 
316  {
317  const PxReal tx = w*q.x + q.w*x + y*q.z - q.y*z;
318  const PxReal ty = w*q.y + q.w*y + z*q.x - q.z*x;
319  const PxReal tz = w*q.z + q.w*z + x*q.y - q.x*y;
320 
321  w = w*q.w - q.x*x - y*q.y - q.z*z;
322  x = tx;
323  y = ty;
324  z = tz;
325 
326  return *this;
327  }
328 
330  {
331  x+=q.x;
332  y+=q.y;
333  z+=q.z;
334  w+=q.w;
335  return *this;
336  }
337 
339  {
340  x-=q.x;
341  y-=q.y;
342  z-=q.z;
343  w-=q.w;
344  return *this;
345  }
346 
348  {
349  x*=s;
350  y*=s;
351  z*=s;
352  w*=s;
353  return *this;
354  }
355 
358  {
359  return PxQuat(w*q.x + q.w*x + y*q.z - q.y*z,
360  w*q.y + q.w*y + z*q.x - q.z*x,
361  w*q.z + q.w*z + x*q.y - q.x*y,
362  w*q.w - x*q.x - y*q.y - z*q.z);
363  }
364 
367  {
368  return PxQuat(x+q.x,y+q.y,z+q.z,w+q.w);
369  }
370 
373  {
374  return PxQuat(-x,-y,-z,-w);
375  }
376 
377 
378  PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat operator-(const PxQuat& q) const
379  {
380  return PxQuat(x-q.x,y-q.y,z-q.z,w-q.w);
381  }
382 
383 
385  {
386  return PxQuat(x*r,y*r,z*r,w*r);
387  }
388 
389 
392 
394  PxReal x,y,z,w;
395 };
396 
397 #ifndef PX_DOXYGEN
398 } // namespace physx
399 #endif
400 
402 #endif // PX_FOUNDATION_PX_QUAT_H


Copyright © 2008-2015 NVIDIA Corporation, 2701 San Tomas Expressway, Santa Clara, CA 95050 U.S.A. All rights reserved. www.nvidia.com