Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  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
  416.