-
Notifications
You must be signed in to change notification settings - Fork 1
/
quaternion.h
141 lines (110 loc) · 2.21 KB
/
quaternion.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#ifndef QUATERNION_H
#define QUATERNION_H
#include <cmath>
#include "vec3d.h"
class Vec4D {
public:
float x,y,z,w;
Vec4D(float x0=0.0f, float y0=0.0f, float z0=0.0f, float w0=0.0f) : x(x0), y(y0), z(z0), w(w0) {}
Vec4D(const Vec4D& v) : x(v.x), y(v.y), z(v.z), w(v.w) {}
Vec4D(const Vec3D& v, const float w0) : x(v.x), y(v.y), z(v.z), w(w0) {}
Vec4D& operator= (const Vec4D &v) {
x = v.x;
y = v.y;
z = v.z;
w = v.w;
return *this;
}
const Vec4D operator+ (const Vec4D &v) const
{
Vec4D r(x+v.x,y+v.y,z+v.z,w+v.w);
return r;
}
const Vec4D operator- (const Vec4D &v) const
{
Vec4D r(x-v.x,y-v.y,z-v.z,w-v.w);
return r;
}
const Vec4D operator* (float d) const
{
Vec4D r(x*d,y*d,z*d,w*d);
return r;
}
friend Vec4D operator* (float d, const Vec4D& v)
{
return v * d;
}
Vec4D& operator+= (const Vec4D &v)
{
x += v.x;
y += v.y;
z += v.z;
w += v.w;
return *this;
}
Vec4D& operator-= (const Vec4D &v)
{
x -= v.x;
y -= v.y;
z -= v.z;
w -= v.w;
return *this;
}
Vec4D& operator*= (float d)
{
x *= d;
y *= d;
z *= d;
w *= d;
return *this;
}
float operator* (const Vec4D &v) const
{
return x*v.x + y*v.y + z*v.z + w*v.w;
}
float lengthSquared() const
{
return x*x+y*y+z*z+w*w;
}
float length() const
{
return sqrt(x*x+y*y+z*z+w*w);
}
Vec4D& normalize()
{
this->operator*= (1.0f/length());
return *this;
}
operator float*()
{
return (float*)this;
}
Vec3D xyz() const
{
return Vec3D(x,y,z);
}
};
class Quaternion: public Vec4D {
public:
Quaternion(float x0=0.0f, float y0=0.0f, float z0=0.0f, float w0=1.0f): Vec4D(x0,y0,z0,w0) {}
Quaternion(const Vec4D& v) : Vec4D(v) {}
Quaternion(const Vec3D& v, const float w0) : Vec4D(v, w0) {}
static const Quaternion slerp(const float r, const Quaternion &v1, const Quaternion &v2)
{
// SLERP
float dot = v1*v2;
if (fabs(dot) > 0.9995f) {
// fall back to LERP
return Quaternion::lerp(r, v1, v2);
}
float a = acosf(dot) * r;
Quaternion q = (v2 - v1 * dot);
q.normalize();
return v1 * cosf(a) + q * sinf(a);
}
static const Quaternion lerp(const float r, const Quaternion &v1, const Quaternion &v2)
{
return v1*(1.0f-r) + v2*r;
}
};
#endif