Use special types for distance/magnitude
This commit is contained in:
parent
c5bbaaaf87
commit
f7d0c853ba
|
@ -28,6 +28,7 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
||||||
#include "maths.h"
|
#include "maths.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
#include <cstdint>
|
||||||
#include "dxxsconf.h"
|
#include "dxxsconf.h"
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
@ -37,6 +38,56 @@ struct vms_vector
|
||||||
fix x, y, z;
|
fix x, y, z;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class vm_distance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
fix d;
|
||||||
|
constexpr explicit vm_distance(const fix &f) :
|
||||||
|
d(f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
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 <typename T>
|
||||||
|
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 DEFINE_SERIAL_VMS_VECTOR_TO_MESSAGE() \
|
||||||
DEFINE_SERIAL_UDT_TO_MESSAGE(vms_vector, v, (v.x, v.y, v.z)); \
|
DEFINE_SERIAL_UDT_TO_MESSAGE(vms_vector, v, (v.x, v.y, v.z)); \
|
||||||
ASSERT_SERIAL_UDT_MESSAGE_SIZE(vms_vector, 12)
|
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
|
//dest *= n/d
|
||||||
void vm_vec_scale2 (vms_vector &dest, fix n, fix 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
|
//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)
|
//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;
|
__attribute_warn_unused_result
|
||||||
fix64 vm_vec_dist2 (const vms_vector &v0, const vms_vector &v1) __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
|
//computes an approximation of the magnitude of the vector
|
||||||
//uses dist = largest + next_largest*3/8 + smallest*3/16
|
//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.
|
//computes an approximation of the distance between two points.
|
||||||
//uses dist = largest + next_largest*3/8 + smallest*3/16
|
//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
|
//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) __attribute_warn_unused_result;
|
||||||
static inline vms_vector vm_vec_normalized(vms_vector v)
|
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
|
//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) __attribute_warn_unused_result;
|
||||||
static inline vms_vector vm_vec_normalized_quick(vms_vector v)
|
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
|
//return the normalized direction vector between two points
|
||||||
//dest = normalized(end - start). Returns mag of direction vector
|
//dest = normalized(end - start). Returns mag of direction vector
|
||||||
//NOTE: the order of the parameters matches the vector subtraction
|
//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
|
////returns dot product of two vectors
|
||||||
|
|
|
@ -158,35 +158,35 @@ fix vm_vec_dot(const vms_vector &v0,const vms_vector &v1)
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns magnitude of a vector
|
//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 x = v.x;
|
||||||
const int64_t y = v.y;
|
const int64_t y = v.y;
|
||||||
const int64_t z = v.z;
|
const int64_t z = v.z;
|
||||||
return (x * x) + (y * y) + (z * z);
|
return vm_magnitude_squared{static_cast<uint64_t>((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;
|
quadint q;
|
||||||
q.q = vm_vec_mag2(v);
|
q.q = vm_vec_mag2(v).d2;
|
||||||
return quad_sqrt(q);
|
return vm_magnitude{quad_sqrt(q)};
|
||||||
}
|
}
|
||||||
|
|
||||||
//computes the distance between two points. (does sub and mag)
|
//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));
|
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));
|
return vm_vec_mag2(vm_vec_sub(v0,v1));
|
||||||
}
|
}
|
||||||
|
|
||||||
//computes an approximation of the magnitude of the vector
|
//computes an approximation of the magnitude of the vector
|
||||||
//uses dist = largest + next_largest*3/8 + smallest*3/16
|
//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;
|
fix a,b,c,bc;
|
||||||
|
|
||||||
|
@ -207,23 +207,21 @@ fix vm_vec_mag_quick(const vms_vector &v)
|
||||||
|
|
||||||
bc = (b>>2) + (c>>3);
|
bc = (b>>2) + (c>>3);
|
||||||
|
|
||||||
return a + bc + (bc>>1);
|
return vm_magnitude{static_cast<uint32_t>(a + bc + (bc>>1))};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//computes an approximation of the distance between two points.
|
//computes an approximation of the distance between two points.
|
||||||
//uses dist = largest + next_largest*3/8 + smallest*3/16
|
//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));
|
return vm_vec_mag_quick(vm_vec_sub(v0,v1));
|
||||||
}
|
}
|
||||||
|
|
||||||
//normalize a vector. returns mag of source vec
|
//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;
|
auto m = vm_vec_mag(src);
|
||||||
|
|
||||||
m = vm_vec_mag(src);
|
|
||||||
if (m > 0) {
|
if (m > 0) {
|
||||||
vm_vec_divide(dest, src, m);
|
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
|
//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);
|
return vm_vec_copy_normalize(v,v);
|
||||||
}
|
}
|
||||||
|
|
||||||
//normalize a vector. returns mag of source vec. uses approx mag
|
//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;
|
auto m = vm_vec_mag_quick(src);
|
||||||
m = vm_vec_mag_quick(src);
|
|
||||||
if (m > 0) {
|
if (m > 0) {
|
||||||
vm_vec_divide(dest, src, m);
|
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
|
//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);
|
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
|
//return the normalized direction vector between two points
|
||||||
//dest = normalized(end - start). Returns 1/mag of direction vector
|
//dest = normalized(end - start). Returns 1/mag of direction vector
|
||||||
//NOTE: the order of the parameters matches the vector subtraction
|
//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));
|
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
|
//return the normalized direction vector between two points
|
||||||
//dest = normalized(end - start). Returns mag of direction vector
|
//dest = normalized(end - start). Returns mag of direction vector
|
||||||
//NOTE: the order of the parameters matches the vector subtraction
|
//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));
|
return vm_vec_normalize(vm_vec_sub(dest,end,start));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue