diff --git a/common/include/vecmat.h b/common/include/vecmat.h index 8f5555dc8..af384a135 100644 --- a/common/include/vecmat.h +++ b/common/include/vecmat.h @@ -28,6 +28,7 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #include "maths.h" #ifdef __cplusplus +#include #include "dxxsconf.h" #include @@ -37,6 +38,56 @@ struct vms_vector fix x, y, z; }; +class vm_distance +{ +public: + fix d; + constexpr explicit vm_distance(const fix &f) : + d(f) + { + } + template + operator T() const = delete; + constexpr operator fix() const + { + return d; + } +}; + +class vm_magnitude : public vm_distance +{ +public: + constexpr explicit vm_magnitude(const uint32_t &f) : + vm_distance(f) + { + } +}; + +class vm_distance_squared +{ +public: + fix64 d2; + constexpr explicit vm_distance_squared(const fix64 &f2) : + d2(f2) + { + } + template + operator T() const = delete; + constexpr operator fix64() const + { + return d2; + } +}; + +class vm_magnitude_squared : public vm_distance_squared +{ +public: + constexpr explicit vm_magnitude_squared(const uint64_t &f2) : + vm_distance_squared(f2) + { + } +}; + #define DEFINE_SERIAL_VMS_VECTOR_TO_MESSAGE() \ DEFINE_SERIAL_UDT_TO_MESSAGE(vms_vector, v, (v.x, v.y, v.z)); \ ASSERT_SERIAL_UDT_MESSAGE_SIZE(vms_vector, 12) @@ -178,29 +229,35 @@ void vm_vec_scale_add2 (vms_vector &dest, const vms_vector &src, fix k); //dest *= n/d void vm_vec_scale2 (vms_vector &dest, fix n, fix d); -fix64 vm_vec_mag2 (const vms_vector &v) __attribute_warn_unused_result; +__attribute_warn_unused_result +vm_magnitude_squared vm_vec_mag2(const vms_vector &v); //returns magnitude of a vector -fix vm_vec_mag (const vms_vector &v) __attribute_warn_unused_result; +__attribute_warn_unused_result +vm_magnitude vm_vec_mag(const vms_vector &v); //computes the distance between two points. (does sub and mag) -fix vm_vec_dist (const vms_vector &v0, const vms_vector &v1) __attribute_warn_unused_result; -fix64 vm_vec_dist2 (const vms_vector &v0, const vms_vector &v1) __attribute_warn_unused_result; +__attribute_warn_unused_result +vm_distance vm_vec_dist(const vms_vector &v0, const vms_vector &v1); +__attribute_warn_unused_result +vm_distance_squared vm_vec_dist2(const vms_vector &v0, const vms_vector &v1); //computes an approximation of the magnitude of the vector //uses dist = largest + next_largest*3/8 + smallest*3/16 -fix vm_vec_mag_quick (const vms_vector &v) __attribute_warn_unused_result; +__attribute_warn_unused_result +vm_magnitude vm_vec_mag_quick(const vms_vector &v); //computes an approximation of the distance between two points. //uses dist = largest + next_largest*3/8 + smallest*3/16 -fix vm_vec_dist_quick (const vms_vector &v0, const vms_vector &v1) __attribute_warn_unused_result; +__attribute_warn_unused_result +vm_distance vm_vec_dist_quick(const vms_vector &v0, const vms_vector &v1); //normalize a vector. returns mag of source vec -fix vm_vec_copy_normalize (vms_vector &dest, const vms_vector &src); +vm_magnitude vm_vec_copy_normalize(vms_vector &dest, const vms_vector &src); -fix vm_vec_normalize (vms_vector &v); +vm_magnitude vm_vec_normalize(vms_vector &v); static inline vms_vector vm_vec_normalized(vms_vector v) __attribute_warn_unused_result; static inline vms_vector vm_vec_normalized(vms_vector v) { @@ -208,9 +265,9 @@ static inline vms_vector vm_vec_normalized(vms_vector v) } //normalize a vector. returns mag of source vec. uses approx mag -fix vm_vec_copy_normalize_quick (vms_vector &dest, const vms_vector &src); +vm_magnitude vm_vec_copy_normalize_quick(vms_vector &dest, const vms_vector &src); -fix vm_vec_normalize_quick (vms_vector &v); +vm_magnitude vm_vec_normalize_quick(vms_vector &v); static inline vms_vector vm_vec_normalized_quick(vms_vector v) __attribute_warn_unused_result; static inline vms_vector vm_vec_normalized_quick(vms_vector v) { @@ -221,9 +278,9 @@ static inline vms_vector vm_vec_normalized_quick(vms_vector v) //return the normalized direction vector between two points //dest = normalized(end - start). Returns mag of direction vector //NOTE: the order of the parameters matches the vector subtraction -fix vm_vec_normalized_dir (vms_vector &dest, const vms_vector &end, const vms_vector &start); +vm_magnitude vm_vec_normalized_dir (vms_vector &dest, const vms_vector &end, const vms_vector &start); -fix vm_vec_normalized_dir_quick (vms_vector &dest, const vms_vector &end, const vms_vector &start); +vm_magnitude vm_vec_normalized_dir_quick (vms_vector &dest, const vms_vector &end, const vms_vector &start); ////returns dot product of two vectors diff --git a/common/maths/vecmat.cpp b/common/maths/vecmat.cpp index 5044bebc9..d39c97e78 100644 --- a/common/maths/vecmat.cpp +++ b/common/maths/vecmat.cpp @@ -158,35 +158,35 @@ fix vm_vec_dot(const vms_vector &v0,const vms_vector &v1) } //returns magnitude of a vector -fix64 vm_vec_mag2(const vms_vector &v) +vm_magnitude_squared vm_vec_mag2(const vms_vector &v) { const int64_t x = v.x; const int64_t y = v.y; const int64_t z = v.z; - return (x * x) + (y * y) + (z * z); + return vm_magnitude_squared{static_cast((x * x) + (y * y) + (z * z))}; } -fix vm_vec_mag(const vms_vector &v) +vm_magnitude vm_vec_mag(const vms_vector &v) { quadint q; - q.q = vm_vec_mag2(v); - return quad_sqrt(q); + q.q = vm_vec_mag2(v).d2; + return vm_magnitude{quad_sqrt(q)}; } //computes the distance between two points. (does sub and mag) -fix vm_vec_dist(const vms_vector &v0,const vms_vector &v1) +vm_distance vm_vec_dist(const vms_vector &v0,const vms_vector &v1) { return vm_vec_mag(vm_vec_sub(v0,v1)); } -fix64 vm_vec_dist2(const vms_vector &v0,const vms_vector &v1) +vm_distance_squared vm_vec_dist2(const vms_vector &v0,const vms_vector &v1) { return vm_vec_mag2(vm_vec_sub(v0,v1)); } //computes an approximation of the magnitude of the vector //uses dist = largest + next_largest*3/8 + smallest*3/16 -fix vm_vec_mag_quick(const vms_vector &v) +vm_magnitude vm_vec_mag_quick(const vms_vector &v) { fix a,b,c,bc; @@ -207,23 +207,21 @@ fix vm_vec_mag_quick(const vms_vector &v) bc = (b>>2) + (c>>3); - return a + bc + (bc>>1); + return vm_magnitude{static_cast(a + bc + (bc>>1))}; } //computes an approximation of the distance between two points. //uses dist = largest + next_largest*3/8 + smallest*3/16 -fix vm_vec_dist_quick(const vms_vector &v0,const vms_vector &v1) +vm_distance vm_vec_dist_quick(const vms_vector &v0,const vms_vector &v1) { return vm_vec_mag_quick(vm_vec_sub(v0,v1)); } //normalize a vector. returns mag of source vec -fix vm_vec_copy_normalize(vms_vector &dest,const vms_vector &src) +vm_magnitude vm_vec_copy_normalize(vms_vector &dest,const vms_vector &src) { - fix m; - - m = vm_vec_mag(src); + auto m = vm_vec_mag(src); if (m > 0) { vm_vec_divide(dest, src, m); } @@ -238,16 +236,15 @@ void vm_vec_divide(vms_vector &dest,const vms_vector &src, fix m) } //normalize a vector. returns mag of source vec -fix vm_vec_normalize(vms_vector &v) +vm_magnitude vm_vec_normalize(vms_vector &v) { return vm_vec_copy_normalize(v,v); } //normalize a vector. returns mag of source vec. uses approx mag -fix vm_vec_copy_normalize_quick(vms_vector &dest,const vms_vector &src) +vm_magnitude vm_vec_copy_normalize_quick(vms_vector &dest,const vms_vector &src) { - fix m; - m = vm_vec_mag_quick(src); + auto m = vm_vec_mag_quick(src); if (m > 0) { vm_vec_divide(dest, src, m); } @@ -255,7 +252,7 @@ fix vm_vec_copy_normalize_quick(vms_vector &dest,const vms_vector &src) } //normalize a vector. returns 1/mag of source vec. uses approx 1/mag -fix vm_vec_normalize_quick(vms_vector &v) +vm_magnitude vm_vec_normalize_quick(vms_vector &v) { return vm_vec_copy_normalize_quick(v,v); } @@ -263,7 +260,7 @@ fix vm_vec_normalize_quick(vms_vector &v) //return the normalized direction vector between two points //dest = normalized(end - start). Returns 1/mag of direction vector //NOTE: the order of the parameters matches the vector subtraction -fix vm_vec_normalized_dir_quick(vms_vector &dest,const vms_vector &end,const vms_vector &start) +vm_magnitude vm_vec_normalized_dir_quick(vms_vector &dest,const vms_vector &end,const vms_vector &start) { return vm_vec_normalize_quick(vm_vec_sub(dest,end,start)); } @@ -271,7 +268,7 @@ fix vm_vec_normalized_dir_quick(vms_vector &dest,const vms_vector &end,const vms //return the normalized direction vector between two points //dest = normalized(end - start). Returns mag of direction vector //NOTE: the order of the parameters matches the vector subtraction -fix vm_vec_normalized_dir(vms_vector &dest,const vms_vector &end,const vms_vector &start) +vm_magnitude vm_vec_normalized_dir(vms_vector &dest,const vms_vector &end,const vms_vector &start) { return vm_vec_normalize(vm_vec_sub(dest,end,start)); }