zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Quaternion.cpp
Go to the documentation of this file.
1 /* This file is part of the Zenipex Library (zenilib).
2  * Copyright (C) 2011 Mitchell Keith Bloch (bazald).
3  *
4  * zenilib is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * zenilib is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with zenilib. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <zeni.h>
19 
20 #include <cmath>
21 
22 #include <Zeni/Define.h>
23 
24 namespace Zeni {
25 
26  Quaternion::Quaternion(const float &t, const Vector3f &s, const bool &degenerate_)
27  : time(t),
28  space(s),
29  degenerate(s.degenerate || degenerate_)
30  {
31  }
32 
34  const Vector3f axis = source % destination;
35  const float angle = source.angle_between(destination);
36  Quaternion rotation = Quaternion::Axis_Angle(axis, angle);
37 
38  if(rotation.degenerate) {
39  if(INFINTESSIMAL(angle))
40  return Quaternion();
41  else {
42  const Vector3f pos(fabsf(source.i), fabsf(source.j), fabsf(source.k));
43 
44  if(pos.i < pos.j && pos.i < pos.k)
45  rotation = Quaternion::Axis_Angle(source % Vector3f(1.0f, 0.0f, 0.0f), Global::pi);
46  else if(pos.j < pos.k)
47  rotation = Quaternion::Axis_Angle(source % Vector3f(0.0f, 1.0f, 0.0f), Global::pi);
48  else
49  rotation = Quaternion::Axis_Angle(source % Vector3f(0.0f, 0.0f, 1.0f), Global::pi);
50  }
51  }
52 
53  return rotation.normalized();
54  }
55 
56  Quaternion Quaternion::Axis_Angle(const Vector3f &v, const float &theta) {
57  const float half_theta = 0.5f * theta;
58 
59  const float time = float(cos(half_theta));
60  const float space_coeff = float(sin(half_theta));
61  const Vector3f space_vec = v.normalized();
62 
63  return Quaternion(time, space_coeff * space_vec, space_vec.degenerate).normalized();
64  }
65 
66  Quaternion Quaternion::Forward_Up(const Vector3f &destination_forward,
67  const Vector3f &destination_up,
68  const Vector3f &default_forward,
69  const Vector3f &default_up)
70  {
71  const Vector3f axis0 = default_forward % destination_forward;
72  const float angle0 = default_forward.angle_between(destination_forward);
73 
74  Quaternion rotation0 = Quaternion::Axis_Angle(axis0, angle0);
75  if(rotation0.degenerate) {
76  if(INFINTESSIMAL(angle0))
77  rotation0 = Quaternion();
78  else
79  rotation0 = Quaternion::Axis_Angle(default_up, Global::pi);
80  }
81 
82  const Vector3f intermediate_up = rotation0 * default_up;
83  const Vector3f axis1 = intermediate_up % destination_up;
84  const float angle1 = intermediate_up.angle_between(destination_up);
85 
86  Quaternion rotation1 = Quaternion::Axis_Angle(axis1, angle1);
87  if(rotation1.degenerate) {
88  if(INFINTESSIMAL(angle1))
89  rotation1 = Quaternion();
90  else
91  rotation1 = Quaternion::Axis_Angle(destination_forward, Global::pi);
92  }
93 
94  return (rotation1 * rotation0).normalized();
95  }
96 
97  Quaternion::Quaternion(const float &yaw, const float &pitch, const float &roll, const bool &degenerate_)
98  : degenerate(degenerate_)
99  {
100  const float half_yaw = 0.5f * yaw;
101  const float half_pitch = 0.5f * pitch;
102  const float half_roll = 0.5f * roll;
103 
104  const float shy = float(sin(half_yaw));
105  const float shp = float(sin(half_pitch));
106  const float shr = float(sin(half_roll));
107  const float chy = float(cos(half_yaw));
108  const float chp = float(cos(half_pitch));
109  const float chr = float(cos(half_roll));
110 
111  time = chr * chp * chy + shr * shp * shy;
112  space.i = shr * chp * chy - chr * shp * shy;
113  space.j = chr * shp * chy + shr * chp * shy;
114  space.k = chr * chp * shy - shr * shp * chy;
115  }
116 
117  Quaternion::Quaternion(const Quaternion &rhs, const bool &degenerate_)
118  : time(rhs.time),
119  space(rhs.space),
120  degenerate(rhs.degenerate || degenerate_)
121  {
122  }
123 
125  float mplier = magnitude();
126 
127  if(INFINTESSIMAL(mplier)) {
128  degenerate = true;
129  return *this;
130  }
131 
132  mplier = 1.0f / mplier;
133 
134  time *= mplier;
135  space *= mplier;
136 
137  return *this;
138  }
139 
141  float mplier = magnitude();
142 
143  if(INFINTESSIMAL(mplier))
144  return Quaternion(*this, true);
145 
146  mplier = 1.0f / mplier;
147 
148  return Quaternion(time * mplier, space * mplier);
149  }
150 
151  std::ostream & serialize(std::ostream &os, const Quaternion &value) {
152  return serialize(serialize(os, value.time), value.space);
153  }
154 
155  std::istream & unserialize(std::istream &is, Quaternion &value) {
156  return unserialize(unserialize(is, value.time), value.space);
157  }
158 
159 }
160 
161 #include <Zeni/Undefine.h>
static Quaternion Vector3f_to_Vector3f(const Vector3f &destination, const Vector3f &source)
Create a Quaternion rotating to one Vector3f from another.
Definition: Quaternion.cpp:33
GLdouble s
Definition: glew.h:1376
GLclampf f
Definition: glew.h:3390
GLdouble angle
Definition: glew.h:8396
static Quaternion Axis_Angle(const Vector3f &v, const float &theta)
Create a Quaternion from an Axis/Angle pair.
Definition: Quaternion.cpp:56
GLdouble GLdouble t
Definition: glew.h:1384
Vector3f space
Definition: Quaternion.h:105
std::istream & unserialize(std::istream &is, Color &value)
Definition: Color.cpp:72
std::ostream & serialize(std::ostream &os, const Color &value)
Definition: Color.cpp:68
A Featureful 3-Space Vector Class.
Definition: Vector3f.h:58
const GLdouble * v
Definition: glew.h:1377
bool degenerate
Definition: Vector3f.h:123
const float pi
pi == 3.1415926...
Definition: Vector3f.cpp:27
Quaternion normalized() const
Get the normalized vector.
Definition: Quaternion.cpp:140
A Featureful Quaternion Class.
Definition: Quaternion.h:44
static Quaternion Forward_Up(const Vector3f &destination_forward, const Vector3f &destination_up, const Vector3f &default_forward=ZENI_DEFAULT_FORWARD_VECTOR, const Vector3f &default_up=ZENI_DEFAULT_UP_VECTOR)
Create a Quaternion from a Forward/Up Vector3f pair.
Definition: Quaternion.cpp:66
float angle_between(const Vector3f &rhs) const
Find the angle between the Vector3fs.
Definition: Vector3f.hxx:178
float magnitude() const
Get the magnitude of the vector.
Definition: Quaternion.hxx:123
double sin(double x)
Definition: s_sin.c:56
EGLSurface EGLint void ** value
Definition: eglext.h:301
Quaternion(const bool &degenerate_=false)
Definition: Quaternion.hxx:34
double cos(double x)
Definition: s_cos.c:56
GLsizei GLsizei GLchar * source
Definition: gl2ext.h:994
Quaternion & normalize()
Normalize the vector.
Definition: Quaternion.cpp:124
Vector3f normalized() const
Get the normalized vector.
Definition: Vector3f.cpp:58
#define INFINTESSIMAL(x)
Definition: Define.h:134