00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
#include "Quaternion.h"
00013
using namespace OpenCAL::Utils;
00014
00015
#include <math.h>
00016
00017
using namespace std;
00018
00019
00020
00021
const Quaternion Quaternion::identity(1.0f, Vector3::zero);
00022
00023
00024
00025
00026
00027
00028 Quaternion::Quaternion()
00029 : m_scalar(1.0f), m_vector(0.0f, 0.0f, 0.0f)
00030 {
00031 }
00032
00033 Quaternion::Quaternion(
float scalar,
const Vector3 &vector)
00034 : m_scalar(scalar), m_vector(vector)
00035 {
00036 }
00037
00038 Quaternion::~Quaternion()
00039 {
00040 }
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00056 Quaternion Quaternion::operator+(
const Quaternion &q)
const
00057
{
00058
return Quaternion(
00059 m_scalar + q.
m_scalar,
00060 m_vector + q.
m_vector
00061 );
00062 }
00063
00064 Quaternion Quaternion::operator-(
const Quaternion &q)
const
00065
{
00066
return Quaternion(
00067 m_scalar - q.
m_scalar,
00068 m_vector - q.
m_vector
00069 );
00070 }
00071
00082 Quaternion Quaternion::operator*(
const Quaternion &q)
const
00083
{
00084
return Quaternion(
00085 m_scalar * q.
m_scalar - m_vector.
dotProduct(q.
m_vector),
00086 m_scalar * q.
m_vector + q.
m_scalar * m_vector + m_vector.
crossProduct(q.
m_vector)
00087 );
00088 }
00089
00090 Quaternion Quaternion::operator*(
const Vector3 &v)
const
00091
{
00092
return operator*(
Quaternion(0, v));
00093 }
00094
00095 Quaternion Quaternion::operator*(
float factor)
const
00096
{
00097
return Quaternion(
00098 m_scalar * factor,
00099 m_vector * factor
00100 );
00101 }
00102
00103 Quaternion Quaternion::operator/(
float factor)
const
00104
{
00105
return Quaternion(
00106 m_scalar / factor,
00107 m_vector / factor
00108 );
00109 }
00110
00111
void Quaternion::operator+=(
const Quaternion &q)
00112 {
00113 m_scalar += q.
m_scalar;
00114 m_vector += q.
m_vector;
00115 }
00116
00117
void Quaternion::operator-=(
const Quaternion &q)
00118 {
00119 m_scalar -= q.
m_scalar;
00120 m_vector -= q.
m_vector;
00121 }
00122
00123
void Quaternion::operator*=(
const Quaternion &q)
00124 {
00125
float scalar = m_scalar * q.
m_scalar - m_vector.dotProduct(q.
m_vector);
00126 m_vector = m_scalar * q.
m_vector + q.
m_scalar * m_vector + m_vector.crossProduct(q.
m_vector);
00127 m_scalar = scalar;
00128 }
00129
00130
void Quaternion::operator*=(
const Vector3 &v)
00131 {
00132 operator*=(
Quaternion(0, v));
00133 }
00134
00135
void Quaternion::operator*=(
float factor)
00136 {
00137 m_scalar *= factor;
00138 m_vector *= factor;
00139 }
00140
00141
void Quaternion::operator/=(
float factor)
00142 {
00143 m_scalar /= factor;
00144 m_vector /= factor;
00145 }
00146
00147 Quaternion Quaternion::operator-()
const
00148
{
00149
return Quaternion(
00150 -m_scalar,
00151 -m_vector
00152 );
00153 }
00154
00155 bool Quaternion::operator==(
const Quaternion &q)
const
00156
{
00157
return m_scalar == q.
m_scalar && m_vector == q.
m_vector;
00158 }
00159
00160 bool Quaternion::operator!=(
const Quaternion &q)
const
00161
{
00162
return m_scalar != q.
m_scalar || m_vector != q.
m_vector;
00163 }
00164
00165
00166
Quaternion OpenCAL::Utils::operator*(
const Vector3 &v,
const Quaternion &q)
00167 {
00168
return Quaternion(0, v) * q;
00169 }
00170
00171
Quaternion OpenCAL::Utils::operator*(
float factor,
const Quaternion &q)
00172 {
00173
return Quaternion(
00174 factor * q.
m_scalar,
00175 factor * q.
m_vector
00176 );
00177 }
00178
00179
Quaternion OpenCAL::Utils::operator/(
float factor,
const Quaternion &q)
00180 {
00181
return Quaternion(
00182 factor / q.
m_scalar,
00183 factor / q.
m_vector
00184 );
00185 }
00186
00187
00188
00189
00190
00191
00196 float Quaternion::magnitude()
const
00197
{
00198
return sqrtf(
00199 m_scalar * m_scalar +
00200 m_vector.
getX() * m_vector.
getX() +
00201 m_vector.
getY() * m_vector.
getY() +
00202 m_vector.
getZ() * m_vector.
getZ()
00203 );
00204 }
00205
00206
float Quaternion::magnitudeSquared()
const
00207
{
00208
return (
00209 m_scalar * m_scalar +
00210 m_vector.
getX() * m_vector.
getX() +
00211 m_vector.
getY() * m_vector.
getY() +
00212 m_vector.
getZ() * m_vector.
getZ()
00213 );
00214 }
00215
00225 void Quaternion::inverse()
00226 {
00227
float msi = 1.0f / magnitudeSquared();
00228
00229 m_scalar *= msi;
00230 m_vector *= -msi;
00231 }
00232
00236 Quaternion Quaternion::inversed()
const
00237
{
00238
float msi = 1.0f / magnitudeSquared();
00239
00240
return Quaternion(m_scalar * msi, -m_vector * msi);
00241 }
00242
00246 void Quaternion::inversed(
Quaternion *q)
const
00247
{
00248
float msi = 1.0f / magnitudeSquared();
00249
00250 q->
setScalar(m_scalar * msi);
00251 q->
setVector(-m_vector * msi);
00252 }
00253
00259 void Quaternion::normalize()
00260 {
00261
float mag =
magnitude();
00262
00263 m_scalar /= mag;
00264 m_vector /= mag;
00265 }
00266
00267
Quaternion Quaternion::normalized()
const
00268
{
00269
float mag =
magnitude();
00270
00271
return Quaternion(m_scalar / mag, m_vector / mag);
00272 }
00273
00274
void Quaternion::normalized(
Quaternion *q)
const
00275
{
00276
float mag =
magnitude();
00277
00278 q->
setScalar(m_scalar / mag);
00279 q->
setVector(m_vector / mag);
00280 }
00281
00282
00283
00284
00285
00286
00287
float Quaternion::dotProduct(
const Quaternion &q)
const
00288
{
00289
return m_scalar * q.
m_scalar + m_vector.dotProduct(q.
m_vector);
00290 }
00291
00292
00300 Quaternion Quaternion::slerped(
float u,
const Quaternion &source,
const Quaternion &dest)
const
00301
{
00302
float cosAngle = source.
dotProduct(dest);
00303
float angle, sinAngle, a, b;
00304
00305
if(cosAngle > 0)
00306 {
00307 angle = acosf(cosAngle);
00308 sinAngle = sinf(angle);
00309 a = sinf((1.0f - u) * angle) / sinAngle;
00310 b = sinf(u * angle) / sinAngle;
00311 }
00312
else
00313 {
00314 angle = 2 * Math::pi - acosf(cosAngle);
00315 sinAngle = sinf(angle);
00316 a = sinf((1.0f - u) * angle) / sinAngle;
00317 b = -sinf(u * angle) / sinAngle;
00318 }
00319
00320
return (a * source + b * dest).normalized();
00321 }
00322
00323
00324
00325
00326
00327
00328
Quaternion Quaternion::createFromAxisAngle(
const Vector3 &axis,
float degrees)
00329 {
00330
while(degrees < 0.0f)
00331 degrees += 360.0f;
00332
while(degrees >= 360.0f)
00333 degrees -= 360.0f;
00334
00335
float halfAngle = Math::degToRad(degrees * 0.5f);
00336
00337
return Quaternion(
00338 cosf(halfAngle),
00339 sinf(halfAngle) * axis
00340 );
00341 }
00342
00349 void Quaternion::fromAxisAngle(
const Vector3 &axis,
float degrees)
00350 {
00351
while(degrees < 0.0f)
00352 degrees += 360.0f;
00353
while(degrees >= 360.0f)
00354 degrees -= 360.0f;
00355
00356
float halfAngle = Math::degToRad(degrees * 0.5f);
00357
00358 m_scalar = cosf(halfAngle);
00359 m_vector = sinf(halfAngle) * axis;
00360 }
00361
00362
void Quaternion::toAxisAngle(
Vector3 *axis,
float *degrees)
const
00363
{
00364
00365
00366
00367
00368
00369
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
if(m_scalar > 1 || m_scalar < -1)
00384 {
00385 cerr <<
"The quaternion isn't normalized while converting to axis-angle!!" << endl;
00386
return;
00387 }
00388
00389
if(m_scalar == 1 || m_scalar == -1)
00390 {
00391 *degrees = 0.0f;
00392 *axis =
Vector3(1,0,0);
00393 }
00394
else
00395 {
00396 *degrees = Math::radToDeg(2 * acosf(m_scalar));
00397 *axis = m_vector / sqrtf(1.0f - Math::squared(m_scalar));
00398 }
00399 }
00400
00401
00402
00403
00404
00405
00406
void Quaternion::fromEulerAngle(
float rotX,
float rotY,
float rotZ)
00407 {
00408
Quaternion x, y, z;
00409 x.
fromAxisAngle(Vector3(1.0f, 0.0f, 0.0f), rotX);
00410 y.
fromAxisAngle(Vector3(0.0f, 1.0f, 0.0f), rotY);
00411 z.
fromAxisAngle(Vector3(0.0f, 0.0f, 1.0f), rotZ);
00412
00413 *
this = z * y * x;
00414 }
00415
00416
void Quaternion::fromEulerAngle(
const Vector3 &rot)
00417 {
00418 fromEulerAngle(rot.getX(), rot.getY(), rot.getZ());
00419 }
00420
00421 Vector3 Quaternion::toEulerAngle()
const
00422
{
00424
return Vector3::zero;
00425 }
00426
00427 void Quaternion::toEulerAngle(
float *rotX,
float *rotY,
float *rotZ)
const
00428
{
00430 *rotX = *rotY = *rotZ = 0.0f;
00431 }
00432
00433 void Quaternion::toEulerAngle(
Vector3 *rot)
const
00434
{
00436 *rot = Vector3::zero;
00437 }
00438
00439
00440
00441
00442
00443
00444
void Quaternion::fromMatrix33(
const Matrix33 &matrix)
00445 {
00446
float m00 = matrix.
get(0,0);
00447
float m11 = matrix.
get(1,1);
00448
float m22 = matrix.
get(2,2);
00449
00450 m_scalar = sqrtf(m00 + m11 + m22 + 1.0f) * 0.5f;
00451
00452
float temp = 1 - 2 * m_scalar * m_scalar;
00453 m_vector.
setX(sqrtf((m00 + temp) * 0.5f));
00454 m_vector.
setY(sqrtf((m11 + temp) * 0.5f));
00455 m_vector.
setZ(sqrtf((m22 + temp) * 0.5f));
00456 }
00457
00458
Matrix33 Quaternion::toMatrix33()
const
00459
{
00460
Matrix33 result;
00461
toMatrix33(&result);
00462
return result;
00463 }
00464
00469 void Quaternion::toMatrix33(
Matrix33 *matrix)
const
00470
{
00471 matrix->
identity();
00472
00473
float x2 = m_vector.
getX() * m_vector.
getX();
00474
float y2 = m_vector.
getY() * m_vector.
getY();
00475
float z2 = m_vector.
getZ() * m_vector.
getZ();
00476
00477
float xy = m_vector.
getX() * m_vector.
getY();
00478
float xz = m_vector.
getX() * m_vector.
getZ();
00479
float yz = m_vector.
getY() * m_vector.
getZ();
00480
00481
float sx = m_scalar * m_vector.
getX();
00482
float sy = m_scalar * m_vector.
getY();
00483
float sz = m_scalar * m_vector.
getZ();
00484
00485
00486 matrix->
set(0, 1 - 2 * (y2 + z2));
00487 matrix->
set(1, 2 * (xy - sz));
00488 matrix->
set(2, 2 * (xz + sy));
00489
00490 matrix->
set(3, 2 * (xy + sz));
00491 matrix->
set(4, 1 - 2 * (x2 + z2));
00492 matrix->
set(5, 2 * (yz - sx));
00493
00494 matrix->
set(6, 2 * (xz - sy));
00495 matrix->
set(7, 2 * (yz + sx));
00496 matrix->
set(8, 1 - 2 * (x2 + y2));
00497 }
00498
00499
00500
00501
00502
00503
00504
void Quaternion::print()
const
00505
{
00506 cout << m_scalar <<
", (";
00507 cout << m_vector.
getX() <<
", ";
00508 cout << m_vector.
getY() <<
", ";
00509 cout << m_vector.
getZ() <<
")" << endl;
00510 }
00511
00512 ostream &OpenCAL::Utils::operator<<(ostream &stream,
const Quaternion &q)
00513 {
00514 stream <<
"[" << q.
m_scalar <<
", " << q.
m_vector <<
"]";
00515
return stream;
00516 }