Subversion Repositories Games.Descent

Rev

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