ovr_sdk

annotate LibOVR/Src/Kernel/OVR_Math.h @ 0:1b39a1b46319

initial 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 14 Jan 2015 06:51:16 +0200
parents
children
rev   line source
nuclear@0 1 /************************************************************************************
nuclear@0 2
nuclear@0 3 PublicHeader: OVR_Kernel.h
nuclear@0 4 Filename : OVR_Math.h
nuclear@0 5 Content : Implementation of 3D primitives such as vectors, matrices.
nuclear@0 6 Created : September 4, 2012
nuclear@0 7 Authors : Andrew Reisse, Michael Antonov, Steve LaValle,
nuclear@0 8 Anna Yershova, Max Katsev, Dov Katz
nuclear@0 9
nuclear@0 10 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
nuclear@0 11
nuclear@0 12 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
nuclear@0 13 you may not use the Oculus VR Rift SDK except in compliance with the License,
nuclear@0 14 which is provided at the time of installation or download, or which
nuclear@0 15 otherwise accompanies this software in either electronic or hard copy form.
nuclear@0 16
nuclear@0 17 You may obtain a copy of the License at
nuclear@0 18
nuclear@0 19 http://www.oculusvr.com/licenses/LICENSE-3.2
nuclear@0 20
nuclear@0 21 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
nuclear@0 22 distributed under the License is distributed on an "AS IS" BASIS,
nuclear@0 23 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
nuclear@0 24 See the License for the specific language governing permissions and
nuclear@0 25 limitations under the License.
nuclear@0 26
nuclear@0 27 *************************************************************************************/
nuclear@0 28
nuclear@0 29 #ifndef OVR_Math_h
nuclear@0 30 #define OVR_Math_h
nuclear@0 31
nuclear@0 32 #include <assert.h>
nuclear@0 33 #include <stdlib.h>
nuclear@0 34 #include <math.h>
nuclear@0 35
nuclear@0 36 #include "OVR_Types.h"
nuclear@0 37 #include "OVR_RefCount.h"
nuclear@0 38 #include "OVR_Std.h"
nuclear@0 39 #include "OVR_Alg.h"
nuclear@0 40
nuclear@0 41
nuclear@0 42 namespace OVR {
nuclear@0 43
nuclear@0 44 //-------------------------------------------------------------------------------------
nuclear@0 45 // ***** Constants for 3D world/axis definitions.
nuclear@0 46
nuclear@0 47 // Definitions of axes for coordinate and rotation conversions.
nuclear@0 48 enum Axis
nuclear@0 49 {
nuclear@0 50 Axis_X = 0, Axis_Y = 1, Axis_Z = 2
nuclear@0 51 };
nuclear@0 52
nuclear@0 53 // RotateDirection describes the rotation direction around an axis, interpreted as follows:
nuclear@0 54 // CW - Clockwise while looking "down" from positive axis towards the origin.
nuclear@0 55 // CCW - Counter-clockwise while looking from the positive axis towards the origin,
nuclear@0 56 // which is in the negative axis direction.
nuclear@0 57 // CCW is the default for the RHS coordinate system. Oculus standard RHS coordinate
nuclear@0 58 // system defines Y up, X right, and Z back (pointing out from the screen). In this
nuclear@0 59 // system Rotate_CCW around Z will specifies counter-clockwise rotation in XY plane.
nuclear@0 60 enum RotateDirection
nuclear@0 61 {
nuclear@0 62 Rotate_CCW = 1,
nuclear@0 63 Rotate_CW = -1
nuclear@0 64 };
nuclear@0 65
nuclear@0 66 // Constants for right handed and left handed coordinate systems
nuclear@0 67 enum HandedSystem
nuclear@0 68 {
nuclear@0 69 Handed_R = 1, Handed_L = -1
nuclear@0 70 };
nuclear@0 71
nuclear@0 72 // AxisDirection describes which way the coordinate axis points. Used by WorldAxes.
nuclear@0 73 enum AxisDirection
nuclear@0 74 {
nuclear@0 75 Axis_Up = 2,
nuclear@0 76 Axis_Down = -2,
nuclear@0 77 Axis_Right = 1,
nuclear@0 78 Axis_Left = -1,
nuclear@0 79 Axis_In = 3,
nuclear@0 80 Axis_Out = -3
nuclear@0 81 };
nuclear@0 82
nuclear@0 83 struct WorldAxes
nuclear@0 84 {
nuclear@0 85 AxisDirection XAxis, YAxis, ZAxis;
nuclear@0 86
nuclear@0 87 WorldAxes(AxisDirection x, AxisDirection y, AxisDirection z)
nuclear@0 88 : XAxis(x), YAxis(y), ZAxis(z)
nuclear@0 89 { OVR_ASSERT(abs(x) != abs(y) && abs(y) != abs(z) && abs(z) != abs(x));}
nuclear@0 90 };
nuclear@0 91
nuclear@0 92 } // namespace OVR
nuclear@0 93
nuclear@0 94
nuclear@0 95 //------------------------------------------------------------------------------------//
nuclear@0 96 // ***** C Compatibility Types
nuclear@0 97
nuclear@0 98 // These declarations are used to support conversion between C types used in
nuclear@0 99 // LibOVR C interfaces and their C++ versions. As an example, they allow passing
nuclear@0 100 // Vector3f into a function that expects ovrVector3f.
nuclear@0 101
nuclear@0 102 typedef struct ovrQuatf_ ovrQuatf;
nuclear@0 103 typedef struct ovrQuatd_ ovrQuatd;
nuclear@0 104 typedef struct ovrSizei_ ovrSizei;
nuclear@0 105 typedef struct ovrSizef_ ovrSizef;
nuclear@0 106 typedef struct ovrRecti_ ovrRecti;
nuclear@0 107 typedef struct ovrVector2i_ ovrVector2i;
nuclear@0 108 typedef struct ovrVector2f_ ovrVector2f;
nuclear@0 109 typedef struct ovrVector3f_ ovrVector3f;
nuclear@0 110 typedef struct ovrVector3d_ ovrVector3d;
nuclear@0 111 typedef struct ovrMatrix3d_ ovrMatrix3d;
nuclear@0 112 typedef struct ovrMatrix4f_ ovrMatrix4f;
nuclear@0 113 typedef struct ovrPosef_ ovrPosef;
nuclear@0 114 typedef struct ovrPosed_ ovrPosed;
nuclear@0 115 typedef struct ovrPoseStatef_ ovrPoseStatef;
nuclear@0 116 typedef struct ovrPoseStated_ ovrPoseStated;
nuclear@0 117
nuclear@0 118 namespace OVR {
nuclear@0 119
nuclear@0 120 // Forward-declare our templates.
nuclear@0 121 template<class T> class Quat;
nuclear@0 122 template<class T> class Size;
nuclear@0 123 template<class T> class Rect;
nuclear@0 124 template<class T> class Vector2;
nuclear@0 125 template<class T> class Vector3;
nuclear@0 126 template<class T> class Matrix3;
nuclear@0 127 template<class T> class Matrix4;
nuclear@0 128 template<class T> class Pose;
nuclear@0 129 template<class T> class PoseState;
nuclear@0 130
nuclear@0 131 // CompatibleTypes::Type is used to lookup a compatible C-version of a C++ class.
nuclear@0 132 template<class C>
nuclear@0 133 struct CompatibleTypes
nuclear@0 134 {
nuclear@0 135 // Declaration here seems necessary for MSVC; specializations are
nuclear@0 136 // used instead.
nuclear@0 137 typedef struct {} Type;
nuclear@0 138 };
nuclear@0 139
nuclear@0 140 // Specializations providing CompatibleTypes::Type value.
nuclear@0 141 template<> struct CompatibleTypes<Quat<float> > { typedef ovrQuatf Type; };
nuclear@0 142 template<> struct CompatibleTypes<Quat<double> > { typedef ovrQuatd Type; };
nuclear@0 143 template<> struct CompatibleTypes<Matrix3<double> > { typedef ovrMatrix3d Type; };
nuclear@0 144 template<> struct CompatibleTypes<Matrix4<float> > { typedef ovrMatrix4f Type; };
nuclear@0 145 template<> struct CompatibleTypes<Size<int> > { typedef ovrSizei Type; };
nuclear@0 146 template<> struct CompatibleTypes<Size<float> > { typedef ovrSizef Type; };
nuclear@0 147 template<> struct CompatibleTypes<Rect<int> > { typedef ovrRecti Type; };
nuclear@0 148 template<> struct CompatibleTypes<Vector2<int> > { typedef ovrVector2i Type; };
nuclear@0 149 template<> struct CompatibleTypes<Vector2<float> > { typedef ovrVector2f Type; };
nuclear@0 150 template<> struct CompatibleTypes<Vector3<float> > { typedef ovrVector3f Type; };
nuclear@0 151 template<> struct CompatibleTypes<Vector3<double> > { typedef ovrVector3d Type; };
nuclear@0 152
nuclear@0 153 template<> struct CompatibleTypes<Pose<float> > { typedef ovrPosef Type; };
nuclear@0 154 template<> struct CompatibleTypes<Pose<double> > { typedef ovrPosed Type; };
nuclear@0 155
nuclear@0 156 //------------------------------------------------------------------------------------//
nuclear@0 157 // ***** Math
nuclear@0 158 //
nuclear@0 159 // Math class contains constants and functions. This class is a template specialized
nuclear@0 160 // per type, with Math<float> and Math<double> being distinct.
nuclear@0 161 template<class Type>
nuclear@0 162 class Math
nuclear@0 163 {
nuclear@0 164 public:
nuclear@0 165 // By default, support explicit conversion to float. This allows Vector2<int> to
nuclear@0 166 // compile, for example.
nuclear@0 167 typedef float OtherFloatType;
nuclear@0 168 };
nuclear@0 169
nuclear@0 170
nuclear@0 171 #define MATH_FLOAT_PI (3.1415926f)
nuclear@0 172 #define MATH_FLOAT_TWOPI (2.0f *MATH_FLOAT_PI)
nuclear@0 173 #define MATH_FLOAT_PIOVER2 (0.5f *MATH_FLOAT_PI)
nuclear@0 174 #define MATH_FLOAT_PIOVER4 (0.25f*MATH_FLOAT_PI)
nuclear@0 175 #define MATH_FLOAT_E (2.7182818f)
nuclear@0 176 #define MATH_FLOAT_MAXVALUE (FLT_MAX)
nuclear@0 177 #define MATH_FLOAT MINPOSITIVEVALUE (FLT_MIN)
nuclear@0 178 #define MATH_FLOAT_RADTODEGREEFACTOR (360.0f / MATH_FLOAT_TWOPI)
nuclear@0 179 #define MATH_FLOAT_DEGREETORADFACTOR (MATH_FLOAT_TWOPI / 360.0f)
nuclear@0 180 #define MATH_FLOAT_TOLERANCE (0.00001f)
nuclear@0 181 #define MATH_FLOAT_SINGULARITYRADIUS (0.0000001f) // Use for Gimbal lock numerical problems
nuclear@0 182
nuclear@0 183 #define MATH_DOUBLE_PI (3.14159265358979)
nuclear@0 184 #define MATH_DOUBLE_TWOPI (2.0f *MATH_DOUBLE_PI)
nuclear@0 185 #define MATH_DOUBLE_PIOVER2 (0.5f *MATH_DOUBLE_PI)
nuclear@0 186 #define MATH_DOUBLE_PIOVER4 (0.25f*MATH_DOUBLE_PI)
nuclear@0 187 #define MATH_DOUBLE_E (2.71828182845905)
nuclear@0 188 #define MATH_DOUBLE_MAXVALUE (DBL_MAX)
nuclear@0 189 #define MATH_DOUBLE MINPOSITIVEVALUE (DBL_MIN)
nuclear@0 190 #define MATH_DOUBLE_RADTODEGREEFACTOR (360.0f / MATH_DOUBLE_TWOPI)
nuclear@0 191 #define MATH_DOUBLE_DEGREETORADFACTOR (MATH_DOUBLE_TWOPI / 360.0f)
nuclear@0 192 #define MATH_DOUBLE_TOLERANCE (0.00001)
nuclear@0 193 #define MATH_DOUBLE_SINGULARITYRADIUS (0.000000000001) // Use for Gimbal lock numerical problems
nuclear@0 194
nuclear@0 195
nuclear@0 196
nuclear@0 197
nuclear@0 198 // Single-precision Math constants class.
nuclear@0 199 template<>
nuclear@0 200 class Math<float>
nuclear@0 201 {
nuclear@0 202 public:
nuclear@0 203 typedef double OtherFloatType;
nuclear@0 204 };
nuclear@0 205
nuclear@0 206 // Double-precision Math constants class.
nuclear@0 207 template<>
nuclear@0 208 class Math<double>
nuclear@0 209 {
nuclear@0 210 public:
nuclear@0 211 typedef float OtherFloatType;
nuclear@0 212 };
nuclear@0 213
nuclear@0 214
nuclear@0 215 typedef Math<float> Mathf;
nuclear@0 216 typedef Math<double> Mathd;
nuclear@0 217
nuclear@0 218 // Conversion functions between degrees and radians
nuclear@0 219 template<class T>
nuclear@0 220 T RadToDegree(T rads) { return rads * ((T)MATH_DOUBLE_RADTODEGREEFACTOR); }
nuclear@0 221 template<class T>
nuclear@0 222 T DegreeToRad(T rads) { return rads * ((T)MATH_DOUBLE_DEGREETORADFACTOR); }
nuclear@0 223
nuclear@0 224 // Numerically stable acos function
nuclear@0 225 template<class T>
nuclear@0 226 T Acos(T val) {
nuclear@0 227 if (val > T(1)) return T(0);
nuclear@0 228 else if (val < T(-1)) return ((T)MATH_DOUBLE_PI);
nuclear@0 229 else return acos(val);
nuclear@0 230 };
nuclear@0 231
nuclear@0 232 // Numerically stable asin function
nuclear@0 233 template<class T>
nuclear@0 234 T Asin(T val) {
nuclear@0 235 if (val > T(1)) return ((T)MATH_DOUBLE_PIOVER2);
nuclear@0 236 else if (val < T(-1)) return ((T)MATH_DOUBLE_PIOVER2) * T(3);
nuclear@0 237 else return asin(val);
nuclear@0 238 };
nuclear@0 239
nuclear@0 240 #ifdef OVR_CC_MSVC
nuclear@0 241 inline int isnan(double x) { return _isnan(x); };
nuclear@0 242 #endif
nuclear@0 243
nuclear@0 244 template<class T>
nuclear@0 245 class Quat;
nuclear@0 246
nuclear@0 247
nuclear@0 248 //-------------------------------------------------------------------------------------
nuclear@0 249 // ***** Vector2<>
nuclear@0 250
nuclear@0 251 // Vector2f (Vector2d) represents a 2-dimensional vector or point in space,
nuclear@0 252 // consisting of coordinates x and y
nuclear@0 253
nuclear@0 254 template<class T>
nuclear@0 255 class Vector2
nuclear@0 256 {
nuclear@0 257 public:
nuclear@0 258 T x, y;
nuclear@0 259
nuclear@0 260 Vector2() : x(0), y(0) { }
nuclear@0 261 Vector2(T x_, T y_) : x(x_), y(y_) { }
nuclear@0 262 explicit Vector2(T s) : x(s), y(s) { }
nuclear@0 263 explicit Vector2(const Vector2<typename Math<T>::OtherFloatType> &src)
nuclear@0 264 : x((T)src.x), y((T)src.y) { }
nuclear@0 265
nuclear@0 266
nuclear@0 267 // C-interop support.
nuclear@0 268 typedef typename CompatibleTypes<Vector2<T> >::Type CompatibleType;
nuclear@0 269
nuclear@0 270 Vector2(const CompatibleType& s) : x(s.x), y(s.y) { }
nuclear@0 271
nuclear@0 272 operator const CompatibleType& () const
nuclear@0 273 {
nuclear@0 274 static_assert(sizeof(Vector2<T>) == sizeof(CompatibleType), "sizeof(Vector2<T>) failure");
nuclear@0 275 return reinterpret_cast<const CompatibleType&>(*this);
nuclear@0 276 }
nuclear@0 277
nuclear@0 278
nuclear@0 279 bool operator== (const Vector2& b) const { return x == b.x && y == b.y; }
nuclear@0 280 bool operator!= (const Vector2& b) const { return x != b.x || y != b.y; }
nuclear@0 281
nuclear@0 282 Vector2 operator+ (const Vector2& b) const { return Vector2(x + b.x, y + b.y); }
nuclear@0 283 Vector2& operator+= (const Vector2& b) { x += b.x; y += b.y; return *this; }
nuclear@0 284 Vector2 operator- (const Vector2& b) const { return Vector2(x - b.x, y - b.y); }
nuclear@0 285 Vector2& operator-= (const Vector2& b) { x -= b.x; y -= b.y; return *this; }
nuclear@0 286 Vector2 operator- () const { return Vector2(-x, -y); }
nuclear@0 287
nuclear@0 288 // Scalar multiplication/division scales vector.
nuclear@0 289 Vector2 operator* (T s) const { return Vector2(x*s, y*s); }
nuclear@0 290 Vector2& operator*= (T s) { x *= s; y *= s; return *this; }
nuclear@0 291
nuclear@0 292 Vector2 operator/ (T s) const { T rcp = T(1)/s;
nuclear@0 293 return Vector2(x*rcp, y*rcp); }
nuclear@0 294 Vector2& operator/= (T s) { T rcp = T(1)/s;
nuclear@0 295 x *= rcp; y *= rcp;
nuclear@0 296 return *this; }
nuclear@0 297
nuclear@0 298 static Vector2 Min(const Vector2& a, const Vector2& b) { return Vector2((a.x < b.x) ? a.x : b.x,
nuclear@0 299 (a.y < b.y) ? a.y : b.y); }
nuclear@0 300 static Vector2 Max(const Vector2& a, const Vector2& b) { return Vector2((a.x > b.x) ? a.x : b.x,
nuclear@0 301 (a.y > b.y) ? a.y : b.y); }
nuclear@0 302
nuclear@0 303 // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance.
nuclear@0 304 bool Compare(const Vector2&b, T tolerance = ((T)MATH_DOUBLE_TOLERANCE))
nuclear@0 305 {
nuclear@0 306 return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance);
nuclear@0 307 }
nuclear@0 308
nuclear@0 309 // Access element by index
nuclear@0 310 T& operator[] (int idx)
nuclear@0 311 {
nuclear@0 312 OVR_ASSERT(0 <= idx && idx < 2);
nuclear@0 313 return *(&x + idx);
nuclear@0 314 }
nuclear@0 315 const T& operator[] (int idx) const
nuclear@0 316 {
nuclear@0 317 OVR_ASSERT(0 <= idx && idx < 2);
nuclear@0 318 return *(&x + idx);
nuclear@0 319 }
nuclear@0 320
nuclear@0 321 // Entry-wise product of two vectors
nuclear@0 322 Vector2 EntrywiseMultiply(const Vector2& b) const { return Vector2(x * b.x, y * b.y);}
nuclear@0 323
nuclear@0 324
nuclear@0 325 // Multiply and divide operators do entry-wise math. Used Dot() for dot product.
nuclear@0 326 Vector2 operator* (const Vector2& b) const { return Vector2(x * b.x, y * b.y); }
nuclear@0 327 Vector2 operator/ (const Vector2& b) const { return Vector2(x / b.x, y / b.y); }
nuclear@0 328
nuclear@0 329 // Dot product
nuclear@0 330 // Used to calculate angle q between two vectors among other things,
nuclear@0 331 // as (A dot B) = |a||b|cos(q).
nuclear@0 332 T Dot(const Vector2& b) const { return x*b.x + y*b.y; }
nuclear@0 333
nuclear@0 334 // Returns the angle from this vector to b, in radians.
nuclear@0 335 T Angle(const Vector2& b) const
nuclear@0 336 {
nuclear@0 337 T div = LengthSq()*b.LengthSq();
nuclear@0 338 OVR_ASSERT(div != T(0));
nuclear@0 339 T result = Acos((this->Dot(b))/sqrt(div));
nuclear@0 340 return result;
nuclear@0 341 }
nuclear@0 342
nuclear@0 343 // Return Length of the vector squared.
nuclear@0 344 T LengthSq() const { return (x * x + y * y); }
nuclear@0 345
nuclear@0 346 // Return vector length.
nuclear@0 347 T Length() const { return sqrt(LengthSq()); }
nuclear@0 348
nuclear@0 349 // Returns squared distance between two points represented by vectors.
nuclear@0 350 T DistanceSq(const Vector2& b) const { return (*this - b).LengthSq(); }
nuclear@0 351
nuclear@0 352 // Returns distance between two points represented by vectors.
nuclear@0 353 T Distance(const Vector2& b) const { return (*this - b).Length(); }
nuclear@0 354
nuclear@0 355 // Determine if this a unit vector.
nuclear@0 356 bool IsNormalized() const { return fabs(LengthSq() - T(1)) < ((T)MATH_DOUBLE_TOLERANCE); }
nuclear@0 357
nuclear@0 358 // Normalize, convention vector length to 1.
nuclear@0 359 void Normalize()
nuclear@0 360 {
nuclear@0 361 T l = Length();
nuclear@0 362 OVR_ASSERT(l != T(0));
nuclear@0 363 *this /= l;
nuclear@0 364 }
nuclear@0 365 // Returns normalized (unit) version of the vector without modifying itself.
nuclear@0 366 Vector2 Normalized() const
nuclear@0 367 {
nuclear@0 368 T l = Length();
nuclear@0 369 OVR_ASSERT(l != T(0));
nuclear@0 370 return *this / l;
nuclear@0 371 }
nuclear@0 372
nuclear@0 373 // Linearly interpolates from this vector to another.
nuclear@0 374 // Factor should be between 0.0 and 1.0, with 0 giving full value to this.
nuclear@0 375 Vector2 Lerp(const Vector2& b, T f) const { return *this*(T(1) - f) + b*f; }
nuclear@0 376
nuclear@0 377 // Projects this vector onto the argument; in other words,
nuclear@0 378 // A.Project(B) returns projection of vector A onto B.
nuclear@0 379 Vector2 ProjectTo(const Vector2& b) const
nuclear@0 380 {
nuclear@0 381 T l2 = b.LengthSq();
nuclear@0 382 OVR_ASSERT(l2 != T(0));
nuclear@0 383 return b * ( Dot(b) / l2 );
nuclear@0 384 }
nuclear@0 385 };
nuclear@0 386
nuclear@0 387
nuclear@0 388 typedef Vector2<float> Vector2f;
nuclear@0 389 typedef Vector2<double> Vector2d;
nuclear@0 390 typedef Vector2<int> Vector2i;
nuclear@0 391
nuclear@0 392 typedef Vector2<float> Point2f;
nuclear@0 393 typedef Vector2<double> Point2d;
nuclear@0 394 typedef Vector2<int> Point2i;
nuclear@0 395
nuclear@0 396 //-------------------------------------------------------------------------------------
nuclear@0 397 // ***** Vector3<> - 3D vector of {x, y, z}
nuclear@0 398
nuclear@0 399 //
nuclear@0 400 // Vector3f (Vector3d) represents a 3-dimensional vector or point in space,
nuclear@0 401 // consisting of coordinates x, y and z.
nuclear@0 402
nuclear@0 403 template<class T>
nuclear@0 404 class Vector3
nuclear@0 405 {
nuclear@0 406 public:
nuclear@0 407 T x, y, z;
nuclear@0 408
nuclear@0 409 // FIXME: default initialization of a vector class can be very expensive in a full-blown
nuclear@0 410 // application. A few hundred thousand vector constructions is not unlikely and can add
nuclear@0 411 // up to milliseconds of time on processors like the PS3 PPU.
nuclear@0 412 Vector3() : x(0), y(0), z(0) { }
nuclear@0 413 Vector3(T x_, T y_, T z_ = 0) : x(x_), y(y_), z(z_) { }
nuclear@0 414 explicit Vector3(T s) : x(s), y(s), z(s) { }
nuclear@0 415 explicit Vector3(const Vector3<typename Math<T>::OtherFloatType> &src)
nuclear@0 416 : x((T)src.x), y((T)src.y), z((T)src.z) { }
nuclear@0 417
nuclear@0 418 static const Vector3 ZERO;
nuclear@0 419
nuclear@0 420 // C-interop support.
nuclear@0 421 typedef typename CompatibleTypes<Vector3<T> >::Type CompatibleType;
nuclear@0 422
nuclear@0 423 Vector3(const CompatibleType& s) : x(s.x), y(s.y), z(s.z) { }
nuclear@0 424
nuclear@0 425 operator const CompatibleType& () const
nuclear@0 426 {
nuclear@0 427 static_assert(sizeof(Vector3<T>) == sizeof(CompatibleType), "sizeof(Vector3<T>) failure");
nuclear@0 428 return reinterpret_cast<const CompatibleType&>(*this);
nuclear@0 429 }
nuclear@0 430
nuclear@0 431 bool operator== (const Vector3& b) const { return x == b.x && y == b.y && z == b.z; }
nuclear@0 432 bool operator!= (const Vector3& b) const { return x != b.x || y != b.y || z != b.z; }
nuclear@0 433
nuclear@0 434 Vector3 operator+ (const Vector3& b) const { return Vector3(x + b.x, y + b.y, z + b.z); }
nuclear@0 435 Vector3& operator+= (const Vector3& b) { x += b.x; y += b.y; z += b.z; return *this; }
nuclear@0 436 Vector3 operator- (const Vector3& b) const { return Vector3(x - b.x, y - b.y, z - b.z); }
nuclear@0 437 Vector3& operator-= (const Vector3& b) { x -= b.x; y -= b.y; z -= b.z; return *this; }
nuclear@0 438 Vector3 operator- () const { return Vector3(-x, -y, -z); }
nuclear@0 439
nuclear@0 440 // Scalar multiplication/division scales vector.
nuclear@0 441 Vector3 operator* (T s) const { return Vector3(x*s, y*s, z*s); }
nuclear@0 442 Vector3& operator*= (T s) { x *= s; y *= s; z *= s; return *this; }
nuclear@0 443
nuclear@0 444 Vector3 operator/ (T s) const { T rcp = T(1)/s;
nuclear@0 445 return Vector3(x*rcp, y*rcp, z*rcp); }
nuclear@0 446 Vector3& operator/= (T s) { T rcp = T(1)/s;
nuclear@0 447 x *= rcp; y *= rcp; z *= rcp;
nuclear@0 448 return *this; }
nuclear@0 449
nuclear@0 450 static Vector3 Min(const Vector3& a, const Vector3& b)
nuclear@0 451 {
nuclear@0 452 return Vector3((a.x < b.x) ? a.x : b.x,
nuclear@0 453 (a.y < b.y) ? a.y : b.y,
nuclear@0 454 (a.z < b.z) ? a.z : b.z);
nuclear@0 455 }
nuclear@0 456 static Vector3 Max(const Vector3& a, const Vector3& b)
nuclear@0 457 {
nuclear@0 458 return Vector3((a.x > b.x) ? a.x : b.x,
nuclear@0 459 (a.y > b.y) ? a.y : b.y,
nuclear@0 460 (a.z > b.z) ? a.z : b.z);
nuclear@0 461 }
nuclear@0 462
nuclear@0 463 // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance.
nuclear@0 464 bool Compare(const Vector3&b, T tolerance = ((T)MATH_DOUBLE_TOLERANCE))
nuclear@0 465 {
nuclear@0 466 return (fabs(b.x-x) < tolerance) &&
nuclear@0 467 (fabs(b.y-y) < tolerance) &&
nuclear@0 468 (fabs(b.z-z) < tolerance);
nuclear@0 469 }
nuclear@0 470
nuclear@0 471 T& operator[] (int idx)
nuclear@0 472 {
nuclear@0 473 OVR_ASSERT(0 <= idx && idx < 3);
nuclear@0 474 return *(&x + idx);
nuclear@0 475 }
nuclear@0 476
nuclear@0 477 const T& operator[] (int idx) const
nuclear@0 478 {
nuclear@0 479 OVR_ASSERT(0 <= idx && idx < 3);
nuclear@0 480 return *(&x + idx);
nuclear@0 481 }
nuclear@0 482
nuclear@0 483 // Entrywise product of two vectors
nuclear@0 484 Vector3 EntrywiseMultiply(const Vector3& b) const { return Vector3(x * b.x,
nuclear@0 485 y * b.y,
nuclear@0 486 z * b.z);}
nuclear@0 487
nuclear@0 488 // Multiply and divide operators do entry-wise math
nuclear@0 489 Vector3 operator* (const Vector3& b) const { return Vector3(x * b.x,
nuclear@0 490 y * b.y,
nuclear@0 491 z * b.z); }
nuclear@0 492
nuclear@0 493 Vector3 operator/ (const Vector3& b) const { return Vector3(x / b.x,
nuclear@0 494 y / b.y,
nuclear@0 495 z / b.z); }
nuclear@0 496
nuclear@0 497
nuclear@0 498 // Dot product
nuclear@0 499 // Used to calculate angle q between two vectors among other things,
nuclear@0 500 // as (A dot B) = |a||b|cos(q).
nuclear@0 501 T Dot(const Vector3& b) const { return x*b.x + y*b.y + z*b.z; }
nuclear@0 502
nuclear@0 503 // Compute cross product, which generates a normal vector.
nuclear@0 504 // Direction vector can be determined by right-hand rule: Pointing index finder in
nuclear@0 505 // direction a and middle finger in direction b, thumb will point in a.Cross(b).
nuclear@0 506 Vector3 Cross(const Vector3& b) const { return Vector3(y*b.z - z*b.y,
nuclear@0 507 z*b.x - x*b.z,
nuclear@0 508 x*b.y - y*b.x); }
nuclear@0 509
nuclear@0 510 // Returns the angle from this vector to b, in radians.
nuclear@0 511 T Angle(const Vector3& b) const
nuclear@0 512 {
nuclear@0 513 T div = LengthSq()*b.LengthSq();
nuclear@0 514 OVR_ASSERT(div != T(0));
nuclear@0 515 T result = Acos((this->Dot(b))/sqrt(div));
nuclear@0 516 return result;
nuclear@0 517 }
nuclear@0 518
nuclear@0 519 // Return Length of the vector squared.
nuclear@0 520 T LengthSq() const { return (x * x + y * y + z * z); }
nuclear@0 521
nuclear@0 522 // Return vector length.
nuclear@0 523 T Length() const { return sqrt(LengthSq()); }
nuclear@0 524
nuclear@0 525 // Returns squared distance between two points represented by vectors.
nuclear@0 526 T DistanceSq(Vector3 const& b) const { return (*this - b).LengthSq(); }
nuclear@0 527
nuclear@0 528 // Returns distance between two points represented by vectors.
nuclear@0 529 T Distance(Vector3 const& b) const { return (*this - b).Length(); }
nuclear@0 530
nuclear@0 531 // Determine if this a unit vector.
nuclear@0 532 bool IsNormalized() const { return fabs(LengthSq() - T(1)) < ((T)MATH_DOUBLE_TOLERANCE); }
nuclear@0 533
nuclear@0 534 // Normalize, convention vector length to 1.
nuclear@0 535 void Normalize()
nuclear@0 536 {
nuclear@0 537 T l = Length();
nuclear@0 538 OVR_ASSERT(l != T(0));
nuclear@0 539 *this /= l;
nuclear@0 540 }
nuclear@0 541
nuclear@0 542 // Returns normalized (unit) version of the vector without modifying itself.
nuclear@0 543 Vector3 Normalized() const
nuclear@0 544 {
nuclear@0 545 T l = Length();
nuclear@0 546 OVR_ASSERT(l != T(0));
nuclear@0 547 return *this / l;
nuclear@0 548 }
nuclear@0 549
nuclear@0 550 // Linearly interpolates from this vector to another.
nuclear@0 551 // Factor should be between 0.0 and 1.0, with 0 giving full value to this.
nuclear@0 552 Vector3 Lerp(const Vector3& b, T f) const { return *this*(T(1) - f) + b*f; }
nuclear@0 553
nuclear@0 554 // Projects this vector onto the argument; in other words,
nuclear@0 555 // A.Project(B) returns projection of vector A onto B.
nuclear@0 556 Vector3 ProjectTo(const Vector3& b) const
nuclear@0 557 {
nuclear@0 558 T l2 = b.LengthSq();
nuclear@0 559 OVR_ASSERT(l2 != T(0));
nuclear@0 560 return b * ( Dot(b) / l2 );
nuclear@0 561 }
nuclear@0 562
nuclear@0 563 // Projects this vector onto a plane defined by a normal vector
nuclear@0 564 Vector3 ProjectToPlane(const Vector3& normal) const { return *this - this->ProjectTo(normal); }
nuclear@0 565 };
nuclear@0 566
nuclear@0 567 typedef Vector3<float> Vector3f;
nuclear@0 568 typedef Vector3<double> Vector3d;
nuclear@0 569 typedef Vector3<int32_t> Vector3i;
nuclear@0 570
nuclear@0 571 static_assert((sizeof(Vector3f) == 3*sizeof(float)), "sizeof(Vector3f) failure");
nuclear@0 572 static_assert((sizeof(Vector3d) == 3*sizeof(double)), "sizeof(Vector3d) failure");
nuclear@0 573 static_assert((sizeof(Vector3i) == 3*sizeof(int32_t)), "sizeof(Vector3i) failure");
nuclear@0 574
nuclear@0 575 typedef Vector3<float> Point3f;
nuclear@0 576 typedef Vector3<double> Point3d;
nuclear@0 577 typedef Vector3<int32_t> Point3i;
nuclear@0 578
nuclear@0 579
nuclear@0 580 //-------------------------------------------------------------------------------------
nuclear@0 581 // ***** Vector4<> - 4D vector of {x, y, z, w}
nuclear@0 582
nuclear@0 583 //
nuclear@0 584 // Vector4f (Vector4d) represents a 3-dimensional vector or point in space,
nuclear@0 585 // consisting of coordinates x, y, z and w.
nuclear@0 586
nuclear@0 587 template<class T>
nuclear@0 588 class Vector4
nuclear@0 589 {
nuclear@0 590 public:
nuclear@0 591 T x, y, z, w;
nuclear@0 592
nuclear@0 593 // FIXME: default initialization of a vector class can be very expensive in a full-blown
nuclear@0 594 // application. A few hundred thousand vector constructions is not unlikely and can add
nuclear@0 595 // up to milliseconds of time on processors like the PS3 PPU.
nuclear@0 596 Vector4() : x(0), y(0), z(0), w(0) { }
nuclear@0 597 Vector4(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) { }
nuclear@0 598 explicit Vector4(T s) : x(s), y(s), z(s), w(s) { }
nuclear@0 599 explicit Vector4(const Vector3<T>& v, const float w_=1) : x(v.x), y(v.y), z(v.z), w(w_) { }
nuclear@0 600 explicit Vector4(const Vector4<typename Math<T>::OtherFloatType> &src)
nuclear@0 601 : x((T)src.x), y((T)src.y), z((T)src.z), w((T)src.w) { }
nuclear@0 602
nuclear@0 603 static const Vector4 ZERO;
nuclear@0 604
nuclear@0 605 // C-interop support.
nuclear@0 606 typedef typename CompatibleTypes< Vector4<T> >::Type CompatibleType;
nuclear@0 607
nuclear@0 608 Vector4(const CompatibleType& s) : x(s.x), y(s.y), z(s.z), w(s.w) { }
nuclear@0 609
nuclear@0 610 operator const CompatibleType& () const
nuclear@0 611 {
nuclear@0 612 static_assert(sizeof(Vector4<T>) == sizeof(CompatibleType), "sizeof(Vector4<T>) failure");
nuclear@0 613 return reinterpret_cast<const CompatibleType&>(*this);
nuclear@0 614 }
nuclear@0 615
nuclear@0 616 Vector4& operator= (const Vector3<T>& other) { x=other.x; y=other.y; z=other.z; w=1; return *this; }
nuclear@0 617 bool operator== (const Vector4& b) const { return x == b.x && y == b.y && z == b.z && w == b.w; }
nuclear@0 618 bool operator!= (const Vector4& b) const { return x != b.x || y != b.y || z != b.z || w != b.w; }
nuclear@0 619
nuclear@0 620 Vector4 operator+ (const Vector4& b) const { return Vector4(x + b.x, y + b.y, z + b.z, w + b.w); }
nuclear@0 621 Vector4& operator+= (const Vector4& b) { x += b.x; y += b.y; z += b.z; w += b.w; return *this; }
nuclear@0 622 Vector4 operator- (const Vector4& b) const { return Vector4(x - b.x, y - b.y, z - b.z, w - b.w); }
nuclear@0 623 Vector4& operator-= (const Vector4& b) { x -= b.x; y -= b.y; z -= b.z; w -= b.w; return *this; }
nuclear@0 624 Vector4 operator- () const { return Vector4(-x, -y, -z, -w); }
nuclear@0 625
nuclear@0 626 // Scalar multiplication/division scales vector.
nuclear@0 627 Vector4 operator* (T s) const { return Vector4(x*s, y*s, z*s, w*s); }
nuclear@0 628 Vector4& operator*= (T s) { x *= s; y *= s; z *= s; w *= s;return *this; }
nuclear@0 629
nuclear@0 630 Vector4 operator/ (T s) const { T rcp = T(1)/s;
nuclear@0 631 return Vector4(x*rcp, y*rcp, z*rcp, w*rcp); }
nuclear@0 632 Vector4& operator/= (T s) { T rcp = T(1)/s;
nuclear@0 633 x *= rcp; y *= rcp; z *= rcp; w *= rcp;
nuclear@0 634 return *this; }
nuclear@0 635
nuclear@0 636 static Vector4 Min(const Vector4& a, const Vector4& b)
nuclear@0 637 {
nuclear@0 638 return Vector4((a.x < b.x) ? a.x : b.x,
nuclear@0 639 (a.y < b.y) ? a.y : b.y,
nuclear@0 640 (a.z < b.z) ? a.z : b.z,
nuclear@0 641 (a.w < b.w) ? a.w : b.w);
nuclear@0 642 }
nuclear@0 643 static Vector4 Max(const Vector4& a, const Vector4& b)
nuclear@0 644 {
nuclear@0 645 return Vector4((a.x > b.x) ? a.x : b.x,
nuclear@0 646 (a.y > b.y) ? a.y : b.y,
nuclear@0 647 (a.z > b.z) ? a.z : b.z,
nuclear@0 648 (a.w > b.w) ? a.w : b.w);
nuclear@0 649 }
nuclear@0 650
nuclear@0 651 // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance.
nuclear@0 652 bool Compare(const Vector4&b, T tolerance = ((T)MATH_DOUBLE_TOLERANCE))
nuclear@0 653 {
nuclear@0 654 return (fabs(b.x-x) < tolerance) &&
nuclear@0 655 (fabs(b.y-y) < tolerance) &&
nuclear@0 656 (fabs(b.z-z) < tolerance) &&
nuclear@0 657 (fabs(b.w-w) < tolerance);
nuclear@0 658 }
nuclear@0 659
nuclear@0 660 T& operator[] (int idx)
nuclear@0 661 {
nuclear@0 662 OVR_ASSERT(0 <= idx && idx < 4);
nuclear@0 663 return *(&x + idx);
nuclear@0 664 }
nuclear@0 665
nuclear@0 666 const T& operator[] (int idx) const
nuclear@0 667 {
nuclear@0 668 OVR_ASSERT(0 <= idx && idx < 4);
nuclear@0 669 return *(&x + idx);
nuclear@0 670 }
nuclear@0 671
nuclear@0 672 // Entry wise product of two vectors
nuclear@0 673 Vector4 EntrywiseMultiply(const Vector4& b) const { return Vector4(x * b.x,
nuclear@0 674 y * b.y,
nuclear@0 675 z * b.z);}
nuclear@0 676
nuclear@0 677 // Multiply and divide operators do entry-wise math
nuclear@0 678 Vector4 operator* (const Vector4& b) const { return Vector4(x * b.x,
nuclear@0 679 y * b.y,
nuclear@0 680 z * b.z,
nuclear@0 681 w * b.w); }
nuclear@0 682
nuclear@0 683 Vector4 operator/ (const Vector4& b) const { return Vector4(x / b.x,
nuclear@0 684 y / b.y,
nuclear@0 685 z / b.z,
nuclear@0 686 w / b.w); }
nuclear@0 687
nuclear@0 688
nuclear@0 689 // Dot product
nuclear@0 690 T Dot(const Vector4& b) const { return x*b.x + y*b.y + z*b.z + w*b.w; }
nuclear@0 691
nuclear@0 692 // Return Length of the vector squared.
nuclear@0 693 T LengthSq() const { return (x * x + y * y + z * z + w * w); }
nuclear@0 694
nuclear@0 695 // Return vector length.
nuclear@0 696 T Length() const { return sqrt(LengthSq()); }
nuclear@0 697
nuclear@0 698 // Determine if this a unit vector.
nuclear@0 699 bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; }
nuclear@0 700
nuclear@0 701 // Normalize, convention vector length to 1.
nuclear@0 702 void Normalize()
nuclear@0 703 {
nuclear@0 704 T l = Length();
nuclear@0 705 OVR_ASSERT(l != T(0));
nuclear@0 706 *this /= l;
nuclear@0 707 }
nuclear@0 708
nuclear@0 709 // Returns normalized (unit) version of the vector without modifying itself.
nuclear@0 710 Vector4 Normalized() const
nuclear@0 711 {
nuclear@0 712 T l = Length();
nuclear@0 713 OVR_ASSERT(l != T(0));
nuclear@0 714 return *this / l;
nuclear@0 715 }
nuclear@0 716 };
nuclear@0 717
nuclear@0 718 typedef Vector4<float> Vector4f;
nuclear@0 719 typedef Vector4<double> Vector4d;
nuclear@0 720 typedef Vector4<int> Vector4i;
nuclear@0 721
nuclear@0 722
nuclear@0 723 //-------------------------------------------------------------------------------------
nuclear@0 724 // ***** Bounds3
nuclear@0 725
nuclear@0 726 // Bounds class used to describe a 3D axis aligned bounding box.
nuclear@0 727
nuclear@0 728 template<class T>
nuclear@0 729 class Bounds3
nuclear@0 730 {
nuclear@0 731 public:
nuclear@0 732 Vector3<T> b[2];
nuclear@0 733
nuclear@0 734 Bounds3()
nuclear@0 735 {
nuclear@0 736 }
nuclear@0 737
nuclear@0 738 Bounds3( const Vector3<T> & mins, const Vector3<T> & maxs )
nuclear@0 739 {
nuclear@0 740 b[0] = mins;
nuclear@0 741 b[1] = maxs;
nuclear@0 742 }
nuclear@0 743
nuclear@0 744 void Clear()
nuclear@0 745 {
nuclear@0 746 b[0].x = b[0].y = b[0].z = Math<T>::MaxValue;
nuclear@0 747 b[1].x = b[1].y = b[1].z = -Math<T>::MaxValue;
nuclear@0 748 }
nuclear@0 749
nuclear@0 750 void AddPoint( const Vector3<T> & v )
nuclear@0 751 {
nuclear@0 752 b[0].x = Alg::Min( b[0].x, v.x );
nuclear@0 753 b[0].y = Alg::Min( b[0].y, v.y );
nuclear@0 754 b[0].z = Alg::Min( b[0].z, v.z );
nuclear@0 755 b[1].x = Alg::Max( b[1].x, v.x );
nuclear@0 756 b[1].y = Alg::Max( b[1].y, v.y );
nuclear@0 757 b[1].z = Alg::Max( b[1].z, v.z );
nuclear@0 758 }
nuclear@0 759
nuclear@0 760 const Vector3<T> & GetMins() const { return b[0]; }
nuclear@0 761 const Vector3<T> & GetMaxs() const { return b[1]; }
nuclear@0 762
nuclear@0 763 Vector3<T> & GetMins() { return b[0]; }
nuclear@0 764 Vector3<T> & GetMaxs() { return b[1]; }
nuclear@0 765 };
nuclear@0 766
nuclear@0 767 typedef Bounds3<float> Bounds3f;
nuclear@0 768 typedef Bounds3<double> Bounds3d;
nuclear@0 769
nuclear@0 770
nuclear@0 771 //-------------------------------------------------------------------------------------
nuclear@0 772 // ***** Size
nuclear@0 773
nuclear@0 774 // Size class represents 2D size with Width, Height components.
nuclear@0 775 // Used to describe distentions of render targets, etc.
nuclear@0 776
nuclear@0 777 template<class T>
nuclear@0 778 class Size
nuclear@0 779 {
nuclear@0 780 public:
nuclear@0 781 T w, h;
nuclear@0 782
nuclear@0 783 Size() : w(0), h(0) { }
nuclear@0 784 Size(T w_, T h_) : w(w_), h(h_) { }
nuclear@0 785 explicit Size(T s) : w(s), h(s) { }
nuclear@0 786 explicit Size(const Size<typename Math<T>::OtherFloatType> &src)
nuclear@0 787 : w((T)src.w), h((T)src.h) { }
nuclear@0 788
nuclear@0 789 // C-interop support.
nuclear@0 790 typedef typename CompatibleTypes<Size<T> >::Type CompatibleType;
nuclear@0 791
nuclear@0 792 Size(const CompatibleType& s) : w(s.w), h(s.h) { }
nuclear@0 793
nuclear@0 794 operator const CompatibleType& () const
nuclear@0 795 {
nuclear@0 796 static_assert(sizeof(Size<T>) == sizeof(CompatibleType), "sizeof(Size<T>) failure");
nuclear@0 797 return reinterpret_cast<const CompatibleType&>(*this);
nuclear@0 798 }
nuclear@0 799
nuclear@0 800 bool operator== (const Size& b) const { return w == b.w && h == b.h; }
nuclear@0 801 bool operator!= (const Size& b) const { return w != b.w || h != b.h; }
nuclear@0 802
nuclear@0 803 Size operator+ (const Size& b) const { return Size(w + b.w, h + b.h); }
nuclear@0 804 Size& operator+= (const Size& b) { w += b.w; h += b.h; return *this; }
nuclear@0 805 Size operator- (const Size& b) const { return Size(w - b.w, h - b.h); }
nuclear@0 806 Size& operator-= (const Size& b) { w -= b.w; h -= b.h; return *this; }
nuclear@0 807 Size operator- () const { return Size(-w, -h); }
nuclear@0 808 Size operator* (const Size& b) const { return Size(w * b.w, h * b.h); }
nuclear@0 809 Size& operator*= (const Size& b) { w *= b.w; h *= b.h; return *this; }
nuclear@0 810 Size operator/ (const Size& b) const { return Size(w / b.w, h / b.h); }
nuclear@0 811 Size& operator/= (const Size& b) { w /= b.w; h /= b.h; return *this; }
nuclear@0 812
nuclear@0 813 // Scalar multiplication/division scales both components.
nuclear@0 814 Size operator* (T s) const { return Size(w*s, h*s); }
nuclear@0 815 Size& operator*= (T s) { w *= s; h *= s; return *this; }
nuclear@0 816 Size operator/ (T s) const { return Size(w/s, h/s); }
nuclear@0 817 Size& operator/= (T s) { w /= s; h /= s; return *this; }
nuclear@0 818
nuclear@0 819 static Size Min(const Size& a, const Size& b) { return Size((a.w < b.w) ? a.w : b.w,
nuclear@0 820 (a.h < b.h) ? a.h : b.h); }
nuclear@0 821 static Size Max(const Size& a, const Size& b) { return Size((a.w > b.w) ? a.w : b.w,
nuclear@0 822 (a.h > b.h) ? a.h : b.h); }
nuclear@0 823
nuclear@0 824 T Area() const { return w * h; }
nuclear@0 825
nuclear@0 826 inline Vector2<T> ToVector() const { return Vector2<T>(w, h); }
nuclear@0 827 };
nuclear@0 828
nuclear@0 829
nuclear@0 830 typedef Size<int> Sizei;
nuclear@0 831 typedef Size<unsigned> Sizeu;
nuclear@0 832 typedef Size<float> Sizef;
nuclear@0 833 typedef Size<double> Sized;
nuclear@0 834
nuclear@0 835
nuclear@0 836
nuclear@0 837 //-----------------------------------------------------------------------------------
nuclear@0 838 // ***** Rect
nuclear@0 839
nuclear@0 840 // Rect describes a rectangular area for rendering, that includes position and size.
nuclear@0 841 template<class T>
nuclear@0 842 class Rect
nuclear@0 843 {
nuclear@0 844 public:
nuclear@0 845 T x, y;
nuclear@0 846 T w, h;
nuclear@0 847
nuclear@0 848 Rect() { }
nuclear@0 849 Rect(T x1, T y1, T w1, T h1) : x(x1), y(y1), w(w1), h(h1) { }
nuclear@0 850 Rect(const Vector2<T>& pos, const Size<T>& sz) : x(pos.x), y(pos.y), w(sz.w), h(sz.h) { }
nuclear@0 851 Rect(const Size<T>& sz) : x(0), y(0), w(sz.w), h(sz.h) { }
nuclear@0 852
nuclear@0 853 // C-interop support.
nuclear@0 854 typedef typename CompatibleTypes<Rect<T> >::Type CompatibleType;
nuclear@0 855
nuclear@0 856 Rect(const CompatibleType& s) : x(s.Pos.x), y(s.Pos.y), w(s.Size.w), h(s.Size.h) { }
nuclear@0 857
nuclear@0 858 operator const CompatibleType& () const
nuclear@0 859 {
nuclear@0 860 static_assert(sizeof(Rect<T>) == sizeof(CompatibleType), "sizeof(Rect<T>) failure");
nuclear@0 861 return reinterpret_cast<const CompatibleType&>(*this);
nuclear@0 862 }
nuclear@0 863
nuclear@0 864 Vector2<T> GetPos() const { return Vector2<T>(x, y); }
nuclear@0 865 Size<T> GetSize() const { return Size<T>(w, h); }
nuclear@0 866 void SetPos(const Vector2<T>& pos) { x = pos.x; y = pos.y; }
nuclear@0 867 void SetSize(const Size<T>& sz) { w = sz.w; h = sz.h; }
nuclear@0 868
nuclear@0 869 bool operator == (const Rect& vp) const
nuclear@0 870 { return (x == vp.x) && (y == vp.y) && (w == vp.w) && (h == vp.h); }
nuclear@0 871 bool operator != (const Rect& vp) const
nuclear@0 872 { return !operator == (vp); }
nuclear@0 873 };
nuclear@0 874
nuclear@0 875 typedef Rect<int> Recti;
nuclear@0 876
nuclear@0 877
nuclear@0 878 //-------------------------------------------------------------------------------------//
nuclear@0 879 // ***** Quat
nuclear@0 880 //
nuclear@0 881 // Quatf represents a quaternion class used for rotations.
nuclear@0 882 //
nuclear@0 883 // Quaternion multiplications are done in right-to-left order, to match the
nuclear@0 884 // behavior of matrices.
nuclear@0 885
nuclear@0 886
nuclear@0 887 template<class T>
nuclear@0 888 class Quat
nuclear@0 889 {
nuclear@0 890 public:
nuclear@0 891 // w + Xi + Yj + Zk
nuclear@0 892 T x, y, z, w;
nuclear@0 893
nuclear@0 894 Quat() : x(0), y(0), z(0), w(1) { }
nuclear@0 895 Quat(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) { }
nuclear@0 896 explicit Quat(const Quat<typename Math<T>::OtherFloatType> &src)
nuclear@0 897 : x((T)src.x), y((T)src.y), z((T)src.z), w((T)src.w) { }
nuclear@0 898
nuclear@0 899 typedef typename CompatibleTypes<Quat<T> >::Type CompatibleType;
nuclear@0 900
nuclear@0 901 // C-interop support.
nuclear@0 902 Quat(const CompatibleType& s) : x(s.x), y(s.y), z(s.z), w(s.w) { }
nuclear@0 903
nuclear@0 904 operator CompatibleType () const
nuclear@0 905 {
nuclear@0 906 CompatibleType result;
nuclear@0 907 result.x = x;
nuclear@0 908 result.y = y;
nuclear@0 909 result.z = z;
nuclear@0 910 result.w = w;
nuclear@0 911 return result;
nuclear@0 912 }
nuclear@0 913
nuclear@0 914 // Constructs quaternion for rotation around the axis by an angle.
nuclear@0 915 Quat(const Vector3<T>& axis, T angle)
nuclear@0 916 {
nuclear@0 917 // Make sure we don't divide by zero.
nuclear@0 918 if (axis.LengthSq() == 0)
nuclear@0 919 {
nuclear@0 920 // Assert if the axis is zero, but the angle isn't
nuclear@0 921 OVR_ASSERT(angle == 0);
nuclear@0 922 x = 0; y = 0; z = 0; w = 1;
nuclear@0 923 return;
nuclear@0 924 }
nuclear@0 925
nuclear@0 926 Vector3<T> unitAxis = axis.Normalized();
nuclear@0 927 T sinHalfAngle = sin(angle * T(0.5));
nuclear@0 928
nuclear@0 929 w = cos(angle * T(0.5));
nuclear@0 930 x = unitAxis.x * sinHalfAngle;
nuclear@0 931 y = unitAxis.y * sinHalfAngle;
nuclear@0 932 z = unitAxis.z * sinHalfAngle;
nuclear@0 933 }
nuclear@0 934
nuclear@0 935 // Constructs quaternion for rotation around one of the coordinate axis by an angle.
nuclear@0 936 Quat(Axis A, T angle, RotateDirection d = Rotate_CCW, HandedSystem s = Handed_R)
nuclear@0 937 {
nuclear@0 938 T sinHalfAngle = s * d *sin(angle * T(0.5));
nuclear@0 939 T v[3];
nuclear@0 940 v[0] = v[1] = v[2] = T(0);
nuclear@0 941 v[A] = sinHalfAngle;
nuclear@0 942
nuclear@0 943 w = cos(angle * T(0.5));
nuclear@0 944 x = v[0];
nuclear@0 945 y = v[1];
nuclear@0 946 z = v[2];
nuclear@0 947 }
nuclear@0 948
nuclear@0 949 // Compute axis and angle from quaternion
nuclear@0 950 void GetAxisAngle(Vector3<T>* axis, T* angle) const
nuclear@0 951 {
nuclear@0 952 if ( x*x + y*y + z*z > ((T)MATH_DOUBLE_TOLERANCE) * ((T)MATH_DOUBLE_TOLERANCE) ) {
nuclear@0 953 *axis = Vector3<T>(x, y, z).Normalized();
nuclear@0 954 *angle = 2 * Acos(w);
nuclear@0 955 if (*angle > ((T)MATH_DOUBLE_PI)) // Reduce the magnitude of the angle, if necessary
nuclear@0 956 {
nuclear@0 957 *angle = ((T)MATH_DOUBLE_TWOPI) - *angle;
nuclear@0 958 *axis = *axis * (-1);
nuclear@0 959 }
nuclear@0 960 }
nuclear@0 961 else
nuclear@0 962 {
nuclear@0 963 *axis = Vector3<T>(1, 0, 0);
nuclear@0 964 *angle= 0;
nuclear@0 965 }
nuclear@0 966 }
nuclear@0 967
nuclear@0 968 // Constructs the quaternion from a rotation matrix
nuclear@0 969 explicit Quat(const Matrix4<T>& m)
nuclear@0 970 {
nuclear@0 971 T trace = m.M[0][0] + m.M[1][1] + m.M[2][2];
nuclear@0 972
nuclear@0 973 // In almost all cases, the first part is executed.
nuclear@0 974 // However, if the trace is not positive, the other
nuclear@0 975 // cases arise.
nuclear@0 976 if (trace > T(0))
nuclear@0 977 {
nuclear@0 978 T s = sqrt(trace + T(1)) * T(2); // s=4*qw
nuclear@0 979 w = T(0.25) * s;
nuclear@0 980 x = (m.M[2][1] - m.M[1][2]) / s;
nuclear@0 981 y = (m.M[0][2] - m.M[2][0]) / s;
nuclear@0 982 z = (m.M[1][0] - m.M[0][1]) / s;
nuclear@0 983 }
nuclear@0 984 else if ((m.M[0][0] > m.M[1][1])&&(m.M[0][0] > m.M[2][2]))
nuclear@0 985 {
nuclear@0 986 T s = sqrt(T(1) + m.M[0][0] - m.M[1][1] - m.M[2][2]) * T(2);
nuclear@0 987 w = (m.M[2][1] - m.M[1][2]) / s;
nuclear@0 988 x = T(0.25) * s;
nuclear@0 989 y = (m.M[0][1] + m.M[1][0]) / s;
nuclear@0 990 z = (m.M[2][0] + m.M[0][2]) / s;
nuclear@0 991 }
nuclear@0 992 else if (m.M[1][1] > m.M[2][2])
nuclear@0 993 {
nuclear@0 994 T s = sqrt(T(1) + m.M[1][1] - m.M[0][0] - m.M[2][2]) * T(2); // S=4*qy
nuclear@0 995 w = (m.M[0][2] - m.M[2][0]) / s;
nuclear@0 996 x = (m.M[0][1] + m.M[1][0]) / s;
nuclear@0 997 y = T(0.25) * s;
nuclear@0 998 z = (m.M[1][2] + m.M[2][1]) / s;
nuclear@0 999 }
nuclear@0 1000 else
nuclear@0 1001 {
nuclear@0 1002 T s = sqrt(T(1) + m.M[2][2] - m.M[0][0] - m.M[1][1]) * T(2); // S=4*qz
nuclear@0 1003 w = (m.M[1][0] - m.M[0][1]) / s;
nuclear@0 1004 x = (m.M[0][2] + m.M[2][0]) / s;
nuclear@0 1005 y = (m.M[1][2] + m.M[2][1]) / s;
nuclear@0 1006 z = T(0.25) * s;
nuclear@0 1007 }
nuclear@0 1008 }
nuclear@0 1009
nuclear@0 1010 // Constructs the quaternion from a rotation matrix
nuclear@0 1011 explicit Quat(const Matrix3<T>& m)
nuclear@0 1012 {
nuclear@0 1013 T trace = m.M[0][0] + m.M[1][1] + m.M[2][2];
nuclear@0 1014
nuclear@0 1015 // In almost all cases, the first part is executed.
nuclear@0 1016 // However, if the trace is not positive, the other
nuclear@0 1017 // cases arise.
nuclear@0 1018 if (trace > T(0))
nuclear@0 1019 {
nuclear@0 1020 T s = sqrt(trace + T(1)) * T(2); // s=4*qw
nuclear@0 1021 w = T(0.25) * s;
nuclear@0 1022 x = (m.M[2][1] - m.M[1][2]) / s;
nuclear@0 1023 y = (m.M[0][2] - m.M[2][0]) / s;
nuclear@0 1024 z = (m.M[1][0] - m.M[0][1]) / s;
nuclear@0 1025 }
nuclear@0 1026 else if ((m.M[0][0] > m.M[1][1])&&(m.M[0][0] > m.M[2][2]))
nuclear@0 1027 {
nuclear@0 1028 T s = sqrt(T(1) + m.M[0][0] - m.M[1][1] - m.M[2][2]) * T(2);
nuclear@0 1029 w = (m.M[2][1] - m.M[1][2]) / s;
nuclear@0 1030 x = T(0.25) * s;
nuclear@0 1031 y = (m.M[0][1] + m.M[1][0]) / s;
nuclear@0 1032 z = (m.M[2][0] + m.M[0][2]) / s;
nuclear@0 1033 }
nuclear@0 1034 else if (m.M[1][1] > m.M[2][2])
nuclear@0 1035 {
nuclear@0 1036 T s = sqrt(T(1) + m.M[1][1] - m.M[0][0] - m.M[2][2]) * T(2); // S=4*qy
nuclear@0 1037 w = (m.M[0][2] - m.M[2][0]) / s;
nuclear@0 1038 x = (m.M[0][1] + m.M[1][0]) / s;
nuclear@0 1039 y = T(0.25) * s;
nuclear@0 1040 z = (m.M[1][2] + m.M[2][1]) / s;
nuclear@0 1041 }
nuclear@0 1042 else
nuclear@0 1043 {
nuclear@0 1044 T s = sqrt(T(1) + m.M[2][2] - m.M[0][0] - m.M[1][1]) * T(2); // S=4*qz
nuclear@0 1045 w = (m.M[1][0] - m.M[0][1]) / s;
nuclear@0 1046 x = (m.M[0][2] + m.M[2][0]) / s;
nuclear@0 1047 y = (m.M[1][2] + m.M[2][1]) / s;
nuclear@0 1048 z = T(0.25) * s;
nuclear@0 1049 }
nuclear@0 1050 }
nuclear@0 1051
nuclear@0 1052 bool operator== (const Quat& b) const { return x == b.x && y == b.y && z == b.z && w == b.w; }
nuclear@0 1053 bool operator!= (const Quat& b) const { return x != b.x || y != b.y || z != b.z || w != b.w; }
nuclear@0 1054
nuclear@0 1055 Quat operator+ (const Quat& b) const { return Quat(x + b.x, y + b.y, z + b.z, w + b.w); }
nuclear@0 1056 Quat& operator+= (const Quat& b) { w += b.w; x += b.x; y += b.y; z += b.z; return *this; }
nuclear@0 1057 Quat operator- (const Quat& b) const { return Quat(x - b.x, y - b.y, z - b.z, w - b.w); }
nuclear@0 1058 Quat& operator-= (const Quat& b) { w -= b.w; x -= b.x; y -= b.y; z -= b.z; return *this; }
nuclear@0 1059
nuclear@0 1060 Quat operator* (T s) const { return Quat(x * s, y * s, z * s, w * s); }
nuclear@0 1061 Quat& operator*= (T s) { w *= s; x *= s; y *= s; z *= s; return *this; }
nuclear@0 1062 Quat operator/ (T s) const { T rcp = T(1)/s; return Quat(x * rcp, y * rcp, z * rcp, w *rcp); }
nuclear@0 1063 Quat& operator/= (T s) { T rcp = T(1)/s; w *= rcp; x *= rcp; y *= rcp; z *= rcp; return *this; }
nuclear@0 1064
nuclear@0 1065
nuclear@0 1066 // Get Imaginary part vector
nuclear@0 1067 Vector3<T> Imag() const { return Vector3<T>(x,y,z); }
nuclear@0 1068
nuclear@0 1069 // Get quaternion length.
nuclear@0 1070 T Length() const { return sqrt(LengthSq()); }
nuclear@0 1071
nuclear@0 1072 // Get quaternion length squared.
nuclear@0 1073 T LengthSq() const { return (x * x + y * y + z * z + w * w); }
nuclear@0 1074
nuclear@0 1075 // Simple Euclidean distance in R^4 (not SLERP distance, but at least respects Haar measure)
nuclear@0 1076 T Distance(const Quat& q) const
nuclear@0 1077 {
nuclear@0 1078 T d1 = (*this - q).Length();
nuclear@0 1079 T d2 = (*this + q).Length(); // Antipodal point check
nuclear@0 1080 return (d1 < d2) ? d1 : d2;
nuclear@0 1081 }
nuclear@0 1082
nuclear@0 1083 T DistanceSq(const Quat& q) const
nuclear@0 1084 {
nuclear@0 1085 T d1 = (*this - q).LengthSq();
nuclear@0 1086 T d2 = (*this + q).LengthSq(); // Antipodal point check
nuclear@0 1087 return (d1 < d2) ? d1 : d2;
nuclear@0 1088 }
nuclear@0 1089
nuclear@0 1090 T Dot(const Quat& q) const
nuclear@0 1091 {
nuclear@0 1092 return x * q.x + y * q.y + z * q.z + w * q.w;
nuclear@0 1093 }
nuclear@0 1094
nuclear@0 1095 // Angle between two quaternions in radians
nuclear@0 1096 T Angle(const Quat& q) const
nuclear@0 1097 {
nuclear@0 1098 return 2 * Acos(Alg::Abs(Dot(q)));
nuclear@0 1099 }
nuclear@0 1100
nuclear@0 1101 // Normalize
nuclear@0 1102 bool IsNormalized() const { return fabs(LengthSq() - T(1)) < ((T)MATH_DOUBLE_TOLERANCE); }
nuclear@0 1103
nuclear@0 1104 void Normalize()
nuclear@0 1105 {
nuclear@0 1106 T l = Length();
nuclear@0 1107 OVR_ASSERT(l != T(0));
nuclear@0 1108 *this /= l;
nuclear@0 1109 }
nuclear@0 1110
nuclear@0 1111 Quat Normalized() const
nuclear@0 1112 {
nuclear@0 1113 T l = Length();
nuclear@0 1114 OVR_ASSERT(l != T(0));
nuclear@0 1115 return *this / l;
nuclear@0 1116 }
nuclear@0 1117
nuclear@0 1118 // Returns conjugate of the quaternion. Produces inverse rotation if quaternion is normalized.
nuclear@0 1119 Quat Conj() const { return Quat(-x, -y, -z, w); }
nuclear@0 1120
nuclear@0 1121 // Quaternion multiplication. Combines quaternion rotations, performing the one on the
nuclear@0 1122 // right hand side first.
nuclear@0 1123 Quat operator* (const Quat& b) const { return Quat(w * b.x + x * b.w + y * b.z - z * b.y,
nuclear@0 1124 w * b.y - x * b.z + y * b.w + z * b.x,
nuclear@0 1125 w * b.z + x * b.y - y * b.x + z * b.w,
nuclear@0 1126 w * b.w - x * b.x - y * b.y - z * b.z); }
nuclear@0 1127
nuclear@0 1128 //
nuclear@0 1129 // this^p normalized; same as rotating by this p times.
nuclear@0 1130 Quat PowNormalized(T p) const
nuclear@0 1131 {
nuclear@0 1132 Vector3<T> v;
nuclear@0 1133 T a;
nuclear@0 1134 GetAxisAngle(&v, &a);
nuclear@0 1135 return Quat(v, a * p);
nuclear@0 1136 }
nuclear@0 1137
nuclear@0 1138 // Normalized linear interpolation of quaternions
nuclear@0 1139 Quat Nlerp(const Quat& other, T a)
nuclear@0 1140 {
nuclear@0 1141 T sign = (Dot(other) >= 0) ? 1 : -1;
nuclear@0 1142 return (*this * sign * a + other * (1-a)).Normalized();
nuclear@0 1143 }
nuclear@0 1144
nuclear@0 1145 // Rotate transforms vector in a manner that matches Matrix rotations (counter-clockwise,
nuclear@0 1146 // assuming negative direction of the axis). Standard formula: q(t) * V * q(t)^-1.
nuclear@0 1147 Vector3<T> Rotate(const Vector3<T>& v) const
nuclear@0 1148 {
nuclear@0 1149 return ((*this * Quat<T>(v.x, v.y, v.z, T(0))) * Inverted()).Imag();
nuclear@0 1150 }
nuclear@0 1151
nuclear@0 1152 // Inversed quaternion rotates in the opposite direction.
nuclear@0 1153 Quat Inverted() const
nuclear@0 1154 {
nuclear@0 1155 return Quat(-x, -y, -z, w);
nuclear@0 1156 }
nuclear@0 1157
nuclear@0 1158 // Sets this quaternion to the one rotates in the opposite direction.
nuclear@0 1159 void Invert()
nuclear@0 1160 {
nuclear@0 1161 *this = Quat(-x, -y, -z, w);
nuclear@0 1162 }
nuclear@0 1163
nuclear@0 1164 // GetEulerAngles extracts Euler angles from the quaternion, in the specified order of
nuclear@0 1165 // axis rotations and the specified coordinate system. Right-handed coordinate system
nuclear@0 1166 // is the default, with CCW rotations while looking in the negative axis direction.
nuclear@0 1167 // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned.
nuclear@0 1168 // rotation a around axis A1
nuclear@0 1169 // is followed by rotation b around axis A2
nuclear@0 1170 // is followed by rotation c around axis A3
nuclear@0 1171 // rotations are CCW or CW (D) in LH or RH coordinate system (S)
nuclear@0 1172 template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
nuclear@0 1173 void GetEulerAngles(T *a, T *b, T *c) const
nuclear@0 1174 {
nuclear@0 1175 static_assert((A1 != A2) && (A2 != A3) && (A1 != A3), "(A1 != A2) && (A2 != A3) && (A1 != A3)");
nuclear@0 1176
nuclear@0 1177 T Q[3] = { x, y, z }; //Quaternion components x,y,z
nuclear@0 1178
nuclear@0 1179 T ww = w*w;
nuclear@0 1180 T Q11 = Q[A1]*Q[A1];
nuclear@0 1181 T Q22 = Q[A2]*Q[A2];
nuclear@0 1182 T Q33 = Q[A3]*Q[A3];
nuclear@0 1183
nuclear@0 1184 T psign = T(-1);
nuclear@0 1185 // Determine whether even permutation
nuclear@0 1186 if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3))
nuclear@0 1187 psign = T(1);
nuclear@0 1188
nuclear@0 1189 T s2 = psign * T(2) * (psign*w*Q[A2] + Q[A1]*Q[A3]);
nuclear@0 1190
nuclear@0 1191 if (s2 < T(-1) + ((T)MATH_DOUBLE_SINGULARITYRADIUS))
nuclear@0 1192 { // South pole singularity
nuclear@0 1193 *a = T(0);
nuclear@0 1194 *b = -S*D*((T)MATH_DOUBLE_PIOVER2);
nuclear@0 1195 *c = S*D*atan2(T(2)*(psign*Q[A1]*Q[A2] + w*Q[A3]),
nuclear@0 1196 ww + Q22 - Q11 - Q33 );
nuclear@0 1197 }
nuclear@0 1198 else if (s2 > T(1) - ((T)MATH_DOUBLE_SINGULARITYRADIUS))
nuclear@0 1199 { // North pole singularity
nuclear@0 1200 *a = T(0);
nuclear@0 1201 *b = S*D*((T)MATH_DOUBLE_PIOVER2);
nuclear@0 1202 *c = S*D*atan2(T(2)*(psign*Q[A1]*Q[A2] + w*Q[A3]),
nuclear@0 1203 ww + Q22 - Q11 - Q33);
nuclear@0 1204 }
nuclear@0 1205 else
nuclear@0 1206 {
nuclear@0 1207 *a = -S*D*atan2(T(-2)*(w*Q[A1] - psign*Q[A2]*Q[A3]),
nuclear@0 1208 ww + Q33 - Q11 - Q22);
nuclear@0 1209 *b = S*D*asin(s2);
nuclear@0 1210 *c = S*D*atan2(T(2)*(w*Q[A3] - psign*Q[A1]*Q[A2]),
nuclear@0 1211 ww + Q11 - Q22 - Q33);
nuclear@0 1212 }
nuclear@0 1213 return;
nuclear@0 1214 }
nuclear@0 1215
nuclear@0 1216 template <Axis A1, Axis A2, Axis A3, RotateDirection D>
nuclear@0 1217 void GetEulerAngles(T *a, T *b, T *c) const
nuclear@0 1218 { GetEulerAngles<A1, A2, A3, D, Handed_R>(a, b, c); }
nuclear@0 1219
nuclear@0 1220 template <Axis A1, Axis A2, Axis A3>
nuclear@0 1221 void GetEulerAngles(T *a, T *b, T *c) const
nuclear@0 1222 { GetEulerAngles<A1, A2, A3, Rotate_CCW, Handed_R>(a, b, c); }
nuclear@0 1223
nuclear@0 1224 // GetEulerAnglesABA extracts Euler angles from the quaternion, in the specified order of
nuclear@0 1225 // axis rotations and the specified coordinate system. Right-handed coordinate system
nuclear@0 1226 // is the default, with CCW rotations while looking in the negative axis direction.
nuclear@0 1227 // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned.
nuclear@0 1228 // rotation a around axis A1
nuclear@0 1229 // is followed by rotation b around axis A2
nuclear@0 1230 // is followed by rotation c around axis A1
nuclear@0 1231 // Rotations are CCW or CW (D) in LH or RH coordinate system (S)
nuclear@0 1232 template <Axis A1, Axis A2, RotateDirection D, HandedSystem S>
nuclear@0 1233 void GetEulerAnglesABA(T *a, T *b, T *c) const
nuclear@0 1234 {
nuclear@0 1235 static_assert(A1 != A2, "A1 != A2");
nuclear@0 1236
nuclear@0 1237 T Q[3] = {x, y, z}; // Quaternion components
nuclear@0 1238
nuclear@0 1239 // Determine the missing axis that was not supplied
nuclear@0 1240 int m = 3 - A1 - A2;
nuclear@0 1241
nuclear@0 1242 T ww = w*w;
nuclear@0 1243 T Q11 = Q[A1]*Q[A1];
nuclear@0 1244 T Q22 = Q[A2]*Q[A2];
nuclear@0 1245 T Qmm = Q[m]*Q[m];
nuclear@0 1246
nuclear@0 1247 T psign = T(-1);
nuclear@0 1248 if ((A1 + 1) % 3 == A2) // Determine whether even permutation
nuclear@0 1249 {
nuclear@0 1250 psign = T(1);
nuclear@0 1251 }
nuclear@0 1252
nuclear@0 1253 T c2 = ww + Q11 - Q22 - Qmm;
nuclear@0 1254 if (c2 < T(-1) + Math<T>::SingularityRadius)
nuclear@0 1255 { // South pole singularity
nuclear@0 1256 *a = T(0);
nuclear@0 1257 *b = S*D*((T)MATH_DOUBLE_PI);
nuclear@0 1258 *c = S*D*atan2( T(2)*(w*Q[A1] - psign*Q[A2]*Q[m]),
nuclear@0 1259 ww + Q22 - Q11 - Qmm);
nuclear@0 1260 }
nuclear@0 1261 else if (c2 > T(1) - Math<T>::SingularityRadius)
nuclear@0 1262 { // North pole singularity
nuclear@0 1263 *a = T(0);
nuclear@0 1264 *b = T(0);
nuclear@0 1265 *c = S*D*atan2( T(2)*(w*Q[A1] - psign*Q[A2]*Q[m]),
nuclear@0 1266 ww + Q22 - Q11 - Qmm);
nuclear@0 1267 }
nuclear@0 1268 else
nuclear@0 1269 {
nuclear@0 1270 *a = S*D*atan2( psign*w*Q[m] + Q[A1]*Q[A2],
nuclear@0 1271 w*Q[A2] -psign*Q[A1]*Q[m]);
nuclear@0 1272 *b = S*D*acos(c2);
nuclear@0 1273 *c = S*D*atan2( -psign*w*Q[m] + Q[A1]*Q[A2],
nuclear@0 1274 w*Q[A2] + psign*Q[A1]*Q[m]);
nuclear@0 1275 }
nuclear@0 1276 return;
nuclear@0 1277 }
nuclear@0 1278 };
nuclear@0 1279
nuclear@0 1280 typedef Quat<float> Quatf;
nuclear@0 1281 typedef Quat<double> Quatd;
nuclear@0 1282
nuclear@0 1283 static_assert((sizeof(Quatf) == 4*sizeof(float)), "sizeof(Quatf) failure");
nuclear@0 1284 static_assert((sizeof(Quatd) == 4*sizeof(double)), "sizeof(Quatd) failure");
nuclear@0 1285
nuclear@0 1286 //-------------------------------------------------------------------------------------
nuclear@0 1287 // ***** Pose
nuclear@0 1288
nuclear@0 1289 // Position and orientation combined.
nuclear@0 1290
nuclear@0 1291 template<class T>
nuclear@0 1292 class Pose
nuclear@0 1293 {
nuclear@0 1294 public:
nuclear@0 1295 typedef typename CompatibleTypes<Pose<T> >::Type CompatibleType;
nuclear@0 1296
nuclear@0 1297 Pose() { }
nuclear@0 1298 Pose(const Quat<T>& orientation, const Vector3<T>& pos)
nuclear@0 1299 : Rotation(orientation), Translation(pos) { }
nuclear@0 1300 Pose(const Pose& s)
nuclear@0 1301 : Rotation(s.Rotation), Translation(s.Translation) { }
nuclear@0 1302 Pose(const CompatibleType& s)
nuclear@0 1303 : Rotation(s.Orientation), Translation(s.Position) { }
nuclear@0 1304 explicit Pose(const Pose<typename Math<T>::OtherFloatType> &s)
nuclear@0 1305 : Rotation(s.Rotation), Translation(s.Translation) { }
nuclear@0 1306
nuclear@0 1307 operator typename CompatibleTypes<Pose<T> >::Type () const
nuclear@0 1308 {
nuclear@0 1309 typename CompatibleTypes<Pose<T> >::Type result;
nuclear@0 1310 result.Orientation = Rotation;
nuclear@0 1311 result.Position = Translation;
nuclear@0 1312 return result;
nuclear@0 1313 }
nuclear@0 1314
nuclear@0 1315 Quat<T> Rotation;
nuclear@0 1316 Vector3<T> Translation;
nuclear@0 1317
nuclear@0 1318 static_assert((sizeof(T) == sizeof(double) || sizeof(T) == sizeof(float)), "(sizeof(T) == sizeof(double) || sizeof(T) == sizeof(float))");
nuclear@0 1319
nuclear@0 1320 void ToArray(T* arr) const
nuclear@0 1321 {
nuclear@0 1322 T temp[7] = { Rotation.x, Rotation.y, Rotation.z, Rotation.w, Translation.x, Translation.y, Translation.z };
nuclear@0 1323 for (int i = 0; i < 7; i++) arr[i] = temp[i];
nuclear@0 1324 }
nuclear@0 1325
nuclear@0 1326 static Pose<T> FromArray(const T* v)
nuclear@0 1327 {
nuclear@0 1328 Quat<T> rotation(v[0], v[1], v[2], v[3]);
nuclear@0 1329 Vector3<T> translation(v[4], v[5], v[6]);
nuclear@0 1330 return Pose<T>(rotation, translation);
nuclear@0 1331 }
nuclear@0 1332
nuclear@0 1333 Vector3<T> Rotate(const Vector3<T>& v) const
nuclear@0 1334 {
nuclear@0 1335 return Rotation.Rotate(v);
nuclear@0 1336 }
nuclear@0 1337
nuclear@0 1338 Vector3<T> Translate(const Vector3<T>& v) const
nuclear@0 1339 {
nuclear@0 1340 return v + Translation;
nuclear@0 1341 }
nuclear@0 1342
nuclear@0 1343 Vector3<T> Apply(const Vector3<T>& v) const
nuclear@0 1344 {
nuclear@0 1345 return Translate(Rotate(v));
nuclear@0 1346 }
nuclear@0 1347
nuclear@0 1348 Pose operator*(const Pose& other) const
nuclear@0 1349 {
nuclear@0 1350 return Pose(Rotation * other.Rotation, Apply(other.Translation));
nuclear@0 1351 }
nuclear@0 1352
nuclear@0 1353 Pose Inverted() const
nuclear@0 1354 {
nuclear@0 1355 Quat<T> inv = Rotation.Inverted();
nuclear@0 1356 return Pose(inv, inv.Rotate(-Translation));
nuclear@0 1357 }
nuclear@0 1358 };
nuclear@0 1359
nuclear@0 1360 typedef Pose<float> Posef;
nuclear@0 1361 typedef Pose<double> Posed;
nuclear@0 1362
nuclear@0 1363 static_assert((sizeof(Posed) == sizeof(Quatd) + sizeof(Vector3d)), "sizeof(Posed) failure");
nuclear@0 1364 static_assert((sizeof(Posef) == sizeof(Quatf) + sizeof(Vector3f)), "sizeof(Posef) failure");
nuclear@0 1365
nuclear@0 1366
nuclear@0 1367 //-------------------------------------------------------------------------------------
nuclear@0 1368 // ***** Matrix4
nuclear@0 1369 //
nuclear@0 1370 // Matrix4 is a 4x4 matrix used for 3d transformations and projections.
nuclear@0 1371 // Translation stored in the last column.
nuclear@0 1372 // The matrix is stored in row-major order in memory, meaning that values
nuclear@0 1373 // of the first row are stored before the next one.
nuclear@0 1374 //
nuclear@0 1375 // The arrangement of the matrix is chosen to be in Right-Handed
nuclear@0 1376 // coordinate system and counterclockwise rotations when looking down
nuclear@0 1377 // the axis
nuclear@0 1378 //
nuclear@0 1379 // Transformation Order:
nuclear@0 1380 // - Transformations are applied from right to left, so the expression
nuclear@0 1381 // M1 * M2 * M3 * V means that the vector V is transformed by M3 first,
nuclear@0 1382 // followed by M2 and M1.
nuclear@0 1383 //
nuclear@0 1384 // Coordinate system: Right Handed
nuclear@0 1385 //
nuclear@0 1386 // Rotations: Counterclockwise when looking down the axis. All angles are in radians.
nuclear@0 1387 //
nuclear@0 1388 // | sx 01 02 tx | // First column (sx, 10, 20): Axis X basis vector.
nuclear@0 1389 // | 10 sy 12 ty | // Second column (01, sy, 21): Axis Y basis vector.
nuclear@0 1390 // | 20 21 sz tz | // Third columnt (02, 12, sz): Axis Z basis vector.
nuclear@0 1391 // | 30 31 32 33 |
nuclear@0 1392 //
nuclear@0 1393 // The basis vectors are first three columns.
nuclear@0 1394
nuclear@0 1395 template<class T>
nuclear@0 1396 class Matrix4
nuclear@0 1397 {
nuclear@0 1398 static const Matrix4 IdentityValue;
nuclear@0 1399
nuclear@0 1400 public:
nuclear@0 1401 T M[4][4];
nuclear@0 1402
nuclear@0 1403 enum NoInitType { NoInit };
nuclear@0 1404
nuclear@0 1405 // Construct with no memory initialization.
nuclear@0 1406 Matrix4(NoInitType) { }
nuclear@0 1407
nuclear@0 1408 // By default, we construct identity matrix.
nuclear@0 1409 Matrix4()
nuclear@0 1410 {
nuclear@0 1411 SetIdentity();
nuclear@0 1412 }
nuclear@0 1413
nuclear@0 1414 Matrix4(T m11, T m12, T m13, T m14,
nuclear@0 1415 T m21, T m22, T m23, T m24,
nuclear@0 1416 T m31, T m32, T m33, T m34,
nuclear@0 1417 T m41, T m42, T m43, T m44)
nuclear@0 1418 {
nuclear@0 1419 M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = m14;
nuclear@0 1420 M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = m24;
nuclear@0 1421 M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = m34;
nuclear@0 1422 M[3][0] = m41; M[3][1] = m42; M[3][2] = m43; M[3][3] = m44;
nuclear@0 1423 }
nuclear@0 1424
nuclear@0 1425 Matrix4(T m11, T m12, T m13,
nuclear@0 1426 T m21, T m22, T m23,
nuclear@0 1427 T m31, T m32, T m33)
nuclear@0 1428 {
nuclear@0 1429 M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = 0;
nuclear@0 1430 M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = 0;
nuclear@0 1431 M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = 0;
nuclear@0 1432 M[3][0] = 0; M[3][1] = 0; M[3][2] = 0; M[3][3] = 1;
nuclear@0 1433 }
nuclear@0 1434
nuclear@0 1435 explicit Matrix4(const Quat<T>& q)
nuclear@0 1436 {
nuclear@0 1437 T ww = q.w*q.w;
nuclear@0 1438 T xx = q.x*q.x;
nuclear@0 1439 T yy = q.y*q.y;
nuclear@0 1440 T zz = q.z*q.z;
nuclear@0 1441
nuclear@0 1442 M[0][0] = ww + xx - yy - zz; M[0][1] = 2 * (q.x*q.y - q.w*q.z); M[0][2] = 2 * (q.x*q.z + q.w*q.y); M[0][3] = 0;
nuclear@0 1443 M[1][0] = 2 * (q.x*q.y + q.w*q.z); M[1][1] = ww - xx + yy - zz; M[1][2] = 2 * (q.y*q.z - q.w*q.x); M[1][3] = 0;
nuclear@0 1444 M[2][0] = 2 * (q.x*q.z - q.w*q.y); M[2][1] = 2 * (q.y*q.z + q.w*q.x); M[2][2] = ww - xx - yy + zz; M[2][3] = 0;
nuclear@0 1445 M[3][0] = 0; M[3][1] = 0; M[3][2] = 0; M[3][3] = 1;
nuclear@0 1446 }
nuclear@0 1447
nuclear@0 1448 explicit Matrix4(const Pose<T>& p)
nuclear@0 1449 {
nuclear@0 1450 Matrix4 result(p.Rotation);
nuclear@0 1451 result.SetTranslation(p.Translation);
nuclear@0 1452 *this = result;
nuclear@0 1453 }
nuclear@0 1454
nuclear@0 1455 // C-interop support
nuclear@0 1456 explicit Matrix4(const Matrix4<typename Math<T>::OtherFloatType> &src)
nuclear@0 1457 {
nuclear@0 1458 for (int i = 0; i < 4; i++)
nuclear@0 1459 for (int j = 0; j < 4; j++)
nuclear@0 1460 M[i][j] = (T)src.M[i][j];
nuclear@0 1461 }
nuclear@0 1462
nuclear@0 1463 // C-interop support.
nuclear@0 1464 Matrix4(const typename CompatibleTypes<Matrix4<T> >::Type& s)
nuclear@0 1465 {
nuclear@0 1466 static_assert(sizeof(s) == sizeof(Matrix4), "sizeof(s) == sizeof(Matrix4)");
nuclear@0 1467 memcpy(M, s.M, sizeof(M));
nuclear@0 1468 }
nuclear@0 1469
nuclear@0 1470 operator typename CompatibleTypes<Matrix4<T> >::Type () const
nuclear@0 1471 {
nuclear@0 1472 typename CompatibleTypes<Matrix4<T> >::Type result;
nuclear@0 1473 static_assert(sizeof(result) == sizeof(Matrix4), "sizeof(result) == sizeof(Matrix4)");
nuclear@0 1474 memcpy(result.M, M, sizeof(M));
nuclear@0 1475 return result;
nuclear@0 1476 }
nuclear@0 1477
nuclear@0 1478 void ToString(char* dest, size_t destsize) const
nuclear@0 1479 {
nuclear@0 1480 size_t pos = 0;
nuclear@0 1481 for (int r=0; r<4; r++)
nuclear@0 1482 for (int c=0; c<4; c++)
nuclear@0 1483 pos += OVR_sprintf(dest+pos, destsize-pos, "%g ", M[r][c]);
nuclear@0 1484 }
nuclear@0 1485
nuclear@0 1486 static Matrix4 FromString(const char* src)
nuclear@0 1487 {
nuclear@0 1488 Matrix4 result;
nuclear@0 1489 if (src)
nuclear@0 1490 {
nuclear@0 1491 for (int r=0; r<4; r++)
nuclear@0 1492 {
nuclear@0 1493 for (int c=0; c<4; c++)
nuclear@0 1494 {
nuclear@0 1495 result.M[r][c] = (T)atof(src);
nuclear@0 1496 while (src && *src != ' ')
nuclear@0 1497 {
nuclear@0 1498 src++;
nuclear@0 1499 }
nuclear@0 1500 while (src && *src == ' ')
nuclear@0 1501 {
nuclear@0 1502 src++;
nuclear@0 1503 }
nuclear@0 1504 }
nuclear@0 1505 }
nuclear@0 1506 }
nuclear@0 1507 return result;
nuclear@0 1508 }
nuclear@0 1509
nuclear@0 1510 static const Matrix4& Identity() { return IdentityValue; }
nuclear@0 1511
nuclear@0 1512 void SetIdentity()
nuclear@0 1513 {
nuclear@0 1514 M[0][0] = M[1][1] = M[2][2] = M[3][3] = 1;
nuclear@0 1515 M[0][1] = M[1][0] = M[2][3] = M[3][1] = 0;
nuclear@0 1516 M[0][2] = M[1][2] = M[2][0] = M[3][2] = 0;
nuclear@0 1517 M[0][3] = M[1][3] = M[2][1] = M[3][0] = 0;
nuclear@0 1518 }
nuclear@0 1519
nuclear@0 1520 void SetXBasis(const Vector3f & v)
nuclear@0 1521 {
nuclear@0 1522 M[0][0] = v.x;
nuclear@0 1523 M[1][0] = v.y;
nuclear@0 1524 M[2][0] = v.z;
nuclear@0 1525 }
nuclear@0 1526 Vector3f GetXBasis() const
nuclear@0 1527 {
nuclear@0 1528 return Vector3f(M[0][0], M[1][0], M[2][0]);
nuclear@0 1529 }
nuclear@0 1530
nuclear@0 1531 void SetYBasis(const Vector3f & v)
nuclear@0 1532 {
nuclear@0 1533 M[0][1] = v.x;
nuclear@0 1534 M[1][1] = v.y;
nuclear@0 1535 M[2][1] = v.z;
nuclear@0 1536 }
nuclear@0 1537 Vector3f GetYBasis() const
nuclear@0 1538 {
nuclear@0 1539 return Vector3f(M[0][1], M[1][1], M[2][1]);
nuclear@0 1540 }
nuclear@0 1541
nuclear@0 1542 void SetZBasis(const Vector3f & v)
nuclear@0 1543 {
nuclear@0 1544 M[0][2] = v.x;
nuclear@0 1545 M[1][2] = v.y;
nuclear@0 1546 M[2][2] = v.z;
nuclear@0 1547 }
nuclear@0 1548 Vector3f GetZBasis() const
nuclear@0 1549 {
nuclear@0 1550 return Vector3f(M[0][2], M[1][2], M[2][2]);
nuclear@0 1551 }
nuclear@0 1552
nuclear@0 1553 bool operator== (const Matrix4& b) const
nuclear@0 1554 {
nuclear@0 1555 bool isEqual = true;
nuclear@0 1556 for (int i = 0; i < 4; i++)
nuclear@0 1557 for (int j = 0; j < 4; j++)
nuclear@0 1558 isEqual &= (M[i][j] == b.M[i][j]);
nuclear@0 1559
nuclear@0 1560 return isEqual;
nuclear@0 1561 }
nuclear@0 1562
nuclear@0 1563 Matrix4 operator+ (const Matrix4& b) const
nuclear@0 1564 {
nuclear@0 1565 Matrix4 result(*this);
nuclear@0 1566 result += b;
nuclear@0 1567 return result;
nuclear@0 1568 }
nuclear@0 1569
nuclear@0 1570 Matrix4& operator+= (const Matrix4& b)
nuclear@0 1571 {
nuclear@0 1572 for (int i = 0; i < 4; i++)
nuclear@0 1573 for (int j = 0; j < 4; j++)
nuclear@0 1574 M[i][j] += b.M[i][j];
nuclear@0 1575 return *this;
nuclear@0 1576 }
nuclear@0 1577
nuclear@0 1578 Matrix4 operator- (const Matrix4& b) const
nuclear@0 1579 {
nuclear@0 1580 Matrix4 result(*this);
nuclear@0 1581 result -= b;
nuclear@0 1582 return result;
nuclear@0 1583 }
nuclear@0 1584
nuclear@0 1585 Matrix4& operator-= (const Matrix4& b)
nuclear@0 1586 {
nuclear@0 1587 for (int i = 0; i < 4; i++)
nuclear@0 1588 for (int j = 0; j < 4; j++)
nuclear@0 1589 M[i][j] -= b.M[i][j];
nuclear@0 1590 return *this;
nuclear@0 1591 }
nuclear@0 1592
nuclear@0 1593 // Multiplies two matrices into destination with minimum copying.
nuclear@0 1594 static Matrix4& Multiply(Matrix4* d, const Matrix4& a, const Matrix4& b)
nuclear@0 1595 {
nuclear@0 1596 OVR_ASSERT((d != &a) && (d != &b));
nuclear@0 1597 int i = 0;
nuclear@0 1598 do {
nuclear@0 1599 d->M[i][0] = a.M[i][0] * b.M[0][0] + a.M[i][1] * b.M[1][0] + a.M[i][2] * b.M[2][0] + a.M[i][3] * b.M[3][0];
nuclear@0 1600 d->M[i][1] = a.M[i][0] * b.M[0][1] + a.M[i][1] * b.M[1][1] + a.M[i][2] * b.M[2][1] + a.M[i][3] * b.M[3][1];
nuclear@0 1601 d->M[i][2] = a.M[i][0] * b.M[0][2] + a.M[i][1] * b.M[1][2] + a.M[i][2] * b.M[2][2] + a.M[i][3] * b.M[3][2];
nuclear@0 1602 d->M[i][3] = a.M[i][0] * b.M[0][3] + a.M[i][1] * b.M[1][3] + a.M[i][2] * b.M[2][3] + a.M[i][3] * b.M[3][3];
nuclear@0 1603 } while((++i) < 4);
nuclear@0 1604
nuclear@0 1605 return *d;
nuclear@0 1606 }
nuclear@0 1607
nuclear@0 1608 Matrix4 operator* (const Matrix4& b) const
nuclear@0 1609 {
nuclear@0 1610 Matrix4 result(Matrix4::NoInit);
nuclear@0 1611 Multiply(&result, *this, b);
nuclear@0 1612 return result;
nuclear@0 1613 }
nuclear@0 1614
nuclear@0 1615 Matrix4& operator*= (const Matrix4& b)
nuclear@0 1616 {
nuclear@0 1617 return Multiply(this, Matrix4(*this), b);
nuclear@0 1618 }
nuclear@0 1619
nuclear@0 1620 Matrix4 operator* (T s) const
nuclear@0 1621 {
nuclear@0 1622 Matrix4 result(*this);
nuclear@0 1623 result *= s;
nuclear@0 1624 return result;
nuclear@0 1625 }
nuclear@0 1626
nuclear@0 1627 Matrix4& operator*= (T s)
nuclear@0 1628 {
nuclear@0 1629 for (int i = 0; i < 4; i++)
nuclear@0 1630 for (int j = 0; j < 4; j++)
nuclear@0 1631 M[i][j] *= s;
nuclear@0 1632 return *this;
nuclear@0 1633 }
nuclear@0 1634
nuclear@0 1635
nuclear@0 1636 Matrix4 operator/ (T s) const
nuclear@0 1637 {
nuclear@0 1638 Matrix4 result(*this);
nuclear@0 1639 result /= s;
nuclear@0 1640 return result;
nuclear@0 1641 }
nuclear@0 1642
nuclear@0 1643 Matrix4& operator/= (T s)
nuclear@0 1644 {
nuclear@0 1645 for (int i = 0; i < 4; i++)
nuclear@0 1646 for (int j = 0; j < 4; j++)
nuclear@0 1647 M[i][j] /= s;
nuclear@0 1648 return *this;
nuclear@0 1649 }
nuclear@0 1650
nuclear@0 1651 Vector3<T> Transform(const Vector3<T>& v) const
nuclear@0 1652 {
nuclear@0 1653 const T rcpW = 1.0f / (M[3][0] * v.x + M[3][1] * v.y + M[3][2] * v.z + M[3][3]);
nuclear@0 1654 return Vector3<T>((M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3]) * rcpW,
nuclear@0 1655 (M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3]) * rcpW,
nuclear@0 1656 (M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3]) * rcpW);
nuclear@0 1657 }
nuclear@0 1658
nuclear@0 1659 Vector4<T> Transform(const Vector4<T>& v) const
nuclear@0 1660 {
nuclear@0 1661 return Vector4<T>(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3] * v.w,
nuclear@0 1662 M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3] * v.w,
nuclear@0 1663 M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3] * v.w,
nuclear@0 1664 M[3][0] * v.x + M[3][1] * v.y + M[3][2] * v.z + M[3][3] * v.w);
nuclear@0 1665 }
nuclear@0 1666
nuclear@0 1667 Matrix4 Transposed() const
nuclear@0 1668 {
nuclear@0 1669 return Matrix4(M[0][0], M[1][0], M[2][0], M[3][0],
nuclear@0 1670 M[0][1], M[1][1], M[2][1], M[3][1],
nuclear@0 1671 M[0][2], M[1][2], M[2][2], M[3][2],
nuclear@0 1672 M[0][3], M[1][3], M[2][3], M[3][3]);
nuclear@0 1673 }
nuclear@0 1674
nuclear@0 1675 void Transpose()
nuclear@0 1676 {
nuclear@0 1677 *this = Transposed();
nuclear@0 1678 }
nuclear@0 1679
nuclear@0 1680
nuclear@0 1681 T SubDet (const size_t* rows, const size_t* cols) const
nuclear@0 1682 {
nuclear@0 1683 return M[rows[0]][cols[0]] * (M[rows[1]][cols[1]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[1]])
nuclear@0 1684 - M[rows[0]][cols[1]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[0]])
nuclear@0 1685 + M[rows[0]][cols[2]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[1]] - M[rows[1]][cols[1]] * M[rows[2]][cols[0]]);
nuclear@0 1686 }
nuclear@0 1687
nuclear@0 1688 T Cofactor(size_t I, size_t J) const
nuclear@0 1689 {
nuclear@0 1690 const size_t indices[4][3] = {{1,2,3},{0,2,3},{0,1,3},{0,1,2}};
nuclear@0 1691 return ((I+J)&1) ? -SubDet(indices[I],indices[J]) : SubDet(indices[I],indices[J]);
nuclear@0 1692 }
nuclear@0 1693
nuclear@0 1694 T Determinant() const
nuclear@0 1695 {
nuclear@0 1696 return M[0][0] * Cofactor(0,0) + M[0][1] * Cofactor(0,1) + M[0][2] * Cofactor(0,2) + M[0][3] * Cofactor(0,3);
nuclear@0 1697 }
nuclear@0 1698
nuclear@0 1699 Matrix4 Adjugated() const
nuclear@0 1700 {
nuclear@0 1701 return Matrix4(Cofactor(0,0), Cofactor(1,0), Cofactor(2,0), Cofactor(3,0),
nuclear@0 1702 Cofactor(0,1), Cofactor(1,1), Cofactor(2,1), Cofactor(3,1),
nuclear@0 1703 Cofactor(0,2), Cofactor(1,2), Cofactor(2,2), Cofactor(3,2),
nuclear@0 1704 Cofactor(0,3), Cofactor(1,3), Cofactor(2,3), Cofactor(3,3));
nuclear@0 1705 }
nuclear@0 1706
nuclear@0 1707 Matrix4 Inverted() const
nuclear@0 1708 {
nuclear@0 1709 T det = Determinant();
nuclear@0 1710 assert(det != 0);
nuclear@0 1711 return Adjugated() * (1.0f/det);
nuclear@0 1712 }
nuclear@0 1713
nuclear@0 1714 void Invert()
nuclear@0 1715 {
nuclear@0 1716 *this = Inverted();
nuclear@0 1717 }
nuclear@0 1718
nuclear@0 1719 // This is more efficient than general inverse, but ONLY works
nuclear@0 1720 // correctly if it is a homogeneous transform matrix (rot + trans)
nuclear@0 1721 Matrix4 InvertedHomogeneousTransform() const
nuclear@0 1722 {
nuclear@0 1723 // Make the inverse rotation matrix
nuclear@0 1724 Matrix4 rinv = this->Transposed();
nuclear@0 1725 rinv.M[3][0] = rinv.M[3][1] = rinv.M[3][2] = 0.0f;
nuclear@0 1726 // Make the inverse translation matrix
nuclear@0 1727 Vector3<T> tvinv(-M[0][3],-M[1][3],-M[2][3]);
nuclear@0 1728 Matrix4 tinv = Matrix4::Translation(tvinv);
nuclear@0 1729 return rinv * tinv; // "untranslate", then "unrotate"
nuclear@0 1730 }
nuclear@0 1731
nuclear@0 1732 // This is more efficient than general inverse, but ONLY works
nuclear@0 1733 // correctly if it is a homogeneous transform matrix (rot + trans)
nuclear@0 1734 void InvertHomogeneousTransform()
nuclear@0 1735 {
nuclear@0 1736 *this = InvertedHomogeneousTransform();
nuclear@0 1737 }
nuclear@0 1738
nuclear@0 1739 // Matrix to Euler Angles conversion
nuclear@0 1740 // a,b,c, are the YawPitchRoll angles to be returned
nuclear@0 1741 // rotation a around axis A1
nuclear@0 1742 // is followed by rotation b around axis A2
nuclear@0 1743 // is followed by rotation c around axis A3
nuclear@0 1744 // rotations are CCW or CW (D) in LH or RH coordinate system (S)
nuclear@0 1745 template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
nuclear@0 1746 void ToEulerAngles(T *a, T *b, T *c) const
nuclear@0 1747 {
nuclear@0 1748 static_assert((A1 != A2) && (A2 != A3) && (A1 != A3), "(A1 != A2) && (A2 != A3) && (A1 != A3)");
nuclear@0 1749
nuclear@0 1750 T psign = -1;
nuclear@0 1751 if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) // Determine whether even permutation
nuclear@0 1752 psign = 1;
nuclear@0 1753
nuclear@0 1754 T pm = psign*M[A1][A3];
nuclear@0 1755 if (pm < -1.0f + Math<T>::SingularityRadius)
nuclear@0 1756 { // South pole singularity
nuclear@0 1757 *a = 0;
nuclear@0 1758 *b = -S*D*((T)MATH_DOUBLE_PIOVER2);
nuclear@0 1759 *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] );
nuclear@0 1760 }
nuclear@0 1761 else if (pm > 1.0f - Math<T>::SingularityRadius)
nuclear@0 1762 { // North pole singularity
nuclear@0 1763 *a = 0;
nuclear@0 1764 *b = S*D*((T)MATH_DOUBLE_PIOVER2);
nuclear@0 1765 *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] );
nuclear@0 1766 }
nuclear@0 1767 else
nuclear@0 1768 { // Normal case (nonsingular)
nuclear@0 1769 *a = S*D*atan2( -psign*M[A2][A3], M[A3][A3] );
nuclear@0 1770 *b = S*D*asin(pm);
nuclear@0 1771 *c = S*D*atan2( -psign*M[A1][A2], M[A1][A1] );
nuclear@0 1772 }
nuclear@0 1773
nuclear@0 1774 return;
nuclear@0 1775 }
nuclear@0 1776
nuclear@0 1777 // Matrix to Euler Angles conversion
nuclear@0 1778 // a,b,c, are the YawPitchRoll angles to be returned
nuclear@0 1779 // rotation a around axis A1
nuclear@0 1780 // is followed by rotation b around axis A2
nuclear@0 1781 // is followed by rotation c around axis A1
nuclear@0 1782 // rotations are CCW or CW (D) in LH or RH coordinate system (S)
nuclear@0 1783 template <Axis A1, Axis A2, RotateDirection D, HandedSystem S>
nuclear@0 1784 void ToEulerAnglesABA(T *a, T *b, T *c) const
nuclear@0 1785 {
nuclear@0 1786 static_assert(A1 != A2, "A1 != A2");
nuclear@0 1787
nuclear@0 1788 // Determine the axis that was not supplied
nuclear@0 1789 int m = 3 - A1 - A2;
nuclear@0 1790
nuclear@0 1791 T psign = -1;
nuclear@0 1792 if ((A1 + 1) % 3 == A2) // Determine whether even permutation
nuclear@0 1793 psign = 1.0f;
nuclear@0 1794
nuclear@0 1795 T c2 = M[A1][A1];
nuclear@0 1796 if (c2 < -1 + Math<T>::SingularityRadius)
nuclear@0 1797 { // South pole singularity
nuclear@0 1798 *a = 0;
nuclear@0 1799 *b = S*D*((T)MATH_DOUBLE_PI);
nuclear@0 1800 *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]);
nuclear@0 1801 }
nuclear@0 1802 else if (c2 > 1.0f - Math<T>::SingularityRadius)
nuclear@0 1803 { // North pole singularity
nuclear@0 1804 *a = 0;
nuclear@0 1805 *b = 0;
nuclear@0 1806 *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]);
nuclear@0 1807 }
nuclear@0 1808 else
nuclear@0 1809 { // Normal case (nonsingular)
nuclear@0 1810 *a = S*D*atan2( M[A2][A1],-psign*M[m][A1]);
nuclear@0 1811 *b = S*D*acos(c2);
nuclear@0 1812 *c = S*D*atan2( M[A1][A2],psign*M[A1][m]);
nuclear@0 1813 }
nuclear@0 1814 return;
nuclear@0 1815 }
nuclear@0 1816
nuclear@0 1817 // Creates a matrix that converts the vertices from one coordinate system
nuclear@0 1818 // to another.
nuclear@0 1819 static Matrix4 AxisConversion(const WorldAxes& to, const WorldAxes& from)
nuclear@0 1820 {
nuclear@0 1821 // Holds axis values from the 'to' structure
nuclear@0 1822 int toArray[3] = { to.XAxis, to.YAxis, to.ZAxis };
nuclear@0 1823
nuclear@0 1824 // The inverse of the toArray
nuclear@0 1825 int inv[4];
nuclear@0 1826 inv[0] = inv[abs(to.XAxis)] = 0;
nuclear@0 1827 inv[abs(to.YAxis)] = 1;
nuclear@0 1828 inv[abs(to.ZAxis)] = 2;
nuclear@0 1829
nuclear@0 1830 Matrix4 m(0, 0, 0,
nuclear@0 1831 0, 0, 0,
nuclear@0 1832 0, 0, 0);
nuclear@0 1833
nuclear@0 1834 // Only three values in the matrix need to be changed to 1 or -1.
nuclear@0 1835 m.M[inv[abs(from.XAxis)]][0] = T(from.XAxis/toArray[inv[abs(from.XAxis)]]);
nuclear@0 1836 m.M[inv[abs(from.YAxis)]][1] = T(from.YAxis/toArray[inv[abs(from.YAxis)]]);
nuclear@0 1837 m.M[inv[abs(from.ZAxis)]][2] = T(from.ZAxis/toArray[inv[abs(from.ZAxis)]]);
nuclear@0 1838 return m;
nuclear@0 1839 }
nuclear@0 1840
nuclear@0 1841
nuclear@0 1842 // Creates a matrix for translation by vector
nuclear@0 1843 static Matrix4 Translation(const Vector3<T>& v)
nuclear@0 1844 {
nuclear@0 1845 Matrix4 t;
nuclear@0 1846 t.M[0][3] = v.x;
nuclear@0 1847 t.M[1][3] = v.y;
nuclear@0 1848 t.M[2][3] = v.z;
nuclear@0 1849 return t;
nuclear@0 1850 }
nuclear@0 1851
nuclear@0 1852 // Creates a matrix for translation by vector
nuclear@0 1853 static Matrix4 Translation(T x, T y, T z = 0.0f)
nuclear@0 1854 {
nuclear@0 1855 Matrix4 t;
nuclear@0 1856 t.M[0][3] = x;
nuclear@0 1857 t.M[1][3] = y;
nuclear@0 1858 t.M[2][3] = z;
nuclear@0 1859 return t;
nuclear@0 1860 }
nuclear@0 1861
nuclear@0 1862 // Sets the translation part
nuclear@0 1863 void SetTranslation(const Vector3<T>& v)
nuclear@0 1864 {
nuclear@0 1865 M[0][3] = v.x;
nuclear@0 1866 M[1][3] = v.y;
nuclear@0 1867 M[2][3] = v.z;
nuclear@0 1868 }
nuclear@0 1869
nuclear@0 1870 Vector3<T> GetTranslation() const
nuclear@0 1871 {
nuclear@0 1872 return Vector3<T>( M[0][3], M[1][3], M[2][3] );
nuclear@0 1873 }
nuclear@0 1874
nuclear@0 1875 // Creates a matrix for scaling by vector
nuclear@0 1876 static Matrix4 Scaling(const Vector3<T>& v)
nuclear@0 1877 {
nuclear@0 1878 Matrix4 t;
nuclear@0 1879 t.M[0][0] = v.x;
nuclear@0 1880 t.M[1][1] = v.y;
nuclear@0 1881 t.M[2][2] = v.z;
nuclear@0 1882 return t;
nuclear@0 1883 }
nuclear@0 1884
nuclear@0 1885 // Creates a matrix for scaling by vector
nuclear@0 1886 static Matrix4 Scaling(T x, T y, T z)
nuclear@0 1887 {
nuclear@0 1888 Matrix4 t;
nuclear@0 1889 t.M[0][0] = x;
nuclear@0 1890 t.M[1][1] = y;
nuclear@0 1891 t.M[2][2] = z;
nuclear@0 1892 return t;
nuclear@0 1893 }
nuclear@0 1894
nuclear@0 1895 // Creates a matrix for scaling by constant
nuclear@0 1896 static Matrix4 Scaling(T s)
nuclear@0 1897 {
nuclear@0 1898 Matrix4 t;
nuclear@0 1899 t.M[0][0] = s;
nuclear@0 1900 t.M[1][1] = s;
nuclear@0 1901 t.M[2][2] = s;
nuclear@0 1902 return t;
nuclear@0 1903 }
nuclear@0 1904
nuclear@0 1905 // Simple L1 distance in R^12
nuclear@0 1906 T Distance(const Matrix4& m2) const
nuclear@0 1907 {
nuclear@0 1908 T d = fabs(M[0][0] - m2.M[0][0]) + fabs(M[0][1] - m2.M[0][1]);
nuclear@0 1909 d += fabs(M[0][2] - m2.M[0][2]) + fabs(M[0][3] - m2.M[0][3]);
nuclear@0 1910 d += fabs(M[1][0] - m2.M[1][0]) + fabs(M[1][1] - m2.M[1][1]);
nuclear@0 1911 d += fabs(M[1][2] - m2.M[1][2]) + fabs(M[1][3] - m2.M[1][3]);
nuclear@0 1912 d += fabs(M[2][0] - m2.M[2][0]) + fabs(M[2][1] - m2.M[2][1]);
nuclear@0 1913 d += fabs(M[2][2] - m2.M[2][2]) + fabs(M[2][3] - m2.M[2][3]);
nuclear@0 1914 d += fabs(M[3][0] - m2.M[3][0]) + fabs(M[3][1] - m2.M[3][1]);
nuclear@0 1915 d += fabs(M[3][2] - m2.M[3][2]) + fabs(M[3][3] - m2.M[3][3]);
nuclear@0 1916 return d;
nuclear@0 1917 }
nuclear@0 1918
nuclear@0 1919 // Creates a rotation matrix rotating around the X axis by 'angle' radians.
nuclear@0 1920 // Just for quick testing. Not for final API. Need to remove case.
nuclear@0 1921 static Matrix4 RotationAxis(Axis A, T angle, RotateDirection d, HandedSystem s)
nuclear@0 1922 {
nuclear@0 1923 T sina = s * d *sin(angle);
nuclear@0 1924 T cosa = cos(angle);
nuclear@0 1925
nuclear@0 1926 switch(A)
nuclear@0 1927 {
nuclear@0 1928 case Axis_X:
nuclear@0 1929 return Matrix4(1, 0, 0,
nuclear@0 1930 0, cosa, -sina,
nuclear@0 1931 0, sina, cosa);
nuclear@0 1932 case Axis_Y:
nuclear@0 1933 return Matrix4(cosa, 0, sina,
nuclear@0 1934 0, 1, 0,
nuclear@0 1935 -sina, 0, cosa);
nuclear@0 1936 case Axis_Z:
nuclear@0 1937 return Matrix4(cosa, -sina, 0,
nuclear@0 1938 sina, cosa, 0,
nuclear@0 1939 0, 0, 1);
nuclear@0 1940 }
nuclear@0 1941 }
nuclear@0 1942
nuclear@0 1943
nuclear@0 1944 // Creates a rotation matrix rotating around the X axis by 'angle' radians.
nuclear@0 1945 // Rotation direction is depends on the coordinate system:
nuclear@0 1946 // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW),
nuclear@0 1947 // while looking in the negative axis direction. This is the
nuclear@0 1948 // same as looking down from positive axis values towards origin.
nuclear@0 1949 // LHS: Positive angle values rotate clock-wise (CW), while looking in the
nuclear@0 1950 // negative axis direction.
nuclear@0 1951 static Matrix4 RotationX(T angle)
nuclear@0 1952 {
nuclear@0 1953 T sina = sin(angle);
nuclear@0 1954 T cosa = cos(angle);
nuclear@0 1955 return Matrix4(1, 0, 0,
nuclear@0 1956 0, cosa, -sina,
nuclear@0 1957 0, sina, cosa);
nuclear@0 1958 }
nuclear@0 1959
nuclear@0 1960 // Creates a rotation matrix rotating around the Y axis by 'angle' radians.
nuclear@0 1961 // Rotation direction is depends on the coordinate system:
nuclear@0 1962 // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW),
nuclear@0 1963 // while looking in the negative axis direction. This is the
nuclear@0 1964 // same as looking down from positive axis values towards origin.
nuclear@0 1965 // LHS: Positive angle values rotate clock-wise (CW), while looking in the
nuclear@0 1966 // negative axis direction.
nuclear@0 1967 static Matrix4 RotationY(T angle)
nuclear@0 1968 {
nuclear@0 1969 T sina = sin(angle);
nuclear@0 1970 T cosa = cos(angle);
nuclear@0 1971 return Matrix4(cosa, 0, sina,
nuclear@0 1972 0, 1, 0,
nuclear@0 1973 -sina, 0, cosa);
nuclear@0 1974 }
nuclear@0 1975
nuclear@0 1976 // Creates a rotation matrix rotating around the Z axis by 'angle' radians.
nuclear@0 1977 // Rotation direction is depends on the coordinate system:
nuclear@0 1978 // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW),
nuclear@0 1979 // while looking in the negative axis direction. This is the
nuclear@0 1980 // same as looking down from positive axis values towards origin.
nuclear@0 1981 // LHS: Positive angle values rotate clock-wise (CW), while looking in the
nuclear@0 1982 // negative axis direction.
nuclear@0 1983 static Matrix4 RotationZ(T angle)
nuclear@0 1984 {
nuclear@0 1985 T sina = sin(angle);
nuclear@0 1986 T cosa = cos(angle);
nuclear@0 1987 return Matrix4(cosa, -sina, 0,
nuclear@0 1988 sina, cosa, 0,
nuclear@0 1989 0, 0, 1);
nuclear@0 1990 }
nuclear@0 1991
nuclear@0 1992 // LookAtRH creates a View transformation matrix for right-handed coordinate system.
nuclear@0 1993 // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up'
nuclear@0 1994 // specifying the up vector. The resulting matrix should be used with PerspectiveRH
nuclear@0 1995 // projection.
nuclear@0 1996 static Matrix4 LookAtRH(const Vector3<T>& eye, const Vector3<T>& at, const Vector3<T>& up)
nuclear@0 1997 {
nuclear@0 1998 Vector3<T> z = (eye - at).Normalized(); // Forward
nuclear@0 1999 Vector3<T> x = up.Cross(z).Normalized(); // Right
nuclear@0 2000 Vector3<T> y = z.Cross(x);
nuclear@0 2001
nuclear@0 2002 Matrix4 m(x.x, x.y, x.z, -(x.Dot(eye)),
nuclear@0 2003 y.x, y.y, y.z, -(y.Dot(eye)),
nuclear@0 2004 z.x, z.y, z.z, -(z.Dot(eye)),
nuclear@0 2005 0, 0, 0, 1 );
nuclear@0 2006 return m;
nuclear@0 2007 }
nuclear@0 2008
nuclear@0 2009 // LookAtLH creates a View transformation matrix for left-handed coordinate system.
nuclear@0 2010 // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up'
nuclear@0 2011 // specifying the up vector.
nuclear@0 2012 static Matrix4 LookAtLH(const Vector3<T>& eye, const Vector3<T>& at, const Vector3<T>& up)
nuclear@0 2013 {
nuclear@0 2014 Vector3<T> z = (at - eye).Normalized(); // Forward
nuclear@0 2015 Vector3<T> x = up.Cross(z).Normalized(); // Right
nuclear@0 2016 Vector3<T> y = z.Cross(x);
nuclear@0 2017
nuclear@0 2018 Matrix4 m(x.x, x.y, x.z, -(x.Dot(eye)),
nuclear@0 2019 y.x, y.y, y.z, -(y.Dot(eye)),
nuclear@0 2020 z.x, z.y, z.z, -(z.Dot(eye)),
nuclear@0 2021 0, 0, 0, 1 );
nuclear@0 2022 return m;
nuclear@0 2023 }
nuclear@0 2024
nuclear@0 2025 // PerspectiveRH creates a right-handed perspective projection matrix that can be
nuclear@0 2026 // used with the Oculus sample renderer.
nuclear@0 2027 // yfov - Specifies vertical field of view in radians.
nuclear@0 2028 // aspect - Screen aspect ration, which is usually width/height for square pixels.
nuclear@0 2029 // Note that xfov = yfov * aspect.
nuclear@0 2030 // znear - Absolute value of near Z clipping clipping range.
nuclear@0 2031 // zfar - Absolute value of far Z clipping clipping range (larger then near).
nuclear@0 2032 // Even though RHS usually looks in the direction of negative Z, positive values
nuclear@0 2033 // are expected for znear and zfar.
nuclear@0 2034 static Matrix4 PerspectiveRH(T yfov, T aspect, T znear, T zfar)
nuclear@0 2035 {
nuclear@0 2036 Matrix4 m;
nuclear@0 2037 T tanHalfFov = tan(yfov * 0.5f);
nuclear@0 2038
nuclear@0 2039 m.M[0][0] = 1. / (aspect * tanHalfFov);
nuclear@0 2040 m.M[1][1] = 1. / tanHalfFov;
nuclear@0 2041 m.M[2][2] = zfar / (znear - zfar);
nuclear@0 2042 m.M[3][2] = -1.;
nuclear@0 2043 m.M[2][3] = (zfar * znear) / (znear - zfar);
nuclear@0 2044 m.M[3][3] = 0.;
nuclear@0 2045
nuclear@0 2046 // Note: Post-projection matrix result assumes Left-Handed coordinate system,
nuclear@0 2047 // with Y up, X right and Z forward. This supports positive z-buffer values.
nuclear@0 2048 // This is the case even for RHS coordinate input.
nuclear@0 2049 return m;
nuclear@0 2050 }
nuclear@0 2051
nuclear@0 2052 // PerspectiveLH creates a left-handed perspective projection matrix that can be
nuclear@0 2053 // used with the Oculus sample renderer.
nuclear@0 2054 // yfov - Specifies vertical field of view in radians.
nuclear@0 2055 // aspect - Screen aspect ration, which is usually width/height for square pixels.
nuclear@0 2056 // Note that xfov = yfov * aspect.
nuclear@0 2057 // znear - Absolute value of near Z clipping clipping range.
nuclear@0 2058 // zfar - Absolute value of far Z clipping clipping range (larger then near).
nuclear@0 2059 static Matrix4 PerspectiveLH(T yfov, T aspect, T znear, T zfar)
nuclear@0 2060 {
nuclear@0 2061 Matrix4 m;
nuclear@0 2062 T tanHalfFov = tan(yfov * 0.5f);
nuclear@0 2063
nuclear@0 2064 m.M[0][0] = 1. / (aspect * tanHalfFov);
nuclear@0 2065 m.M[1][1] = 1. / tanHalfFov;
nuclear@0 2066 //m.M[2][2] = zfar / (znear - zfar);
nuclear@0 2067 m.M[2][2] = zfar / (zfar - znear);
nuclear@0 2068 m.M[3][2] = -1.;
nuclear@0 2069 m.M[2][3] = (zfar * znear) / (znear - zfar);
nuclear@0 2070 m.M[3][3] = 0.;
nuclear@0 2071
nuclear@0 2072 // Note: Post-projection matrix result assumes Left-Handed coordinate system,
nuclear@0 2073 // with Y up, X right and Z forward. This supports positive z-buffer values.
nuclear@0 2074 // This is the case even for RHS coordinate input.
nuclear@0 2075 return m;
nuclear@0 2076 }
nuclear@0 2077
nuclear@0 2078 static Matrix4 Ortho2D(T w, T h)
nuclear@0 2079 {
nuclear@0 2080 Matrix4 m;
nuclear@0 2081 m.M[0][0] = 2.0/w;
nuclear@0 2082 m.M[1][1] = -2.0/h;
nuclear@0 2083 m.M[0][3] = -1.0;
nuclear@0 2084 m.M[1][3] = 1.0;
nuclear@0 2085 m.M[2][2] = 0;
nuclear@0 2086 return m;
nuclear@0 2087 }
nuclear@0 2088 };
nuclear@0 2089
nuclear@0 2090 typedef Matrix4<float> Matrix4f;
nuclear@0 2091 typedef Matrix4<double> Matrix4d;
nuclear@0 2092
nuclear@0 2093 //-------------------------------------------------------------------------------------
nuclear@0 2094 // ***** Matrix3
nuclear@0 2095 //
nuclear@0 2096 // Matrix3 is a 3x3 matrix used for representing a rotation matrix.
nuclear@0 2097 // The matrix is stored in row-major order in memory, meaning that values
nuclear@0 2098 // of the first row are stored before the next one.
nuclear@0 2099 //
nuclear@0 2100 // The arrangement of the matrix is chosen to be in Right-Handed
nuclear@0 2101 // coordinate system and counterclockwise rotations when looking down
nuclear@0 2102 // the axis
nuclear@0 2103 //
nuclear@0 2104 // Transformation Order:
nuclear@0 2105 // - Transformations are applied from right to left, so the expression
nuclear@0 2106 // M1 * M2 * M3 * V means that the vector V is transformed by M3 first,
nuclear@0 2107 // followed by M2 and M1.
nuclear@0 2108 //
nuclear@0 2109 // Coordinate system: Right Handed
nuclear@0 2110 //
nuclear@0 2111 // Rotations: Counterclockwise when looking down the axis. All angles are in radians.
nuclear@0 2112
nuclear@0 2113 template<typename T>
nuclear@0 2114 class SymMat3;
nuclear@0 2115
nuclear@0 2116 template<class T>
nuclear@0 2117 class Matrix3
nuclear@0 2118 {
nuclear@0 2119 static const Matrix3 IdentityValue;
nuclear@0 2120
nuclear@0 2121 public:
nuclear@0 2122 T M[3][3];
nuclear@0 2123
nuclear@0 2124 enum NoInitType { NoInit };
nuclear@0 2125
nuclear@0 2126 // Construct with no memory initialization.
nuclear@0 2127 Matrix3(NoInitType) { }
nuclear@0 2128
nuclear@0 2129 // By default, we construct identity matrix.
nuclear@0 2130 Matrix3()
nuclear@0 2131 {
nuclear@0 2132 SetIdentity();
nuclear@0 2133 }
nuclear@0 2134
nuclear@0 2135 Matrix3(T m11, T m12, T m13,
nuclear@0 2136 T m21, T m22, T m23,
nuclear@0 2137 T m31, T m32, T m33)
nuclear@0 2138 {
nuclear@0 2139 M[0][0] = m11; M[0][1] = m12; M[0][2] = m13;
nuclear@0 2140 M[1][0] = m21; M[1][1] = m22; M[1][2] = m23;
nuclear@0 2141 M[2][0] = m31; M[2][1] = m32; M[2][2] = m33;
nuclear@0 2142 }
nuclear@0 2143
nuclear@0 2144 /*
nuclear@0 2145 explicit Matrix3(const Quat<T>& q)
nuclear@0 2146 {
nuclear@0 2147 T ww = q.w*q.w;
nuclear@0 2148 T xx = q.x*q.x;
nuclear@0 2149 T yy = q.y*q.y;
nuclear@0 2150 T zz = q.z*q.z;
nuclear@0 2151
nuclear@0 2152 M[0][0] = ww + xx - yy - zz; M[0][1] = 2 * (q.x*q.y - q.w*q.z); M[0][2] = 2 * (q.x*q.z + q.w*q.y);
nuclear@0 2153 M[1][0] = 2 * (q.x*q.y + q.w*q.z); M[1][1] = ww - xx + yy - zz; M[1][2] = 2 * (q.y*q.z - q.w*q.x);
nuclear@0 2154 M[2][0] = 2 * (q.x*q.z - q.w*q.y); M[2][1] = 2 * (q.y*q.z + q.w*q.x); M[2][2] = ww - xx - yy + zz;
nuclear@0 2155 }
nuclear@0 2156 */
nuclear@0 2157
nuclear@0 2158 explicit Matrix3(const Quat<T>& q)
nuclear@0 2159 {
nuclear@0 2160 const T tx = q.x+q.x, ty = q.y+q.y, tz = q.z+q.z;
nuclear@0 2161 const T twx = q.w*tx, twy = q.w*ty, twz = q.w*tz;
nuclear@0 2162 const T txx = q.x*tx, txy = q.x*ty, txz = q.x*tz;
nuclear@0 2163 const T tyy = q.y*ty, tyz = q.y*tz, tzz = q.z*tz;
nuclear@0 2164 M[0][0] = T(1) - (tyy + tzz); M[0][1] = txy - twz; M[0][2] = txz + twy;
nuclear@0 2165 M[1][0] = txy + twz; M[1][1] = T(1) - (txx + tzz); M[1][2] = tyz - twx;
nuclear@0 2166 M[2][0] = txz - twy; M[2][1] = tyz + twx; M[2][2] = T(1) - (txx + tyy);
nuclear@0 2167 }
nuclear@0 2168
nuclear@0 2169 inline explicit Matrix3(T s)
nuclear@0 2170 {
nuclear@0 2171 M[0][0] = M[1][1] = M[2][2] = s;
nuclear@0 2172 M[0][1] = M[0][2] = M[1][0] = M[1][2] = M[2][0] = M[2][1] = 0;
nuclear@0 2173 }
nuclear@0 2174
nuclear@0 2175 explicit Matrix3(const Pose<T>& p)
nuclear@0 2176 {
nuclear@0 2177 Matrix3 result(p.Rotation);
nuclear@0 2178 result.SetTranslation(p.Translation);
nuclear@0 2179 *this = result;
nuclear@0 2180 }
nuclear@0 2181
nuclear@0 2182 // C-interop support
nuclear@0 2183 explicit Matrix3(const Matrix4<typename Math<T>::OtherFloatType> &src)
nuclear@0 2184 {
nuclear@0 2185 for (int i = 0; i < 3; i++)
nuclear@0 2186 for (int j = 0; j < 3; j++)
nuclear@0 2187 M[i][j] = (T)src.M[i][j];
nuclear@0 2188 }
nuclear@0 2189
nuclear@0 2190 // C-interop support.
nuclear@0 2191 Matrix3(const typename CompatibleTypes<Matrix3<T> >::Type& s)
nuclear@0 2192 {
nuclear@0 2193 static_assert(sizeof(s) == sizeof(Matrix3), "sizeof(s) == sizeof(Matrix3)");
nuclear@0 2194 memcpy(M, s.M, sizeof(M));
nuclear@0 2195 }
nuclear@0 2196
nuclear@0 2197 operator const typename CompatibleTypes<Matrix3<T> >::Type () const
nuclear@0 2198 {
nuclear@0 2199 typename CompatibleTypes<Matrix3<T> >::Type result;
nuclear@0 2200 static_assert(sizeof(result) == sizeof(Matrix3), "sizeof(result) == sizeof(Matrix3)");
nuclear@0 2201 memcpy(result.M, M, sizeof(M));
nuclear@0 2202 return result;
nuclear@0 2203 }
nuclear@0 2204
nuclear@0 2205 void ToString(char* dest, size_t destsize) const
nuclear@0 2206 {
nuclear@0 2207 size_t pos = 0;
nuclear@0 2208 for (int r=0; r<3; r++)
nuclear@0 2209 for (int c=0; c<3; c++)
nuclear@0 2210 pos += OVR_sprintf(dest+pos, destsize-pos, "%g ", M[r][c]);
nuclear@0 2211 }
nuclear@0 2212
nuclear@0 2213 static Matrix3 FromString(const char* src)
nuclear@0 2214 {
nuclear@0 2215 Matrix3 result;
nuclear@0 2216 for (int r=0; r<3; r++)
nuclear@0 2217 for (int c=0; c<3; c++)
nuclear@0 2218 {
nuclear@0 2219 result.M[r][c] = (T)atof(src);
nuclear@0 2220 while (src && *src != ' ')
nuclear@0 2221 src++;
nuclear@0 2222 while (src && *src == ' ')
nuclear@0 2223 src++;
nuclear@0 2224 }
nuclear@0 2225 return result;
nuclear@0 2226 }
nuclear@0 2227
nuclear@0 2228 static const Matrix3& Identity() { return IdentityValue; }
nuclear@0 2229
nuclear@0 2230 void SetIdentity()
nuclear@0 2231 {
nuclear@0 2232 M[0][0] = M[1][1] = M[2][2] = 1;
nuclear@0 2233 M[0][1] = M[1][0] = M[2][0] = 0;
nuclear@0 2234 M[0][2] = M[1][2] = M[2][1] = 0;
nuclear@0 2235 }
nuclear@0 2236
nuclear@0 2237 bool operator== (const Matrix3& b) const
nuclear@0 2238 {
nuclear@0 2239 bool isEqual = true;
nuclear@0 2240 for (int i = 0; i < 3; i++)
nuclear@0 2241 for (int j = 0; j < 3; j++)
nuclear@0 2242 isEqual &= (M[i][j] == b.M[i][j]);
nuclear@0 2243
nuclear@0 2244 return isEqual;
nuclear@0 2245 }
nuclear@0 2246
nuclear@0 2247 Matrix3 operator+ (const Matrix3& b) const
nuclear@0 2248 {
nuclear@0 2249 Matrix4<T> result(*this);
nuclear@0 2250 result += b;
nuclear@0 2251 return result;
nuclear@0 2252 }
nuclear@0 2253
nuclear@0 2254 Matrix3& operator+= (const Matrix3& b)
nuclear@0 2255 {
nuclear@0 2256 for (int i = 0; i < 3; i++)
nuclear@0 2257 for (int j = 0; j < 3; j++)
nuclear@0 2258 M[i][j] += b.M[i][j];
nuclear@0 2259 return *this;
nuclear@0 2260 }
nuclear@0 2261
nuclear@0 2262 void operator= (const Matrix3& b)
nuclear@0 2263 {
nuclear@0 2264 for (int i = 0; i < 3; i++)
nuclear@0 2265 for (int j = 0; j < 3; j++)
nuclear@0 2266 M[i][j] = b.M[i][j];
nuclear@0 2267 return;
nuclear@0 2268 }
nuclear@0 2269
nuclear@0 2270 void operator= (const SymMat3<T>& b)
nuclear@0 2271 {
nuclear@0 2272 for (int i = 0; i < 3; i++)
nuclear@0 2273 for (int j = 0; j < 3; j++)
nuclear@0 2274 M[i][j] = 0;
nuclear@0 2275
nuclear@0 2276 M[0][0] = b.v[0];
nuclear@0 2277 M[0][1] = b.v[1];
nuclear@0 2278 M[0][2] = b.v[2];
nuclear@0 2279 M[1][1] = b.v[3];
nuclear@0 2280 M[1][2] = b.v[4];
nuclear@0 2281 M[2][2] = b.v[5];
nuclear@0 2282
nuclear@0 2283 return;
nuclear@0 2284 }
nuclear@0 2285
nuclear@0 2286 Matrix3 operator- (const Matrix3& b) const
nuclear@0 2287 {
nuclear@0 2288 Matrix3 result(*this);
nuclear@0 2289 result -= b;
nuclear@0 2290 return result;
nuclear@0 2291 }
nuclear@0 2292
nuclear@0 2293 Matrix3& operator-= (const Matrix3& b)
nuclear@0 2294 {
nuclear@0 2295 for (int i = 0; i < 3; i++)
nuclear@0 2296 for (int j = 0; j < 3; j++)
nuclear@0 2297 M[i][j] -= b.M[i][j];
nuclear@0 2298 return *this;
nuclear@0 2299 }
nuclear@0 2300
nuclear@0 2301 // Multiplies two matrices into destination with minimum copying.
nuclear@0 2302 static Matrix3& Multiply(Matrix3* d, const Matrix3& a, const Matrix3& b)
nuclear@0 2303 {
nuclear@0 2304 OVR_ASSERT((d != &a) && (d != &b));
nuclear@0 2305 int i = 0;
nuclear@0 2306 do {
nuclear@0 2307 d->M[i][0] = a.M[i][0] * b.M[0][0] + a.M[i][1] * b.M[1][0] + a.M[i][2] * b.M[2][0];
nuclear@0 2308 d->M[i][1] = a.M[i][0] * b.M[0][1] + a.M[i][1] * b.M[1][1] + a.M[i][2] * b.M[2][1];
nuclear@0 2309 d->M[i][2] = a.M[i][0] * b.M[0][2] + a.M[i][1] * b.M[1][2] + a.M[i][2] * b.M[2][2];
nuclear@0 2310 } while((++i) < 3);
nuclear@0 2311
nuclear@0 2312 return *d;
nuclear@0 2313 }
nuclear@0 2314
nuclear@0 2315 Matrix3 operator* (const Matrix3& b) const
nuclear@0 2316 {
nuclear@0 2317 Matrix3 result(Matrix3::NoInit);
nuclear@0 2318 Multiply(&result, *this, b);
nuclear@0 2319 return result;
nuclear@0 2320 }
nuclear@0 2321
nuclear@0 2322 Matrix3& operator*= (const Matrix3& b)
nuclear@0 2323 {
nuclear@0 2324 return Multiply(this, Matrix3(*this), b);
nuclear@0 2325 }
nuclear@0 2326
nuclear@0 2327 Matrix3 operator* (T s) const
nuclear@0 2328 {
nuclear@0 2329 Matrix3 result(*this);
nuclear@0 2330 result *= s;
nuclear@0 2331 return result;
nuclear@0 2332 }
nuclear@0 2333
nuclear@0 2334 Matrix3& operator*= (T s)
nuclear@0 2335 {
nuclear@0 2336 for (int i = 0; i < 3; i++)
nuclear@0 2337 for (int j = 0; j < 3; j++)
nuclear@0 2338 M[i][j] *= s;
nuclear@0 2339 return *this;
nuclear@0 2340 }
nuclear@0 2341
nuclear@0 2342 Vector3<T> operator* (const Vector3<T> &b) const
nuclear@0 2343 {
nuclear@0 2344 Vector3<T> result;
nuclear@0 2345 result.x = M[0][0]*b.x + M[0][1]*b.y + M[0][2]*b.z;
nuclear@0 2346 result.y = M[1][0]*b.x + M[1][1]*b.y + M[1][2]*b.z;
nuclear@0 2347 result.z = M[2][0]*b.x + M[2][1]*b.y + M[2][2]*b.z;
nuclear@0 2348
nuclear@0 2349 return result;
nuclear@0 2350 }
nuclear@0 2351
nuclear@0 2352 Matrix3 operator/ (T s) const
nuclear@0 2353 {
nuclear@0 2354 Matrix3 result(*this);
nuclear@0 2355 result /= s;
nuclear@0 2356 return result;
nuclear@0 2357 }
nuclear@0 2358
nuclear@0 2359 Matrix3& operator/= (T s)
nuclear@0 2360 {
nuclear@0 2361 for (int i = 0; i < 3; i++)
nuclear@0 2362 for (int j = 0; j < 3; j++)
nuclear@0 2363 M[i][j] /= s;
nuclear@0 2364 return *this;
nuclear@0 2365 }
nuclear@0 2366
nuclear@0 2367 Vector2<T> Transform(const Vector2<T>& v) const
nuclear@0 2368 {
nuclear@0 2369 const float rcpZ = 1.0f / (M[2][0] * v.x + M[2][1] * v.y + M[2][2]);
nuclear@0 2370 return Vector2<T>((M[0][0] * v.x + M[0][1] * v.y + M[0][2]) * rcpZ,
nuclear@0 2371 (M[1][0] * v.x + M[1][1] * v.y + M[1][2]) * rcpZ);
nuclear@0 2372 }
nuclear@0 2373
nuclear@0 2374 Vector3<T> Transform(const Vector3<T>& v) const
nuclear@0 2375 {
nuclear@0 2376 return Vector3<T>(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z,
nuclear@0 2377 M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z,
nuclear@0 2378 M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z);
nuclear@0 2379 }
nuclear@0 2380
nuclear@0 2381 Matrix3 Transposed() const
nuclear@0 2382 {
nuclear@0 2383 return Matrix3(M[0][0], M[1][0], M[2][0],
nuclear@0 2384 M[0][1], M[1][1], M[2][1],
nuclear@0 2385 M[0][2], M[1][2], M[2][2]);
nuclear@0 2386 }
nuclear@0 2387
nuclear@0 2388 void Transpose()
nuclear@0 2389 {
nuclear@0 2390 *this = Transposed();
nuclear@0 2391 }
nuclear@0 2392
nuclear@0 2393
nuclear@0 2394 T SubDet (const size_t* rows, const size_t* cols) const
nuclear@0 2395 {
nuclear@0 2396 return M[rows[0]][cols[0]] * (M[rows[1]][cols[1]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[1]])
nuclear@0 2397 - M[rows[0]][cols[1]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[0]])
nuclear@0 2398 + M[rows[0]][cols[2]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[1]] - M[rows[1]][cols[1]] * M[rows[2]][cols[0]]);
nuclear@0 2399 }
nuclear@0 2400
nuclear@0 2401 // M += a*b.t()
nuclear@0 2402 inline void Rank1Add(const Vector3<T> &a, const Vector3<T> &b)
nuclear@0 2403 {
nuclear@0 2404 M[0][0] += a.x*b.x; M[0][1] += a.x*b.y; M[0][2] += a.x*b.z;
nuclear@0 2405 M[1][0] += a.y*b.x; M[1][1] += a.y*b.y; M[1][2] += a.y*b.z;
nuclear@0 2406 M[2][0] += a.z*b.x; M[2][1] += a.z*b.y; M[2][2] += a.z*b.z;
nuclear@0 2407 }
nuclear@0 2408
nuclear@0 2409 // M -= a*b.t()
nuclear@0 2410 inline void Rank1Sub(const Vector3<T> &a, const Vector3<T> &b)
nuclear@0 2411 {
nuclear@0 2412 M[0][0] -= a.x*b.x; M[0][1] -= a.x*b.y; M[0][2] -= a.x*b.z;
nuclear@0 2413 M[1][0] -= a.y*b.x; M[1][1] -= a.y*b.y; M[1][2] -= a.y*b.z;
nuclear@0 2414 M[2][0] -= a.z*b.x; M[2][1] -= a.z*b.y; M[2][2] -= a.z*b.z;
nuclear@0 2415 }
nuclear@0 2416
nuclear@0 2417 inline Vector3<T> Col(int c) const
nuclear@0 2418 {
nuclear@0 2419 return Vector3<T>(M[0][c], M[1][c], M[2][c]);
nuclear@0 2420 }
nuclear@0 2421
nuclear@0 2422 inline Vector3<T> Row(int r) const
nuclear@0 2423 {
nuclear@0 2424 return Vector3<T>(M[r][0], M[r][1], M[r][2]);
nuclear@0 2425 }
nuclear@0 2426
nuclear@0 2427 inline T Determinant() const
nuclear@0 2428 {
nuclear@0 2429 const Matrix3<T>& m = *this;
nuclear@0 2430 T d;
nuclear@0 2431
nuclear@0 2432 d = m.M[0][0] * (m.M[1][1]*m.M[2][2] - m.M[1][2] * m.M[2][1]);
nuclear@0 2433 d -= m.M[0][1] * (m.M[1][0]*m.M[2][2] - m.M[1][2] * m.M[2][0]);
nuclear@0 2434 d += m.M[0][2] * (m.M[1][0]*m.M[2][1] - m.M[1][1] * m.M[2][0]);
nuclear@0 2435
nuclear@0 2436 return d;
nuclear@0 2437 }
nuclear@0 2438
nuclear@0 2439 inline Matrix3<T> Inverse() const
nuclear@0 2440 {
nuclear@0 2441 Matrix3<T> a;
nuclear@0 2442 const Matrix3<T>& m = *this;
nuclear@0 2443 T d = Determinant();
nuclear@0 2444
nuclear@0 2445 assert(d != 0);
nuclear@0 2446 T s = T(1)/d;
nuclear@0 2447
nuclear@0 2448 a.M[0][0] = s * (m.M[1][1] * m.M[2][2] - m.M[1][2] * m.M[2][1]);
nuclear@0 2449 a.M[1][0] = s * (m.M[1][2] * m.M[2][0] - m.M[1][0] * m.M[2][2]);
nuclear@0 2450 a.M[2][0] = s * (m.M[1][0] * m.M[2][1] - m.M[1][1] * m.M[2][0]);
nuclear@0 2451
nuclear@0 2452 a.M[0][1] = s * (m.M[0][2] * m.M[2][1] - m.M[0][1] * m.M[2][2]);
nuclear@0 2453 a.M[1][1] = s * (m.M[0][0] * m.M[2][2] - m.M[0][2] * m.M[2][0]);
nuclear@0 2454 a.M[2][1] = s * (m.M[0][1] * m.M[2][0] - m.M[0][0] * m.M[2][1]);
nuclear@0 2455
nuclear@0 2456 a.M[0][2] = s * (m.M[0][1] * m.M[1][2] - m.M[0][2] * m.M[1][1]);
nuclear@0 2457 a.M[1][2] = s * (m.M[0][2] * m.M[1][0] - m.M[0][0] * m.M[1][2]);
nuclear@0 2458 a.M[2][2] = s * (m.M[0][0] * m.M[1][1] - m.M[0][1] * m.M[1][0]);
nuclear@0 2459
nuclear@0 2460 return a;
nuclear@0 2461 }
nuclear@0 2462
nuclear@0 2463 };
nuclear@0 2464
nuclear@0 2465 typedef Matrix3<float> Matrix3f;
nuclear@0 2466 typedef Matrix3<double> Matrix3d;
nuclear@0 2467
nuclear@0 2468 //-------------------------------------------------------------------------------------
nuclear@0 2469
nuclear@0 2470 template<typename T>
nuclear@0 2471 class SymMat3
nuclear@0 2472 {
nuclear@0 2473 private:
nuclear@0 2474 typedef SymMat3<T> this_type;
nuclear@0 2475
nuclear@0 2476 public:
nuclear@0 2477 typedef T Value_t;
nuclear@0 2478 // Upper symmetric
nuclear@0 2479 T v[6]; // _00 _01 _02 _11 _12 _22
nuclear@0 2480
nuclear@0 2481 inline SymMat3() {}
nuclear@0 2482
nuclear@0 2483 inline explicit SymMat3(T s)
nuclear@0 2484 {
nuclear@0 2485 v[0] = v[3] = v[5] = s;
nuclear@0 2486 v[1] = v[2] = v[4] = 0;
nuclear@0 2487 }
nuclear@0 2488
nuclear@0 2489 inline explicit SymMat3(T a00, T a01, T a02, T a11, T a12, T a22)
nuclear@0 2490 {
nuclear@0 2491 v[0] = a00; v[1] = a01; v[2] = a02;
nuclear@0 2492 v[3] = a11; v[4] = a12;
nuclear@0 2493 v[5] = a22;
nuclear@0 2494 }
nuclear@0 2495
nuclear@0 2496 static inline int Index(unsigned int i, unsigned int j)
nuclear@0 2497 {
nuclear@0 2498 return (i <= j) ? (3*i - i*(i+1)/2 + j) : (3*j - j*(j+1)/2 + i);
nuclear@0 2499 }
nuclear@0 2500
nuclear@0 2501 inline T operator()(int i, int j) const { return v[Index(i,j)]; }
nuclear@0 2502
nuclear@0 2503 inline T &operator()(int i, int j) { return v[Index(i,j)]; }
nuclear@0 2504
nuclear@0 2505 template<typename U>
nuclear@0 2506 inline SymMat3<U> CastTo() const
nuclear@0 2507 {
nuclear@0 2508 return SymMat3<U>(static_cast<U>(v[0]), static_cast<U>(v[1]), static_cast<U>(v[2]),
nuclear@0 2509 static_cast<U>(v[3]), static_cast<U>(v[4]), static_cast<U>(v[5]));
nuclear@0 2510 }
nuclear@0 2511
nuclear@0 2512 inline this_type& operator+=(const this_type& b)
nuclear@0 2513 {
nuclear@0 2514 v[0]+=b.v[0];
nuclear@0 2515 v[1]+=b.v[1];
nuclear@0 2516 v[2]+=b.v[2];
nuclear@0 2517 v[3]+=b.v[3];
nuclear@0 2518 v[4]+=b.v[4];
nuclear@0 2519 v[5]+=b.v[5];
nuclear@0 2520 return *this;
nuclear@0 2521 }
nuclear@0 2522
nuclear@0 2523 inline this_type& operator-=(const this_type& b)
nuclear@0 2524 {
nuclear@0 2525 v[0]-=b.v[0];
nuclear@0 2526 v[1]-=b.v[1];
nuclear@0 2527 v[2]-=b.v[2];
nuclear@0 2528 v[3]-=b.v[3];
nuclear@0 2529 v[4]-=b.v[4];
nuclear@0 2530 v[5]-=b.v[5];
nuclear@0 2531
nuclear@0 2532 return *this;
nuclear@0 2533 }
nuclear@0 2534
nuclear@0 2535 inline this_type& operator*=(T s)
nuclear@0 2536 {
nuclear@0 2537 v[0]*=s;
nuclear@0 2538 v[1]*=s;
nuclear@0 2539 v[2]*=s;
nuclear@0 2540 v[3]*=s;
nuclear@0 2541 v[4]*=s;
nuclear@0 2542 v[5]*=s;
nuclear@0 2543
nuclear@0 2544 return *this;
nuclear@0 2545 }
nuclear@0 2546
nuclear@0 2547 inline SymMat3 operator*(T s) const
nuclear@0 2548 {
nuclear@0 2549 SymMat3 d;
nuclear@0 2550 d.v[0] = v[0]*s;
nuclear@0 2551 d.v[1] = v[1]*s;
nuclear@0 2552 d.v[2] = v[2]*s;
nuclear@0 2553 d.v[3] = v[3]*s;
nuclear@0 2554 d.v[4] = v[4]*s;
nuclear@0 2555 d.v[5] = v[5]*s;
nuclear@0 2556
nuclear@0 2557 return d;
nuclear@0 2558 }
nuclear@0 2559
nuclear@0 2560 // Multiplies two matrices into destination with minimum copying.
nuclear@0 2561 static SymMat3& Multiply(SymMat3* d, const SymMat3& a, const SymMat3& b)
nuclear@0 2562 {
nuclear@0 2563 // _00 _01 _02 _11 _12 _22
nuclear@0 2564
nuclear@0 2565 d->v[0] = a.v[0] * b.v[0];
nuclear@0 2566 d->v[1] = a.v[0] * b.v[1] + a.v[1] * b.v[3];
nuclear@0 2567 d->v[2] = a.v[0] * b.v[2] + a.v[1] * b.v[4];
nuclear@0 2568
nuclear@0 2569 d->v[3] = a.v[3] * b.v[3];
nuclear@0 2570 d->v[4] = a.v[3] * b.v[4] + a.v[4] * b.v[5];
nuclear@0 2571
nuclear@0 2572 d->v[5] = a.v[5] * b.v[5];
nuclear@0 2573
nuclear@0 2574 return *d;
nuclear@0 2575 }
nuclear@0 2576
nuclear@0 2577 inline T Determinant() const
nuclear@0 2578 {
nuclear@0 2579 const this_type& m = *this;
nuclear@0 2580 T d;
nuclear@0 2581
nuclear@0 2582 d = m(0,0) * (m(1,1)*m(2,2) - m(1,2) * m(2,1));
nuclear@0 2583 d -= m(0,1) * (m(1,0)*m(2,2) - m(1,2) * m(2,0));
nuclear@0 2584 d += m(0,2) * (m(1,0)*m(2,1) - m(1,1) * m(2,0));
nuclear@0 2585
nuclear@0 2586 return d;
nuclear@0 2587 }
nuclear@0 2588
nuclear@0 2589 inline this_type Inverse() const
nuclear@0 2590 {
nuclear@0 2591 this_type a;
nuclear@0 2592 const this_type& m = *this;
nuclear@0 2593 T d = Determinant();
nuclear@0 2594
nuclear@0 2595 assert(d != 0);
nuclear@0 2596 T s = T(1)/d;
nuclear@0 2597
nuclear@0 2598 a(0,0) = s * (m(1,1) * m(2,2) - m(1,2) * m(2,1));
nuclear@0 2599
nuclear@0 2600 a(0,1) = s * (m(0,2) * m(2,1) - m(0,1) * m(2,2));
nuclear@0 2601 a(1,1) = s * (m(0,0) * m(2,2) - m(0,2) * m(2,0));
nuclear@0 2602
nuclear@0 2603 a(0,2) = s * (m(0,1) * m(1,2) - m(0,2) * m(1,1));
nuclear@0 2604 a(1,2) = s * (m(0,2) * m(1,0) - m(0,0) * m(1,2));
nuclear@0 2605 a(2,2) = s * (m(0,0) * m(1,1) - m(0,1) * m(1,0));
nuclear@0 2606
nuclear@0 2607 return a;
nuclear@0 2608 }
nuclear@0 2609
nuclear@0 2610 inline T Trace() const { return v[0] + v[3] + v[5]; }
nuclear@0 2611
nuclear@0 2612 // M = a*a.t()
nuclear@0 2613 inline void Rank1(const Vector3<T> &a)
nuclear@0 2614 {
nuclear@0 2615 v[0] = a.x*a.x; v[1] = a.x*a.y; v[2] = a.x*a.z;
nuclear@0 2616 v[3] = a.y*a.y; v[4] = a.y*a.z;
nuclear@0 2617 v[5] = a.z*a.z;
nuclear@0 2618 }
nuclear@0 2619
nuclear@0 2620 // M += a*a.t()
nuclear@0 2621 inline void Rank1Add(const Vector3<T> &a)
nuclear@0 2622 {
nuclear@0 2623 v[0] += a.x*a.x; v[1] += a.x*a.y; v[2] += a.x*a.z;
nuclear@0 2624 v[3] += a.y*a.y; v[4] += a.y*a.z;
nuclear@0 2625 v[5] += a.z*a.z;
nuclear@0 2626 }
nuclear@0 2627
nuclear@0 2628 // M -= a*a.t()
nuclear@0 2629 inline void Rank1Sub(const Vector3<T> &a)
nuclear@0 2630 {
nuclear@0 2631 v[0] -= a.x*a.x; v[1] -= a.x*a.y; v[2] -= a.x*a.z;
nuclear@0 2632 v[3] -= a.y*a.y; v[4] -= a.y*a.z;
nuclear@0 2633 v[5] -= a.z*a.z;
nuclear@0 2634 }
nuclear@0 2635 };
nuclear@0 2636
nuclear@0 2637 typedef SymMat3<float> SymMat3f;
nuclear@0 2638 typedef SymMat3<double> SymMat3d;
nuclear@0 2639
nuclear@0 2640 template<typename T>
nuclear@0 2641 inline Matrix3<T> operator*(const SymMat3<T>& a, const SymMat3<T>& b)
nuclear@0 2642 {
nuclear@0 2643 #define AJB_ARBC(r,c) (a(r,0)*b(0,c)+a(r,1)*b(1,c)+a(r,2)*b(2,c))
nuclear@0 2644 return Matrix3<T>(
nuclear@0 2645 AJB_ARBC(0,0), AJB_ARBC(0,1), AJB_ARBC(0,2),
nuclear@0 2646 AJB_ARBC(1,0), AJB_ARBC(1,1), AJB_ARBC(1,2),
nuclear@0 2647 AJB_ARBC(2,0), AJB_ARBC(2,1), AJB_ARBC(2,2));
nuclear@0 2648 #undef AJB_ARBC
nuclear@0 2649 }
nuclear@0 2650
nuclear@0 2651 template<typename T>
nuclear@0 2652 inline Matrix3<T> operator*(const Matrix3<T>& a, const SymMat3<T>& b)
nuclear@0 2653 {
nuclear@0 2654 #define AJB_ARBC(r,c) (a(r,0)*b(0,c)+a(r,1)*b(1,c)+a(r,2)*b(2,c))
nuclear@0 2655 return Matrix3<T>(
nuclear@0 2656 AJB_ARBC(0,0), AJB_ARBC(0,1), AJB_ARBC(0,2),
nuclear@0 2657 AJB_ARBC(1,0), AJB_ARBC(1,1), AJB_ARBC(1,2),
nuclear@0 2658 AJB_ARBC(2,0), AJB_ARBC(2,1), AJB_ARBC(2,2));
nuclear@0 2659 #undef AJB_ARBC
nuclear@0 2660 }
nuclear@0 2661
nuclear@0 2662 //-------------------------------------------------------------------------------------
nuclear@0 2663 // ***** Angle
nuclear@0 2664
nuclear@0 2665 // Cleanly representing the algebra of 2D rotations.
nuclear@0 2666 // The operations maintain the angle between -Pi and Pi, the same range as atan2.
nuclear@0 2667
nuclear@0 2668 template<class T>
nuclear@0 2669 class Angle
nuclear@0 2670 {
nuclear@0 2671 public:
nuclear@0 2672 enum AngularUnits
nuclear@0 2673 {
nuclear@0 2674 Radians = 0,
nuclear@0 2675 Degrees = 1
nuclear@0 2676 };
nuclear@0 2677
nuclear@0 2678 Angle() : a(0) {}
nuclear@0 2679
nuclear@0 2680 // Fix the range to be between -Pi and Pi
nuclear@0 2681 Angle(T a_, AngularUnits u = Radians) : a((u == Radians) ? a_ : a_*((T)MATH_DOUBLE_DEGREETORADFACTOR)) { FixRange(); }
nuclear@0 2682
nuclear@0 2683 T Get(AngularUnits u = Radians) const { return (u == Radians) ? a : a*((T)MATH_DOUBLE_RADTODEGREEFACTOR); }
nuclear@0 2684 void Set(const T& x, AngularUnits u = Radians) { a = (u == Radians) ? x : x*((T)MATH_DOUBLE_DEGREETORADFACTOR); FixRange(); }
nuclear@0 2685 int Sign() const { if (a == 0) return 0; else return (a > 0) ? 1 : -1; }
nuclear@0 2686 T Abs() const { return (a > 0) ? a : -a; }
nuclear@0 2687
nuclear@0 2688 bool operator== (const Angle& b) const { return a == b.a; }
nuclear@0 2689 bool operator!= (const Angle& b) const { return a != b.a; }
nuclear@0 2690 // bool operator< (const Angle& b) const { return a < a.b; }
nuclear@0 2691 // bool operator> (const Angle& b) const { return a > a.b; }
nuclear@0 2692 // bool operator<= (const Angle& b) const { return a <= a.b; }
nuclear@0 2693 // bool operator>= (const Angle& b) const { return a >= a.b; }
nuclear@0 2694 // bool operator= (const T& x) { a = x; FixRange(); }
nuclear@0 2695
nuclear@0 2696 // These operations assume a is already between -Pi and Pi.
nuclear@0 2697 Angle& operator+= (const Angle& b) { a = a + b.a; FastFixRange(); return *this; }
nuclear@0 2698 Angle& operator+= (const T& x) { a = a + x; FixRange(); return *this; }
nuclear@0 2699 Angle operator+ (const Angle& b) const { Angle res = *this; res += b; return res; }
nuclear@0 2700 Angle operator+ (const T& x) const { Angle res = *this; res += x; return res; }
nuclear@0 2701 Angle& operator-= (const Angle& b) { a = a - b.a; FastFixRange(); return *this; }
nuclear@0 2702 Angle& operator-= (const T& x) { a = a - x; FixRange(); return *this; }
nuclear@0 2703 Angle operator- (const Angle& b) const { Angle res = *this; res -= b; return res; }
nuclear@0 2704 Angle operator- (const T& x) const { Angle res = *this; res -= x; return res; }
nuclear@0 2705
nuclear@0 2706 T Distance(const Angle& b) { T c = fabs(a - b.a); return (c <= ((T)MATH_DOUBLE_PI)) ? c : ((T)MATH_DOUBLE_TWOPI) - c; }
nuclear@0 2707
nuclear@0 2708 private:
nuclear@0 2709
nuclear@0 2710 // The stored angle, which should be maintained between -Pi and Pi
nuclear@0 2711 T a;
nuclear@0 2712
nuclear@0 2713 // Fixes the angle range to [-Pi,Pi], but assumes no more than 2Pi away on either side
nuclear@0 2714 inline void FastFixRange()
nuclear@0 2715 {
nuclear@0 2716 if (a < -((T)MATH_DOUBLE_PI))
nuclear@0 2717 a += ((T)MATH_DOUBLE_TWOPI);
nuclear@0 2718 else if (a > ((T)MATH_DOUBLE_PI))
nuclear@0 2719 a -= ((T)MATH_DOUBLE_TWOPI);
nuclear@0 2720 }
nuclear@0 2721
nuclear@0 2722 // Fixes the angle range to [-Pi,Pi] for any given range, but slower then the fast method
nuclear@0 2723 inline void FixRange()
nuclear@0 2724 {
nuclear@0 2725 // do nothing if the value is already in the correct range, since fmod call is expensive
nuclear@0 2726 if (a >= -((T)MATH_DOUBLE_PI) && a <= ((T)MATH_DOUBLE_PI))
nuclear@0 2727 return;
nuclear@0 2728 a = fmod(a,((T)MATH_DOUBLE_TWOPI));
nuclear@0 2729 if (a < -((T)MATH_DOUBLE_PI))
nuclear@0 2730 a += ((T)MATH_DOUBLE_TWOPI);
nuclear@0 2731 else if (a > ((T)MATH_DOUBLE_PI))
nuclear@0 2732 a -= ((T)MATH_DOUBLE_TWOPI);
nuclear@0 2733 }
nuclear@0 2734 };
nuclear@0 2735
nuclear@0 2736
nuclear@0 2737 typedef Angle<float> Anglef;
nuclear@0 2738 typedef Angle<double> Angled;
nuclear@0 2739
nuclear@0 2740
nuclear@0 2741 //-------------------------------------------------------------------------------------
nuclear@0 2742 // ***** Plane
nuclear@0 2743
nuclear@0 2744 // Consists of a normal vector and distance from the origin where the plane is located.
nuclear@0 2745
nuclear@0 2746 template<class T>
nuclear@0 2747 class Plane
nuclear@0 2748 {
nuclear@0 2749 public:
nuclear@0 2750 Vector3<T> N;
nuclear@0 2751 T D;
nuclear@0 2752
nuclear@0 2753 Plane() : D(0) {}
nuclear@0 2754
nuclear@0 2755 // Normals must already be normalized
nuclear@0 2756 Plane(const Vector3<T>& n, T d) : N(n), D(d) {}
nuclear@0 2757 Plane(T x, T y, T z, T d) : N(x,y,z), D(d) {}
nuclear@0 2758
nuclear@0 2759 // construct from a point on the plane and the normal
nuclear@0 2760 Plane(const Vector3<T>& p, const Vector3<T>& n) : N(n), D(-(p * n)) {}
nuclear@0 2761
nuclear@0 2762 // Find the point to plane distance. The sign indicates what side of the plane the point is on (0 = point on plane).
nuclear@0 2763 T TestSide(const Vector3<T>& p) const
nuclear@0 2764 {
nuclear@0 2765 return (N.Dot(p)) + D;
nuclear@0 2766 }
nuclear@0 2767
nuclear@0 2768 Plane<T> Flipped() const
nuclear@0 2769 {
nuclear@0 2770 return Plane(-N, -D);
nuclear@0 2771 }
nuclear@0 2772
nuclear@0 2773 void Flip()
nuclear@0 2774 {
nuclear@0 2775 N = -N;
nuclear@0 2776 D = -D;
nuclear@0 2777 }
nuclear@0 2778
nuclear@0 2779 bool operator==(const Plane<T>& rhs) const
nuclear@0 2780 {
nuclear@0 2781 return (this->D == rhs.D && this->N == rhs.N);
nuclear@0 2782 }
nuclear@0 2783 };
nuclear@0 2784
nuclear@0 2785 typedef Plane<float> Planef;
nuclear@0 2786 typedef Plane<double> Planed;
nuclear@0 2787
nuclear@0 2788
nuclear@0 2789 } // Namespace OVR
nuclear@0 2790
nuclear@0 2791 #endif