Simulant  21.12-194
A portable game engine for Windows, OSX, Linux, Dreamcast, and PSP
vec3.h
1 #pragma once
2 
3 #include <cmath>
4 #include "../utils/unicode.h"
5 #include "utils.h"
6 #include "../utils/formatter.h"
7 
8 #ifdef __DREAMCAST__
9 #include <kos.h>
10 #endif
11 
12 namespace smlt {
13 
14 struct Vec2;
15 struct Quaternion;
16 struct Mat4;
17 struct Degrees;
18 struct Mat3;
19 struct Mat4;
20 struct Vec4;
21 class AABB;
22 
23 struct Vec3 {
24 private:
25  friend struct Quaternion;
26  friend struct Mat4;
27  friend struct Mat3;
28  friend struct Vec2;
29  friend struct Ray;
30 
31 public:
32  static const Vec3 NEGATIVE_X;
33  static const Vec3 POSITIVE_X;
34  static const Vec3 NEGATIVE_Y;
35  static const Vec3 POSITIVE_Y;
36  static const Vec3 POSITIVE_Z;
37  static const Vec3 NEGATIVE_Z;
38 
39  static const Vec3 BACK;
40  static const Vec3 DOWN;
41  static const Vec3 FORWARD;
42  static const Vec3 LEFT;
43  static const Vec3 ONE;
44  static const Vec3 RIGHT;
45  static const Vec3 UP;
46  static const Vec3 ZERO;
47 
48  float x;
49  float y;
50  float z;
51 
52  Vec3():
53  x(0.0f),
54  y(0.0f),
55  z(0.0f) {
56  }
57 
58  Vec3(float xyz):
59  x(xyz), y(xyz), z(xyz) {}
60 
61  Vec3(float x, float y):
62  x(x), y(y), z(0) {}
63 
64  Vec3(float x, float y, float z):
65  x(x), y(y), z(z) {
66  }
67 
68  Vec3(const Vec2& v2, float z);
69  Vec3(const Vec3& v) = default;
70 
71  Vec3 operator+(const Vec3& rhs) const {
72  return Vec3(x + rhs.x, y + rhs.y, z + rhs.z);
73  }
74 
75  Vec3& operator+=(const Vec3& rhs) {
76  *this = *this + rhs;
77  return *this;
78  }
79 
80  Vec3 operator-(const Vec3& rhs) const {
81  return Vec3(x - rhs.x, y - rhs.y, z - rhs.z);
82  }
83 
84  Vec3& operator-=(const Vec3& rhs) {
85  *this = *this - rhs;
86  return *this;
87  }
88 
89  Vec3 operator*(const Vec3& rhs) const {
90  return Vec3(x * rhs.x, y * rhs.y, z * rhs.z);
91  }
92 
93  Vec3 operator*(float rhs) const {
94  Vec3 result(x * rhs, y * rhs, z * rhs);
95  return result;
96  }
97 
98  Vec3& operator*=(float rhs) {
99  *this = *this * rhs;
100  return *this;
101  }
102 
103  Vec3& operator/=(float rhs) {
104  *this = *this / rhs;
105  return *this;
106  }
107 
108  Vec3 operator/(float rhs) const {
109  Vec3 result(x / rhs, y / rhs, z / rhs);
110  return result;
111  }
112 
113  bool equals(const Vec3& rhs) const {
114  return x == rhs.x && y == rhs.y && z == rhs.z;
115  }
116 
117  bool operator==(const Vec3& rhs) const {
118  return (*this - rhs).length_squared() < EPSILON;
119  }
120 
121  bool operator!=(const Vec3& rhs) const {
122  return !(*this == rhs);
123  }
124 
125  void set(float x, float y, float z) {
126  this->x = x;
127  this->y = y;
128  this->z = z;
129  }
130 
131  float length() const {
132  #ifdef __DREAMCAST__
133  float r;
134  vec3f_length(x, y, z, r);
135  return r;
136  #else
137  return sqrtf(length_squared());
138  #endif
139  }
140 
141  float length_squared() const {
142  return x * x + y * y + z * z;
143  }
144 
145  const Vec3 normalized() const {
146  #ifdef __DREAMCAST__
147  Vec3 ret(x, y, z);
148  vec3f_normalize(ret.x, ret.y, ret.z);
149  return ret;
150  #else
151  float l = 1.0f / length();
152  return Vec3(
153  x * l,
154  y * l,
155  z * l
156  );
157  #endif
158  }
159 
160  void normalize() {
161  #ifdef __DREAMCAST__
162  vec3f_normalize(x, y, z);
163  #else
164  float l = 1.0f / length();
165 
166  x *= l;
167  y *= l;
168  z *= l;
169  #endif
170  }
171 
172  Vec3 lerp(const Vec3& end, float t) const {
173  t = std::min(t, 1.0f);
174  t = std::max(t, 0.0f);
175 
176  return Vec3(
177  fmaf((end.x - x), t, x),
178  fmaf((end.y - y), t, y),
179  fmaf((end.z - z), t, z)
180  );
181  }
182 
183  Vec3 rotated_by(const Quaternion& q) const;
184 
185  Vec3 rotated_by(const Mat3& rot) const;
186 
187  /* Note: We do *not* supply multiply operators with Mat4 because
188  * the behaviour you want depends on whether want translation or not
189  * (e.g. is this a point in space or a vector). Instead we provide
190  * rotated_by() and transformed_by() the former assumes a W component of
191  * 0 whereas the latter assumes a W component of 1.0
192  */
193 
194  Vec3 rotated_by(const Mat4& rot) const;
195 
196  Vec3 transformed_by(const Mat4& trans) const;
197 
198  Vec3 project_onto_vec3(const Vec3& projection_target) const {
199  Vec3 unitW = this->normalized();
200  Vec3 unitV = projection_target.normalized();
201 
202  float cos0 = unitW.dot(unitV);
203 
204  unitV *= (this->length() * cos0);
205 
206  return unitV;
207  }
208 
209  float dot(const Vec3& rhs) const {
210  #ifdef __DREAMCAST__
211  float r;
212  vec3f_dot(x, y, z, rhs.x, rhs.y, rhs.z, r);
213  return r;
214  #else
215  return x * rhs.x + y * rhs.y + z * rhs.z;
216  #endif
217  }
218 
219  Vec3 cross(const Vec3& rhs) const {
220  Vec3 ret;
221 
222  float a = (z * rhs.y); // fmul
223  float b = (x * rhs.z); // fmul
224  a = -a; // fneg
225  float c = (y * rhs.x); // fmul
226  b = -b; // fneg
227  ret.x = ::fmaf(y, rhs.z, a); // fmac
228  c = -c; // fneg
229  ret.y = ::fmaf(z, rhs.x, b); // fmac
230  ret.z = ::fmaf(x, rhs.y, c); // fmac
231 
232  return ret;
233  }
234 
235  Vec3 limit(float l) {
236  if(length() > l) {
237  normalize();
238  *this *= l;
239  }
240 
241  return *this;
242  }
243 
244  float distance_to(const AABB& aabb) const;
245 
246  template<typename Container>
247  static Vec3 find_average(const Container& vectors) {
248  Vec3 ret;
249  for(auto& v: vectors) {
250  ret += v;
251  }
252 
253  ret /= float(vectors.size());
254  return ret;
255  }
256 
257  static float distance(const smlt::Vec3& lhs, const smlt::Vec3& rhs) {
258  return (rhs - lhs).length();
259  }
260 
261  static float sqr_distance(const smlt::Vec3& lhs, const smlt::Vec3& rhs) {
262  return (rhs - lhs).length_squared();
263  }
264 
265  inline Vec3 parallel_component(const Vec3& unit_basis) const {
266  const float projection = this->dot(unit_basis);
267  return unit_basis * projection;
268  }
269 
270  // return component of vector perpendicular to a unit basis vector
271  // (IMPORTANT NOTE: assumes "basis" has unit magnitude (length==1))
272 
273  inline Vec3 perpendicular_component (const Vec3& unit_basis) const {
274  return (*this) - parallel_component(unit_basis);
275  }
276 
277  friend std::ostream& operator<<(std::ostream& stream, const Vec3& vec);
278 
279  Vec3 perpendicular() const;
280  Vec3 random_deviant(const Degrees& angle, const Vec3 up=Vec3()) const;
281 
282  Vec2 xy() const;
283  Vec4 xyzw(float w=1.0f) const;
284 
285  /* Returns the Quaternion rotation between this vector
286  * and `dir` */
287  Quaternion rotation_to(const Vec3& dir) const;
288 };
289 
290 std::ostream& operator<<(std::ostream& stream, const Vec3& vec);
291 
292 Vec3 operator*(float lhs, const Vec3& rhs);
293 Vec3 operator/(float lhs, const Vec3& rhs);
294 Vec3 operator-(const Vec3& vec);
295 
296 }
smlt::Mat4
Definition: mat4.h:25
smlt::Vec3
Definition: vec3.h:23
smlt::Quaternion
Definition: quaternion.h:24
smlt::Mat3
Definition: mat3.h:13
smlt::Ray
Definition: ray.h:8
smlt
Definition: animation.cpp:25
smlt::Degrees
Definition: degrees.h:7
smlt::AABB
Definition: aabb.h:22
smlt::Vec4
Definition: vec4.h:11
smlt::Vec2
Definition: vec2.h:13