Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 1 | /* |
2 | * Portions of this file are copyright Rebirth contributors and licensed as |
||
3 | * described in COPYING.txt. |
||
4 | * Portions of this file are copyright Parallax Software and licensed |
||
5 | * according to the Parallax license below. |
||
6 | * See COPYING.txt for license details. |
||
7 | |||
8 | THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX |
||
9 | SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO |
||
10 | END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A |
||
11 | ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS |
||
12 | IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS |
||
13 | SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE |
||
14 | FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE |
||
15 | CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS |
||
16 | AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. |
||
17 | COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. |
||
18 | */ |
||
19 | |||
20 | /* |
||
21 | * |
||
22 | * Header file for vector/matrix library |
||
23 | * |
||
24 | */ |
||
25 | |||
26 | #pragma once |
||
27 | |||
28 | #ifdef __cplusplus |
||
29 | #include <cassert> |
||
30 | #include <cstdint> |
||
31 | #include <utility> |
||
32 | #include "fwd-vecmat.h" |
||
33 | |||
34 | namespace dcx { |
||
35 | |||
36 | //The basic fixed-point vector. Access elements by name or position |
||
37 | struct vms_vector |
||
38 | { |
||
39 | fix x, y, z; |
||
40 | }; |
||
41 | |||
42 | class vm_distance |
||
43 | { |
||
44 | public: |
||
45 | fix d = 0; |
||
46 | /* Default constructor only required because Fcd_cache,SoundObjects |
||
47 | * have global scope instances of vm_distance. They should be |
||
48 | * converted to construct as needed, then the default constructor |
||
49 | * should be removed. |
||
50 | */ |
||
51 | constexpr vm_distance() = default; |
||
52 | constexpr explicit vm_distance(const fix &f) : |
||
53 | d(f) |
||
54 | { |
||
55 | } |
||
56 | template <typename T> |
||
57 | vm_distance &operator+=(const T &rhs) |
||
58 | { |
||
59 | return *this = (*this + rhs); |
||
60 | } |
||
61 | template <typename T> |
||
62 | vm_distance &operator*=(const T &rhs) |
||
63 | { |
||
64 | return *this = (*this * rhs); |
||
65 | } |
||
66 | template <typename T> |
||
67 | vm_distance &operator/=(const T &rhs) |
||
68 | { |
||
69 | return *this = (*this / rhs); |
||
70 | } |
||
71 | constexpr vm_distance operator+(const vm_distance &rhs) const |
||
72 | { |
||
73 | return vm_distance{d + rhs.d}; |
||
74 | } |
||
75 | constexpr vm_distance operator*(const int &f) const |
||
76 | { |
||
77 | return vm_distance{d * f}; |
||
78 | } |
||
79 | constexpr vm_distance operator/(const int &f) const |
||
80 | { |
||
81 | return vm_distance{d / f}; |
||
82 | } |
||
83 | constexpr bool operator<(const fix &f) const |
||
84 | { |
||
85 | return d < f; |
||
86 | } |
||
87 | constexpr bool operator<(const vm_distance &rhs) const |
||
88 | { |
||
89 | return d < rhs.d; |
||
90 | } |
||
91 | /* Clang chokes using a template operator> to swap the arguments. |
||
92 | * Use a non-template operator> for the one needed type. |
||
93 | */ |
||
94 | constexpr bool operator>(const fix &f) const |
||
95 | { |
||
96 | return d > f; |
||
97 | } |
||
98 | template <typename T> |
||
99 | bool operator>(const T &t) const = delete; |
||
100 | constexpr explicit operator bool() const { return d; } |
||
101 | #ifndef __clang__ |
||
102 | /* When this catch-all overload is defined, clang becomes confused |
||
103 | * and treats all arithmetic operations as ambiguous because it |
||
104 | * cannot choose between the deleted template function and the |
||
105 | * non-deleted operator fix(). |
||
106 | */ |
||
107 | template <typename T> |
||
108 | operator T() const = delete; |
||
109 | #endif |
||
110 | constexpr operator fix() const |
||
111 | { |
||
112 | return d; |
||
113 | } |
||
114 | constexpr vm_distance_squared operator*(const vm_distance &) const; |
||
115 | }; |
||
116 | |||
117 | class vm_magnitude : public vm_distance |
||
118 | { |
||
119 | public: |
||
120 | constexpr explicit vm_magnitude(const uint32_t &f) : |
||
121 | vm_distance(f) |
||
122 | { |
||
123 | } |
||
124 | }; |
||
125 | |||
126 | class vm_distance_squared |
||
127 | { |
||
128 | public: |
||
129 | fix64 d2; |
||
130 | vm_distance_squared(const fix &) = delete; |
||
131 | constexpr explicit vm_distance_squared(const fix64 &f2) : |
||
132 | d2(f2) |
||
133 | { |
||
134 | } |
||
135 | constexpr bool operator<(const vm_distance_squared &rhs) const |
||
136 | { |
||
137 | return d2 < rhs.d2; |
||
138 | } |
||
139 | constexpr bool operator>(const vm_distance_squared &rhs) const |
||
140 | { |
||
141 | return d2 > rhs.d2; |
||
142 | } |
||
143 | constexpr bool operator>=(const vm_distance_squared &rhs) const |
||
144 | { |
||
145 | return !(*this < rhs); |
||
146 | } |
||
147 | template <typename T> |
||
148 | vm_distance_squared &operator-=(const T &rhs) |
||
149 | { |
||
150 | return *this = (*this - rhs); |
||
151 | } |
||
152 | constexpr vm_distance_squared operator-(const fix &) const = delete; |
||
153 | constexpr vm_distance_squared operator-(const fix64 &f2) const |
||
154 | { |
||
155 | return vm_distance_squared{d2 - f2}; |
||
156 | } |
||
157 | explicit operator bool() const { return d2; } |
||
158 | template <typename T> |
||
159 | constexpr operator T() const = delete; |
||
160 | constexpr operator fix64() const |
||
161 | { |
||
162 | return d2; |
||
163 | } |
||
164 | static constexpr vm_distance_squared maximum_value() |
||
165 | { |
||
166 | return vm_distance_squared{INT64_MAX}; |
||
167 | } |
||
168 | static constexpr vm_distance_squared minimum_value() |
||
169 | { |
||
170 | return vm_distance_squared{static_cast<fix64>(0)}; |
||
171 | } |
||
172 | }; |
||
173 | |||
174 | class vm_magnitude_squared : public vm_distance_squared |
||
175 | { |
||
176 | public: |
||
177 | constexpr explicit vm_magnitude_squared(const uint64_t &f2) : |
||
178 | vm_distance_squared(static_cast<fix64>(f2)) |
||
179 | { |
||
180 | } |
||
181 | }; |
||
182 | |||
183 | constexpr vm_distance_squared vm_distance::operator*(const vm_distance &rhs) const |
||
184 | { |
||
185 | return vm_distance_squared{static_cast<fix64>(static_cast<fix>(*this)) * static_cast<fix64>(static_cast<fix>(rhs))}; |
||
186 | } |
||
187 | |||
188 | #define DEFINE_SERIAL_VMS_VECTOR_TO_MESSAGE() \ |
||
189 | DEFINE_SERIAL_UDT_TO_MESSAGE(vms_vector, v, (v.x, v.y, v.z)); \ |
||
190 | ASSERT_SERIAL_UDT_MESSAGE_SIZE(vms_vector, 12) |
||
191 | |||
192 | //Angle vector. Used to store orientations |
||
193 | struct vms_angvec |
||
194 | { |
||
195 | fixang p, b, h; |
||
196 | }; |
||
197 | |||
198 | |||
199 | //A 3x3 rotation matrix. Sorry about the numbering starting with one. |
||
200 | //Ordering is across then down, so <m1,m2,m3> is the first row |
||
201 | struct vms_matrix |
||
202 | { |
||
203 | vms_vector rvec, uvec, fvec; |
||
204 | }; |
||
205 | |||
206 | // Quaternion structure |
||
207 | struct vms_quaternion |
||
208 | { |
||
209 | signed short w, x, y, z; |
||
210 | }; |
||
211 | |||
212 | |||
213 | //Macros/functions to fill in fields of structures |
||
214 | |||
215 | //macro to set a vector to zero. we could do this with an in-line assembly |
||
216 | //macro, but it's probably better to let the compiler optimize it. |
||
217 | //Note: NO RETURN VALUE |
||
218 | static inline void vm_vec_zero(vms_vector &v) |
||
219 | { |
||
220 | v = {}; |
||
221 | } |
||
222 | |||
223 | //macro set set a matrix to the identity. Note: NO RETURN VALUE |
||
224 | |||
225 | // DPH (18/9/98): Begin mod to fix linefeed problem under linux. Uses an |
||
226 | // inline function instead of a multi-line macro to fix CR/LF problems. |
||
227 | |||
228 | // DPH (19/8/98): End changes. |
||
229 | |||
230 | //Global constants |
||
231 | |||
232 | //Here's a handy constant |
||
233 | |||
234 | //negate a vector |
||
235 | static inline void vm_vec_negate(vms_vector &v) |
||
236 | { |
||
237 | v.x = -v.x; |
||
238 | v.y = -v.y; |
||
239 | v.z = -v.z; |
||
240 | } |
||
241 | |||
242 | static inline vms_vector vm_vec_negated(vms_vector v) __attribute_warn_unused_result; |
||
243 | static inline vms_vector vm_vec_negated(vms_vector v) |
||
244 | { |
||
245 | return vm_vec_negate(v), v; |
||
246 | } |
||
247 | |||
248 | //Functions in library |
||
249 | |||
250 | //adds two vectors, fills in dest, returns ptr to dest |
||
251 | //ok for dest to equal either source, but should use vm_vec_add2() if so |
||
252 | static inline vms_vector vm_vec_add (const vms_vector &src0, const vms_vector &src1) __attribute_warn_unused_result; |
||
253 | static inline vms_vector vm_vec_add (const vms_vector &src0, const vms_vector &src1) |
||
254 | { |
||
255 | vms_vector dest; |
||
256 | return vm_vec_add(dest, src0, src1), dest; |
||
257 | } |
||
258 | |||
259 | |||
260 | //subs two vectors, fills in dest, returns ptr to dest |
||
261 | //ok for dest to equal either source, but should use vm_vec_sub2() if so |
||
262 | static inline vms_vector &vm_vec_sub(vms_vector &dest, const vms_vector &src0, const vms_vector &src1) |
||
263 | { |
||
264 | #ifdef DXX_CONSTANT_TRUE |
||
265 | if (DXX_CONSTANT_TRUE(&src0 == &src1)) |
||
266 | DXX_ALWAYS_ERROR_FUNCTION(vm_vec_sub_same_op, "vm_vec_sub with &src0 == &src1"); |
||
267 | else if (DXX_CONSTANT_TRUE(src0.x == src1.x && src0.y == src1.y && src0.z == src1.z)) |
||
268 | DXX_ALWAYS_ERROR_FUNCTION(vm_vec_sub_same_values, "vm_vec_sub with equal value inputs"); |
||
269 | #endif |
||
270 | return _vm_vec_sub(dest, src0, src1); |
||
271 | } |
||
272 | |||
273 | __attribute_warn_unused_result |
||
274 | static inline vms_vector vm_vec_sub (const vms_vector &src0, const vms_vector &src1) |
||
275 | { |
||
276 | vms_vector dest; |
||
277 | return vm_vec_sub(dest, src0, src1), dest; |
||
278 | } |
||
279 | |||
280 | //averages two vectors. returns ptr to dest |
||
281 | //dest can equal either source |
||
282 | static inline vms_vector vm_vec_avg (const vms_vector &src0, const vms_vector &src1) __attribute_warn_unused_result; |
||
283 | static inline vms_vector vm_vec_avg (const vms_vector &src0, const vms_vector &src1) |
||
284 | { |
||
285 | vms_vector dest; |
||
286 | return vm_vec_avg(dest, src0, src1), dest; |
||
287 | } |
||
288 | |||
289 | //scales and copies a vector. returns ptr to dest |
||
290 | #define vm_vec_copy_scale(A,B,...) vm_vec_copy_scale(A, ## __VA_ARGS__, B) |
||
291 | static inline vms_vector vm_vec_copy_scale(vms_vector src, fix s) __attribute_warn_unused_result; |
||
292 | static inline vms_vector vm_vec_copy_scale(vms_vector src, fix s) |
||
293 | { |
||
294 | return vm_vec_scale(src, s), src; |
||
295 | } |
||
296 | |||
297 | //scales a vector, adds it to another, and stores in a 3rd vector |
||
298 | //dest = src1 + k * src2 |
||
299 | static inline vms_vector vm_vec_scale_add(const vms_vector &src1, const vms_vector &src2, fix k) __attribute_warn_unused_result; |
||
300 | static inline vms_vector vm_vec_scale_add(const vms_vector &src1, const vms_vector &src2, fix k) |
||
301 | { |
||
302 | vms_vector dest; |
||
303 | return vm_vec_scale_add(dest, src1, src2, k), dest; |
||
304 | } |
||
305 | |||
306 | static inline vms_vector vm_vec_normalized(vms_vector v) __attribute_warn_unused_result; |
||
307 | static inline vms_vector vm_vec_normalized(vms_vector v) |
||
308 | { |
||
309 | return vm_vec_normalize(v), v; |
||
310 | } |
||
311 | |||
312 | static inline vms_vector vm_vec_normalized_quick(vms_vector v) __attribute_warn_unused_result; |
||
313 | static inline vms_vector vm_vec_normalized_quick(vms_vector v) |
||
314 | { |
||
315 | return vm_vec_normalize_quick(v), v; |
||
316 | } |
||
317 | |||
318 | static inline vms_vector vm_vec_cross(const vms_vector &src0, const vms_vector &src1) __attribute_warn_unused_result; |
||
319 | static inline vms_vector vm_vec_cross(const vms_vector &src0, const vms_vector &src1) |
||
320 | { |
||
321 | vms_vector dest; |
||
322 | return vm_vec_cross(dest, src0, src1), dest; |
||
323 | } |
||
324 | |||
325 | static inline vms_vector vm_vec_normal(const vms_vector &p0, const vms_vector &p1, const vms_vector &p2) __attribute_warn_unused_result; |
||
326 | static inline vms_vector vm_vec_normal(const vms_vector &p0, const vms_vector &p1, const vms_vector &p2) |
||
327 | { |
||
328 | vms_vector dest; |
||
329 | return vm_vec_normal(dest, p0, p1, p2), dest; |
||
330 | } |
||
331 | |||
332 | static inline vms_vector vm_vec_perp (const vms_vector &p0, const vms_vector &p1, const vms_vector &p2) __attribute_warn_unused_result; |
||
333 | static inline vms_vector vm_vec_perp (const vms_vector &p0, const vms_vector &p1, const vms_vector &p2) |
||
334 | { |
||
335 | vms_vector dest; |
||
336 | return vm_vec_perp(dest, p0, p1, p2), dest; |
||
337 | } |
||
338 | |||
339 | static inline vms_matrix vm_angles_2_matrix (const vms_angvec &a) __attribute_warn_unused_result; |
||
340 | static inline vms_matrix vm_angles_2_matrix (const vms_angvec &a) |
||
341 | { |
||
342 | vms_matrix m; |
||
343 | return vm_angles_2_matrix(m, a), m; |
||
344 | } |
||
345 | |||
346 | static inline vms_matrix vm_vector_2_matrix (const vms_vector &fvec, const vms_vector *uvec, const vms_vector *rvec) __attribute_warn_unused_result; |
||
347 | static inline vms_matrix vm_vector_2_matrix (const vms_vector &fvec, const vms_vector *uvec, const vms_vector *rvec) |
||
348 | { |
||
349 | vms_matrix m; |
||
350 | return vm_vector_2_matrix(m, fvec, uvec, rvec), m; |
||
351 | } |
||
352 | |||
353 | static inline vms_vector vm_vec_rotate (const vms_vector &src, const vms_matrix &m) __attribute_warn_unused_result; |
||
354 | static inline vms_vector vm_vec_rotate (const vms_vector &src, const vms_matrix &m) |
||
355 | { |
||
356 | vms_vector dest; |
||
357 | return vm_vec_rotate(dest, src, m), dest; |
||
358 | } |
||
359 | |||
360 | //transpose a matrix in place. returns ptr to matrix |
||
361 | static inline void vm_transpose_matrix(vms_matrix &m) |
||
362 | { |
||
363 | using std::swap; |
||
364 | swap(m.uvec.x, m.rvec.y); |
||
365 | swap(m.fvec.x, m.rvec.z); |
||
366 | swap(m.fvec.y, m.uvec.z); |
||
367 | } |
||
368 | |||
369 | static inline vms_matrix vm_transposed_matrix(vms_matrix m) __attribute_warn_unused_result; |
||
370 | static inline vms_matrix vm_transposed_matrix(vms_matrix m) |
||
371 | { |
||
372 | vm_transpose_matrix(m); |
||
373 | return m; |
||
374 | } |
||
375 | |||
376 | //mulitply 2 matrices, fill in dest. returns ptr to dest |
||
377 | static inline void vm_matrix_x_matrix(vms_matrix &dest, const vms_matrix &src0, const vms_matrix &src1) |
||
378 | { |
||
379 | #ifdef DXX_CONSTANT_TRUE |
||
380 | if (DXX_CONSTANT_TRUE(&dest == &src0)) |
||
381 | DXX_ALWAYS_ERROR_FUNCTION(vm_matrix_x_matrix_dest_src0, "vm_matrix_x_matrix with &dest == &src0"); |
||
382 | else if (DXX_CONSTANT_TRUE(&dest == &src1)) |
||
383 | DXX_ALWAYS_ERROR_FUNCTION(vm_matrix_x_matrix_dest_src1, "vm_matrix_x_matrix with &dest == &src1"); |
||
384 | #endif |
||
385 | assert(&dest != &src0); |
||
386 | assert(&dest != &src1); |
||
387 | return _vm_matrix_x_matrix(dest, src0, src1); |
||
388 | } |
||
389 | |||
390 | static inline vms_matrix vm_matrix_x_matrix(const vms_matrix &src0, const vms_matrix &src1) __attribute_warn_unused_result; |
||
391 | static inline vms_matrix vm_matrix_x_matrix(const vms_matrix &src0, const vms_matrix &src1) |
||
392 | { |
||
393 | vms_matrix dest; |
||
394 | vm_matrix_x_matrix(dest, src0, src1); |
||
395 | return dest; |
||
396 | } |
||
397 | |||
398 | static inline vms_angvec vm_extract_angles_matrix (const vms_matrix &m) __attribute_warn_unused_result; |
||
399 | static inline vms_angvec vm_extract_angles_matrix (const vms_matrix &m) |
||
400 | { |
||
401 | vms_angvec a; |
||
402 | return vm_extract_angles_matrix(a, m), a; |
||
403 | } |
||
404 | |||
405 | //fills in fields of an angle vector |
||
406 | static inline void vm_angvec_make(vms_angvec *v, fixang p, fixang b, fixang h) |
||
407 | { |
||
408 | v->p = p; |
||
409 | v->b = b; |
||
410 | v->h = h; |
||
411 | } |
||
412 | |||
413 | } |
||
414 | |||
415 | #endif |