Use special types for distance/magnitude

This commit is contained in:
Kp 2015-03-12 02:21:19 +00:00
parent c5bbaaaf87
commit f7d0c853ba
2 changed files with 87 additions and 33 deletions

View file

@ -28,6 +28,7 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
#include "maths.h"
#ifdef __cplusplus
#include <cstdint>
#include "dxxsconf.h"
#include <utility>
@ -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 <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_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

View file

@ -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<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;
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<uint32_t>(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));
}