-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathquat.h
157 lines (127 loc) · 3.41 KB
/
quat.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#ifndef QUAT_H
#define QUAT_H
#include <iostream>
#include <cassert>
#include <cmath>
#include "cvec.h"
#include "matrix4.h"
// Forward declarations used in the definition of Quat;
class Quat;
double dot(const Quat& q, const Quat& p);
double norm2(const Quat& q);
Quat inv(const Quat& q);
Quat normalize(const Quat& q);
Matrix4 quatToMatrix(const Quat& q);
class Quat {
Cvec4 q_; // layout is: q_[0]==w, q_[1]==x, q_[2]==y, q_[3]==z
public:
double operator [] (const int i) const {
return q_[i];
}
double& operator [] (const int i) {
return q_[i];
}
double operator () (const int i) const {
return q_[i];
}
double& operator () (const int i) {
return q_[i];
}
Quat() : q_(1,0,0,0) {}
Quat(const double w, const Cvec3& v) : q_(w, v[0], v[1], v[2]) {}
Quat(const double w, const double x, const double y, const double z) : q_(w, x,y,z) {}
Quat& operator += (const Quat& a) {
q_ += a.q_;
return *this;
}
Quat& operator -= (const Quat& a) {
q_ -= a.q_;
return *this;
}
Quat& operator *= (const double a) {
q_ *= a;
return *this;
}
Quat& operator /= (const double a) {
q_ /= a;
return *this;
}
Quat operator + (const Quat& a) const {
return Quat(*this) += a;
}
Quat operator - (const Quat& a) const {
return Quat(*this) -= a;
}
Quat operator * (const double a) const {
return Quat(*this) *= a;
}
Quat operator / (const double a) const {
return Quat(*this) /= a;
}
Quat operator * (const Quat& a) const {
const Cvec3 u(q_[1], q_[2], q_[3]), v(a.q_[1], a.q_[2], a.q_[3]);
return Quat(q_[0]*a.q_[0] - dot(u, v), (v*q_[0] + u*a.q_[0]) + cross(u, v));
}
Cvec4 operator * (const Cvec4& a) const {
const Quat r = *this * (Quat(0, a[0], a[1], a[2]) * inv(*this));
return Cvec4(r[1], r[2], r[3], a[3]);
}
static Quat makeXRotation(const double ang) {
Quat r;
const double h = 0.5 * ang * CS175_PI/180;
r.q_[1] = std::sin(h);
r.q_[0] = std::cos(h);
return r;
}
static Quat makeYRotation(const double ang) {
Quat r;
const double h = 0.5 * ang * CS175_PI/180;
r.q_[2] = std::sin(h);
r.q_[0] = std::cos(h);
return r;
}
static Quat makeZRotation(const double ang) {
Quat r;
const double h = 0.5 * ang * CS175_PI/180;
r.q_[3] = std::sin(h);
r.q_[0] = std::cos(h);
return r;
}
};
inline double dot(const Quat& q, const Quat& p) {
double s = 0.0;
for (int i = 0; i < 4; ++i) {
s += q(i) * p(i);
}
return s;
}
inline double norm2(const Quat& q) {
return dot(q, q);
}
inline Quat inv(const Quat& q) {
const double n = norm2(q);
assert(n > CS175_EPS2);
return Quat(q(0), -q(1), -q(2), -q(3)) * (1.0/n);
}
inline Quat normalize(const Quat& q) {
return q / std::sqrt(norm2(q));
}
inline Matrix4 quatToMatrix(const Quat& q) {
Matrix4 r;
const double n = norm2(q);
if (n < CS175_EPS2)
return Matrix4(0);
const double two_over_n = 2/n;
r(0, 0) -= (q(2)*q(2) + q(3)*q(3)) * two_over_n;
r(0, 1) += (q(1)*q(2) - q(0)*q(3)) * two_over_n;
r(0, 2) += (q(1)*q(3) + q(2)*q(0)) * two_over_n;
r(1, 0) += (q(1)*q(2) + q(0)*q(3)) * two_over_n;
r(1, 1) -= (q(1)*q(1) + q(3)*q(3)) * two_over_n;
r(1, 2) += (q(2)*q(3) - q(1)*q(0)) * two_over_n;
r(2, 0) += (q(1)*q(3) - q(2)*q(0)) * two_over_n;
r(2, 1) += (q(2)*q(3) + q(1)*q(0)) * two_over_n;
r(2, 2) -= (q(1)*q(1) + q(2)*q(2)) * two_over_n;
assert(isAffine(r));
return r;
}
#endif