BRL-CAD
vmath.h
Go to the documentation of this file.
1/* V M A T H . H
2 * BRL-CAD
3 *
4 * Copyright (c) 2004-2023 United States Government as represented by
5 * the U.S. Army Research Laboratory.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * version 2.1 as published by the Free Software Foundation.
10 *
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this file; see the file named COPYING for more
18 * information.
19 */
20/** @addtogroup vmath */
21/** @{ */
22/** @file vmath.h
23 *
24 * @brief fundamental vector, matrix, quaternion math macros
25 *
26 * VMATH defines commonly needed macros for 2D/3D/4D math involving:
27 *
28 * points (point2d_t, point_t, and hpoint_t),
29 * vectors (vect2d_t, vect_t, and hvect_t),
30 * quaternions (quat_t),
31 * planes (plane_t), and
32 * 4x4 matrices (mat_t).
33 *
34 * By default, all floating point numbers are stored in arrays using
35 * the 'fastf_t' type definition. It should be manually typedef'd to
36 * the "fastest" 64-bit floating point type available on the current
37 * hardware with at least 64 bits of precision. On 16 and 32 bit
38 * machines, this is typically "double", but on 64 bit machines, it
39 * could be "float".
40 *
41 * Matrix array elements have the following positions in the matrix:
42 * @code
43 * | 0 1 2 3 | | 0 |
44 * [ 0 1 2 3 ] | 4 5 6 7 | | 1 |
45 * | 8 9 10 11 | | 2 |
46 * | 12 13 14 15 | | 3 |
47 *
48 * preVector (vect_t) Matrix (mat_t) postVector (vect_t)
49 * @endcode
50 *
51 * Note that while many people in the computer graphics field use
52 * post-multiplication with row vectors (i.e., vector * matrix *
53 * matrix ...) VMATH uses the more traditional representation of
54 * column vectors (i.e., ... matrix * matrix * vector). (The matrices
55 * in these two representations are the transposes of each
56 * other). Therefore, when transforming a vector by a matrix,
57 * pre-multiplication is used, i.e.:
58 *
59 * view_vec = model2view_mat * model_vec
60 *
61 * Furthermore, additional transformations are multiplied on the left,
62 * i.e.:
63 *
64 * @code
65 * vec' = T1 * vec
66 * vec'' = T2 * T1 * vec = T2 * vec'
67 * @endcode
68 *
69 * The most notable implication of this is the location of the "delta"
70 * (translation) values in the matrix, i.e.:
71 *
72 * @code
73 * x' (R0 R1 R2 Dx) x
74 * y' = (R4 R5 R6 Dy) * y
75 * z' (R8 R9 R10 Dz) z
76 * w' (0 0 0 1/s) w
77 * @endcode
78 *
79 * Note -
80 *@n vect_t objects are 3-tuples
81 *@n hvect_t objects are 4-tuples
82 *
83 * Most of these macros require that the result be in separate
84 * storage, distinct from the input parameters, except where noted.
85 *
86 * IMPLEMENTOR NOTES
87 *
88 * When writing macros like this, it is very important that any
89 * variables declared within a macro code blocks start with an
90 * underscore in order to (hopefully) minimize any name conflicts with
91 * user-provided parameters, such as _f in the following example:
92 *
93 * @code
94 * #define ABC() do { double _f; do stuff; } while (0)
95 * @endcode
96 *
97 * All of the macros that introduce a scope like the preceding
98 * example are written as do { } while (0) loops in order to require
99 * callers provide a trailing semicolon (e.g., ABC();). This helps
100 * preserve source code formatting.
101 */
102
103#ifndef VMATH_H
104#define VMATH_H
105
106#include "common.h"
107
108/* needed for additional math defines on Windows when including math.h */
109#define _USE_MATH_DEFINES 1
110
111/* for sqrt(), sin(), cos(), rint(), M_PI, INFINITY (HUGE_VAL), and more */
112#include <math.h>
113
114/* for floating point tolerances and other math constants */
115#include <float.h>
116
117
118#ifdef __cplusplus
119extern "C" {
120#endif
121
122
123#ifndef M_
124# define M_ XXX /**< all with 36-digits of precision */
125#endif
126
127#ifndef M_1_2PI
128# define M_1_2PI 0.159154943091895335768883763372514362 /**< 1/(2*pi) */
129#endif
130#ifndef M_1_PI
131# define M_1_PI 0.318309886183790671537767526745028724 /**< 1/pi */
132#endif
133#ifndef M_2_PI
134# define M_2_PI 0.636619772367581343075535053490057448 /**< 2/pi */
135#endif
136#ifndef M_2_SQRTPI
137# define M_2_SQRTPI 1.12837916709551257389615890312154517 /**< 2/sqrt(pi) */
138#endif
139#ifndef M_E
140# define M_E 2.71828182845904523536028747135266250 /**< e */
141#endif
142#ifndef M_EULER
143# define M_EULER 0.577215664901532860606512090082402431 /**< Euler's constant */
144#endif
145#ifndef M_LOG2E
146# define M_LOG2E 1.44269504088896340735992468100189214 /**< log_2(e) */
147#endif
148#ifndef M_LOG10E
149# define M_LOG10E 0.434294481903251827651128918916605082 /**< log_10(e) */
150#endif
151#ifndef M_LN2
152# define M_LN2 0.693147180559945309417232121458176568 /**< log_e(2) */
153#endif
154#ifndef M_LN10
155# define M_LN10 2.30258509299404568401799145468436421 /**< log_e(10) */
156#endif
157#ifndef M_LNPI
158# define M_LNPI 1.14472988584940017414342735135305871 /** log_e(pi) */
159#endif
160#ifndef M_PI
161# define M_PI 3.14159265358979323846264338327950288 /**< pi */
162#endif
163#ifndef M_2PI
164# define M_2PI 6.28318530717958647692528676655900576 /**< 2*pi */
165#endif
166#ifndef M_PI_2
167# define M_PI_2 1.57079632679489661923132169163975144 /**< pi/2 */
168#endif
169#ifndef M_PI_3
170# define M_PI_3 1.04719755119659774615421446109316763 /**< pi/3 */
171#endif
172#ifndef M_PI_4
173# define M_PI_4 0.785398163397448309615660845819875721 /**< pi/4 */
174#endif
175#ifndef M_SQRT1_2
176# define M_SQRT1_2 0.707106781186547524400844362104849039 /**< sqrt(1/2) */
177#endif
178#ifndef M_SQRT2
179# define M_SQRT2 1.41421356237309504880168872420969808 /**< sqrt(2) */
180#endif
181#ifndef M_SQRT3
182# define M_SQRT3 1.73205080756887729352744634150587237 /**< sqrt(3) */
183#endif
184#ifndef M_SQRTPI
185# define M_SQRTPI 1.77245385090551602729816748334114518 /**< sqrt(pi) */
186#endif
187
188#ifndef DEG2RAD
189# define DEG2RAD 0.0174532925199432957692369076848861271 /**< pi/180 */
190#endif
191#ifndef RAD2DEG
192# define RAD2DEG 57.2957795130823208767981548141051703 /**< 180/pi */
193#endif
194
195
196/**
197 * Definitions about limits of floating point representation
198 * Eventually, should be tied to type of hardware (IEEE, IBM, Cray)
199 * used to implement the fastf_t type.
200 *
201 * MAX_FASTF - Very close to the largest value that can be held by a
202 * fastf_t without overflow. Typically specified as an integer power
203 * of ten, to make the value easy to spot when printed. TODO: macro
204 * function syntax instead of constant (DEPRECATED)
205 *
206 * SQRT_MAX_FASTF - sqrt(MAX_FASTF), or slightly smaller. Any number
207 * larger than this, if squared, can be expected to * produce an
208 * overflow. TODO: macro function syntax instead of constant
209 * (DEPRECATED)
210 *
211 * SMALL_FASTF - Very close to the smallest value that can be
212 * represented while still being greater than zero. Any number
213 * smaller than this (and non-negative) can be considered to be
214 * zero; dividing by such a number can be expected to produce a
215 * divide-by-zero error. All divisors should be checked against
216 * this value before actual division is performed. TODO: macro
217 * function syntax instead of constant (DEPRECATED)
218 *
219 * SQRT_SMALL_FASTF - sqrt(SMALL_FASTF), or slightly larger. The
220 * value of this is quite a lot larger than that of SMALL_FASTF. Any
221 * number smaller than this, when squared, can be expected to produce
222 * a zero result. TODO: macro function syntax instead of constant
223 * (DEPRECATED)
224 *
225 */
226#if defined(vax)
227/* DEC VAX "D" format, the most restrictive */
228# define MAX_FASTF 1.0e37 /* Very close to the largest number */
229# define SQRT_MAX_FASTF 1.0e18 /* This squared just avoids overflow */
230# define SMALL_FASTF 1.0e-37 /* Anything smaller is zero */
231# define SQRT_SMALL_FASTF 1.0e-18 /* This squared gives zero */
232#else
233/* IBM format, being the next most restrictive format */
234# define MAX_FASTF 1.0e73 /* Very close to the largest number */
235# define SQRT_MAX_FASTF 1.0e36 /* This squared just avoids overflow */
236# define SMALL_FASTF 1.0e-77 /* Anything smaller is zero */
237# if defined(aux)
238# define SQRT_SMALL_FASTF 1.0e-40 /* _doprnt error in libc */
239# else
240# define SQRT_SMALL_FASTF 1.0e-39 /* This squared gives zero */
241# endif
242#endif
243
244/** DEPRECATED, do not use */
245#define SMALL SQRT_SMALL_FASTF
246
247/**
248 * It is necessary to have a representation of 1.0/0.0 or log(0),
249 * i.e., "infinity" that fits within the dynamic range of the machine
250 * being used. This constant places an upper bound on the size object
251 * which can be represented in the model. With IEEE 754 floating
252 * point, this may print as 'inf' and is represented with all 1 bits
253 * in the biased-exponent field and all 0 bits in the fraction with
254 * the sign indicating positive (0) or negative (1) infinity.
255 * However, we do not assume or rely on IEEE 754 floating point.
256 */
257#ifndef INFINITY
258# if defined(DBL_MAX)
259# define INFINITY ((fastf_t)DBL_MAX)
260# elif defined(HUGE_VAL)
261# define INFINITY ((fastf_t)HUGE_VAL)
262# elif defined(MAXDOUBLE)
263# define INFINITY ((fastf_t)MAXDOUBLE)
264# elif defined(HUGE)
265# define INFINITY ((fastf_t)HUGE)
266/* fall back to a single-precision limit */
267# elif defined(FLT_MAX)
268# define INFINITY ((fastf_t)FLT_MAX)
269# elif defined(HUGE_VALF)
270# define INFINITY ((fastf_t)HUGE_VALF)
271# elif defined(MAXFLOAT)
272# define INFINITY ((fastf_t)MAXFLOAT)
273# else
274 /* all else fails, just pick something big slightly under the
275 * 32-bit single-precision floating point limit for IEEE 754.
276 */
277# define INFINITY ((fastf_t)1.0e38)
278# endif
279#endif
280
281
282/* minimum computation tolerances */
283#ifdef vax
284# define VDIVIDE_TOL (1.0e-10)
285# define VUNITIZE_TOL (1.0e-7)
286#else
287# ifdef DBL_EPSILON
288# define VDIVIDE_TOL (DBL_EPSILON)
289# else
290# define VDIVIDE_TOL (1.0e-20)
291# endif
292# ifdef FLT_EPSILON
293# define VUNITIZE_TOL (FLT_EPSILON)
294# else
295# define VUNITIZE_TOL (1.0e-15)
296# endif
297#endif
298
299
300/** @brief number of fastf_t's per vect2d_t */
301#define ELEMENTS_PER_VECT2D 2
302
303/** @brief number of fastf_t's per point2d_t */
304#define ELEMENTS_PER_POINT2D 2
305
306/** @brief number of fastf_t's per vect_t */
307#define ELEMENTS_PER_VECT 3
308
309/** @brief number of fastf_t's per point_t */
310#define ELEMENTS_PER_POINT 3
311
312/** @brief number of fastf_t's per hvect_t (homogeneous vector) */
313#define ELEMENTS_PER_HVECT 4
314
315/** @brief number of fastf_t's per hpt_t (homogeneous point) */
316#define ELEMENTS_PER_HPOINT 4
317
318/** @brief number of fastf_t's per plane_t */
319#define ELEMENTS_PER_PLANE 4
320
321/** @brief number of fastf_t's per mat_t */
322#define ELEMENTS_PER_MAT (ELEMENTS_PER_PLANE*ELEMENTS_PER_PLANE)
323
324
325/*
326 * Fundamental types
327 */
328
329/** @brief fastest 64-bit (or larger) floating point type */
330typedef double fastf_t;
331
332/** @brief 2-tuple vector */
334
335/** @brief pointer to a 2-tuple vector */
337
338/** @brief 2-tuple point */
340
341/** @brief pointer to a 2-tuple point */
343
344/** @brief 3-tuple vector */
346
347/** @brief pointer to a 3-tuple vector */
349
350/** @brief 3-tuple point */
352
353/** @brief pointer to a 3-tuple point */
355
356/** @brief 4-tuple vector */
358
359/** @brief 4-element quaternion */
361
362/** @brief 4-tuple point */
364
365/** @brief 4x4 matrix */
367
368/** @brief pointer to a 4x4 matrix */
370
371/**
372 * @brief Definition of a plane equation
373 *
374 * A plane is defined by a unit-length outward pointing normal vector
375 * (N), and the perpendicular (shortest) distance from the origin to
376 * the plane (in element N[W]).
377 *
378 * The plane consists of all points P=(x, y, z) such that
379 *@n VDOT(P, N) - N[W] == 0
380 *@n that is,
381 *@n N[X]*x + N[Y]*y + N[Z]*z - N[W] == 0
382 *
383 * The inside of the halfspace bounded by the plane
384 * consists of all points P such that
385 *@n VDOT(P, N) - N[W] <= 0
386 *
387 * A ray with direction D is classified w.r.t. the plane by
388 *
389 *@n VDOT(D, N) < 0 ray enters halfspace defined by plane
390 *@n VDOT(D, N) == 0 ray is parallel to plane
391 *@n VDOT(D, N) > 0 ray exits halfspace defined by plane
392 */
394
395/** Vector component names for homogeneous (4-tuple) vectors */
397 X = 0,
398 Y = 1,
399 Z = 2,
400 W = 3,
401 H = W
403
404/**
405 * Locations of deltas (MD*) and scaling values (MS*) in a 4x4
406 * Homogeneous Transform matrix
407 */
409 MSX = 0,
410 MDX = 3,
411 MSY = 5,
412 MDY = 7,
413 MSZ = 10,
414 MDZ = 11,
415 MSA = 15
417
418/**
419 * Evaluates truthfully whether a number is not within valid range of
420 * INFINITY to -INFINITY exclusive (open set).
421 */
422#define INVALID(n) (!((n) > -INFINITY && (n) < INFINITY))
423
424/**
425 * Evaluates truthfully whether any components of a vector are not
426 * within a valid range.
427 */
428#define VINVALID(v) (INVALID((v)[X]) || INVALID((v)[Y]) || INVALID((v)[Z]))
429
430/**
431 * Evaluates truthfully whether any components of a 2D vector are not
432 * within a valid range.
433 */
434#define V2INVALID(v) (INVALID((v)[X]) || INVALID((v)[Y]))
435
436/**
437 * Evaluates truthfully whether any components of a 4D vector are not
438 * within a valid range.
439 */
440#define HINVALID(v) (INVALID((v)[X]) || INVALID((v)[Y]) || INVALID((v)[Z]) || INVALID((v)[W]))
441
442/**
443 * Return truthfully whether a value is within a specified epsilon
444 * distance from zero.
445 */
446#ifdef KEITH_WANTS_THIS
447/* this is a proposed change to equality/zero testing. prior behavior
448 * evaluated as an open set. this would change the behavior to that
449 * of a closed set so that you can perform exact comparisons against
450 * the tolerance and get a match. examples that fail with the current
451 * macro: tol=0.1; 1.1 == 1.0 or tol=0; 1==1
452 *
453 * these need to be tested carefully to make sure we pass ALL
454 * regression and integration tests, which will require some
455 * concerted effort to coordinate prior to a release. first step is
456 * to evaluate impact on performance and behavior of our tests.
457 */
458# define NEAR_ZERO(val, epsilon) (!(((val) < -epsilon) || ((val) > epsilon)))
459# define NEAR_ZERO(val, epsilon) (!(((val) < -epsilon)) && !(((val) > epsilon)))
460#else
461# define NEAR_ZERO(val, epsilon) (((val) > -epsilon) && ((val) < epsilon))
462#endif
463
464/**
465 * Return truthfully whether all elements of a given vector are within
466 * a specified epsilon distance from zero.
467 */
468#define VNEAR_ZERO(v, tol) \
469 (NEAR_ZERO(v[X], tol) \
470 && NEAR_ZERO(v[Y], tol) \
471 && NEAR_ZERO(v[Z], tol))
472
473/**
474 * Test for all elements of `v' being smaller than `tol'.
475 * Version for degree 2 vectors.
476 */
477#define V2NEAR_ZERO(v, tol) (NEAR_ZERO(v[X], tol) && NEAR_ZERO(v[Y], tol))
478
479/**
480 * Test for all elements of `v' being smaller than `tol'.
481 * Version for degree 2 vectors.
482 */
483#define HNEAR_ZERO(v, tol) \
484 (NEAR_ZERO(v[X], tol) \
485 && NEAR_ZERO(v[Y], tol) \
486 && NEAR_ZERO(v[Z], tol) \
487 && NEAR_ZERO(h[W], tol))
488
489
490/**
491 * Return truthfully whether a value is within a minimum
492 * representation tolerance from zero.
493 */
494#define ZERO(_a) NEAR_ZERO((_a), SMALL_FASTF)
495
496/**
497 * Return truthfully whether a vector is within a minimum
498 * representation tolerance from zero.
499 */
500#define VZERO(_a) VNEAR_ZERO((_a), SMALL_FASTF)
501
502/**
503 * Return truthfully whether a 2d vector is within a minimum
504 * representation tolerance from zero.
505 */
506#define V2ZERO(_a) V2NEAR_ZERO((_a), SMALL_FASTF)
507
508/**
509 * Return truthfully whether a homogenized 4-element vector is within
510 * a minimum representation tolerance from zero.
511 */
512#define HZERO(_a) HNEAR_ZERO((_a), SMALL_FASTF)
513
514
515/**
516 * Return truthfully whether two values are within a specified epsilon
517 * distance from each other.
518 */
519#define NEAR_EQUAL(_a, _b, _tol) NEAR_ZERO((_a) - (_b), (_tol))
520
521/**
522 * Return truthfully whether two 3D vectors are approximately equal,
523 * within a specified absolute tolerance.
524 */
525#define VNEAR_EQUAL(_a, _b, _tol) \
526 (NEAR_EQUAL((_a)[X], (_b)[X], (_tol)) \
527 && NEAR_EQUAL((_a)[Y], (_b)[Y], (_tol)) \
528 && NEAR_EQUAL((_a)[Z], (_b)[Z], (_tol)))
529
530/**
531 * Return truthfully whether two 2D vectors are approximately equal,
532 * within a specified absolute tolerance.
533 */
534#define V2NEAR_EQUAL(a, b, tol) \
535 (NEAR_EQUAL((a)[X], (b)[X], tol) \
536 && NEAR_EQUAL((a)[Y], (b)[Y], tol))
537
538/**
539 * Return truthfully whether two 4D vectors are approximately equal,
540 * within a specified absolute tolerance.
541 */
542#define HNEAR_EQUAL(_a, _b, _tol) \
543 (NEAR_EQUAL((_a)[X], (_b)[X], (_tol)) \
544 && NEAR_EQUAL((_a)[Y], (_b)[Y], (_tol)) \
545 && NEAR_EQUAL((_a)[Z], (_b)[Z], (_tol)) \
546 && NEAR_EQUAL((_a)[W], (_b)[W], (_tol)))
547
548/**
549 * Return truthfully whether two values are within a minimum
550 * representation tolerance from each other.
551 */
552#define EQUAL(_a, _b) NEAR_EQUAL((_a), (_b), SMALL_FASTF)
553
554
555/**
556 * Return truthfully whether two vectors are equal within a minimum
557 * representation tolerance.
558 */
559#define VEQUAL(_a, _b) VNEAR_EQUAL((_a), (_b), SMALL_FASTF)
560
561/**
562 * @brief Return truthfully whether two 2D vectors are equal within
563 * a minimum representation tolerance.
564 */
565#define V2EQUAL(_a, _b) V2NEAR_EQUAL((_a), (_b), SMALL_FASTF)
566
567/**
568 * @brief Return truthfully whether two higher degree vectors are
569 * equal within a minimum representation tolerance.
570 */
571#define HEQUAL(_a, _b) HNEAR_EQUAL((_a), (_b), SMALL_FASTF)
572
573
574/** @brief Compute distance from a point to a plane. */
575#define DIST_PNT_PLANE(_pt, _pl) (VDOT(_pt, _pl) - (_pl)[W])
576
577/** @brief Compute distance between two points. */
578#define DIST_PNT_PNT_SQ(_a, _b) \
579 ((_a)[X]-(_b)[X])*((_a)[X]-(_b)[X]) + \
580 ((_a)[Y]-(_b)[Y])*((_a)[Y]-(_b)[Y]) + \
581 ((_a)[Z]-(_b)[Z])*((_a)[Z]-(_b)[Z])
582#define DIST_PNT_PNT(_a, _b) sqrt(DIST_PNT_PNT_SQ(_a, _b))
583
584/** @brief Compute distance between two 2D points. */
585#define DIST_PNT2_PNT2_SQ(_a, _b) \
586 ((_a)[X]-(_b)[X])*((_a)[X]-(_b)[X]) + \
587 ((_a)[Y]-(_b)[Y])*((_a)[Y]-(_b)[Y])
588#define DIST_PNT2_PNT2(_a, _b) sqrt(DIST_PNT2_PNT2_SQ(_a, _b))
589
590/** @brief set translation values of 4x4 matrix with x, y, z values. */
591#define MAT_DELTAS(_m, _x, _y, _z) do { \
592 (_m)[MDX] = (_x); \
593 (_m)[MDY] = (_y); \
594 (_m)[MDZ] = (_z); \
595 } while (0)
596
597/** @brief set translation values of 4x4 matrix from a vector. */
598#define MAT_DELTAS_VEC(_m, _v) \
599 MAT_DELTAS(_m, (_v)[X], (_v)[Y], (_v)[Z])
600
601/**
602 * @brief set translation values of 4x4 matrix from a reversed
603 * vector.
604 */
605#define MAT_DELTAS_VEC_NEG(_m, _v) \
606 MAT_DELTAS(_m, -(_v)[X], -(_v)[Y], -(_v)[Z])
607
608/** @brief get translation values of 4x4 matrix to a vector. */
609#define MAT_DELTAS_GET(_v, _m) do { \
610 (_v)[X] = (_m)[MDX]; \
611 (_v)[Y] = (_m)[MDY]; \
612 (_v)[Z] = (_m)[MDZ]; \
613 } while (0)
614
615/**
616 * @brief get translation values of 4x4 matrix to a vector,
617 * reversed.
618 */
619#define MAT_DELTAS_GET_NEG(_v, _m) do { \
620 (_v)[X] = -(_m)[MDX]; \
621 (_v)[Y] = -(_m)[MDY]; \
622 (_v)[Z] = -(_m)[MDZ]; \
623 } while (0)
624
625/**
626 * @brief increment translation elements in a 4x4 matrix with x, y, z
627 * values.
628 */
629#define MAT_DELTAS_ADD(_m, _x, _y, _z) do { \
630 (_m)[MDX] += (_x); \
631 (_m)[MDY] += (_y); \
632 (_m)[MDZ] += (_z); \
633 } while (0)
634
635/**
636 * @brief increment translation elements in a 4x4 matrix from a
637 * vector.
638 */
639#define MAT_DELTAS_ADD_VEC(_m, _v) do { \
640 (_m)[MDX] += (_v)[X]; \
641 (_m)[MDY] += (_v)[Y]; \
642 (_m)[MDZ] += (_v)[Z]; \
643 } while (0)
644
645/**
646 * @brief decrement translation elements in a 4x4 matrix with x, y, z
647 * values.
648 */
649#define MAT_DELTAS_SUB(_m, _x, _y, _z) do { \
650 (_m)[MDX] -= (_x); \
651 (_m)[MDY] -= (_y); \
652 (_m)[MDZ] -= (_z); \
653 } while (0)
654
655/**
656 * @brief decrement translation elements in a 4x4 matrix from a
657 * vector.
658 */
659#define MAT_DELTAS_SUB_VEC(_m, _v) do { \
660 (_m)[MDX] -= (_v)[X]; \
661 (_m)[MDY] -= (_v)[Y]; \
662 (_m)[MDZ] -= (_v)[Z]; \
663 } while (0)
664
665/**
666 * @brief decrement translation elements in a 4x4 matrix with x, y, z
667 * values.
668 */
669#define MAT_DELTAS_MUL(_m, _x, _y, _z) do { \
670 (_m)[MDX] *= (_x); \
671 (_m)[MDY] *= (_y); \
672 (_m)[MDZ] *= (_z); \
673 } while (0)
674
675/**
676 * @brief decrement translation elements in a 4x4 matrix from a
677 * vector.
678 */
679#define MAT_DELTAS_MUL_VEC(_m, _v) do { \
680 (_m)[MDX] *= (_v)[X]; \
681 (_m)[MDY] *= (_v)[Y]; \
682 (_m)[MDZ] *= (_v)[Z]; \
683 } while (0)
684
685/** @brief set scale of 4x4 matrix from xyz. */
686#define MAT_SCALE(_m, _x, _y, _z) do { \
687 (_m)[MSX] = _x; \
688 (_m)[MSY] = _y; \
689 (_m)[MSZ] = _z; \
690 } while (0)
691
692/** @brief set scale of 4x4 matrix from vector. */
693#define MAT_SCALE_VEC(_m, _v) do { \
694 (_m)[MSX] = (_v)[X]; \
695 (_m)[MSY] = (_v)[Y]; \
696 (_m)[MSZ] = (_v)[Z]; \
697 } while (0)
698
699/** @brief set uniform scale of 4x4 matrix from scalar. */
700#define MAT_SCALE_ALL(_m, _s) (_m)[MSA] = (_s)
701
702/** @brief add to scaling elements in a 4x4 matrix from xyz. */
703#define MAT_SCALE_ADD(_m, _x, _y, _z) do { \
704 (_m)[MSX] += _x; \
705 (_m)[MSY] += _y; \
706 (_m)[MSZ] += _z; \
707 } while (0)
708
709/** @brief add to scaling elements in a 4x4 matrix from vector. */
710#define MAT_SCALE_ADD_VEC(_m, _v) do { \
711 (_m)[MSX] += (_v)[X]; \
712 (_m)[MSY] += (_v)[Y]; \
713 (_m)[MSZ] += (_v)[Z]; \
714 } while (0)
715
716/** @brief subtract from scaling elements in a 4x4 matrix from xyz. */
717#define MAT_SCALE_SUB(_m, _x, _y, _z) do { \
718 (_m)[MSX] -= _x; \
719 (_m)[MSY] -= _y; \
720 (_m)[MSZ] -= _z; \
721 } while (0)
722
723/**
724 * @brief subtract from scaling elements in a 4x4 matrix from
725 * vector.
726 */
727#define MAT_SCALE_SUB_VEC(_m, _v) do { \
728 (_m)[MSX] -= (_v)[X]; \
729 (_m)[MSY] -= (_v)[Y]; \
730 (_m)[MSZ] -= (_v)[Z]; \
731 } while (0)
732
733/** @brief multiply scaling elements in a 4x4 matrix from xyz. */
734#define MAT_SCALE_MUL(_m, _x, _y, _z) do { \
735 (_m)[MSX] *= _x; \
736 (_m)[MSY] *= _y; \
737 (_m)[MSZ] *= _z; \
738 } while (0)
739
740/** @brief multiply scaling elements in a 4x4 matrix from vector. */
741#define MAT_SCALE_MUL_VEC(_m, _v) do { \
742 (_m)[MSX] *= (_v)[X]; \
743 (_m)[MSY] *= (_v)[Y]; \
744 (_m)[MSZ] *= (_v)[Z]; \
745 } while (0)
746
747
748/**
749 * In following are macro versions of librt/mat.c functions for when
750 * speed really matters.
751 */
752
753
754/** @brief Zero a matrix. */
755#define MAT_ZERO(m) do { \
756 (m)[0] = (m)[1] = (m)[2] = (m)[3] = \
757 (m)[4] = (m)[5] = (m)[6] = (m)[7] = \
758 (m)[8] = (m)[9] = (m)[10] = (m)[11] = \
759 (m)[12] = (m)[13] = (m)[14] = (m)[15] = 0.0; \
760 } while (0)
761
762/** @brief Set matrix to identity. */
763#define MAT_IDN(m) do { \
764 (m)[1] = (m)[2] = (m)[3] = (m)[4] = \
765 (m)[6] = (m)[7] = (m)[8] = (m)[9] = \
766 (m)[11] = (m)[12] = (m)[13] = (m)[14] = 0.0; \
767 (m)[0] = (m)[5] = (m)[10] = (m)[15] = 1.0; \
768 } while (0)
769
770/**
771 * @brief set t to the transpose of matrix m
772 *
773 * NOTE: This implementation will not transpose in-place or
774 * overlapping matrices (e.g., MAT_TRANSPOSE(m, m) will be wrong).
775 */
776#define MAT_TRANSPOSE(t, m) do { \
777 (t)[0] = (m)[0]; \
778 (t)[4] = (m)[1]; \
779 (t)[8] = (m)[2]; \
780 (t)[12] = (m)[3]; \
781 (t)[1] = (m)[4]; \
782 (t)[5] = (m)[5]; \
783 (t)[9] = (m)[6]; \
784 (t)[13] = (m)[7]; \
785 (t)[2] = (m)[8]; \
786 (t)[6] = (m)[9]; \
787 (t)[10] = (m)[10]; \
788 (t)[14] = (m)[11]; \
789 (t)[3] = (m)[12]; \
790 (t)[7] = (m)[13]; \
791 (t)[11] = (m)[14]; \
792 (t)[15] = (m)[15]; \
793 } while (0)
794
795/** @brief Copy a matrix `m' into `c'. */
796#define MAT_COPY(c, m) do { \
797 (c)[0] = (m)[0]; \
798 (c)[1] = (m)[1]; \
799 (c)[2] = (m)[2]; \
800 (c)[3] = (m)[3]; \
801 (c)[4] = (m)[4]; \
802 (c)[5] = (m)[5]; \
803 (c)[6] = (m)[6]; \
804 (c)[7] = (m)[7]; \
805 (c)[8] = (m)[8]; \
806 (c)[9] = (m)[9]; \
807 (c)[10] = (m)[10]; \
808 (c)[11] = (m)[11]; \
809 (c)[12] = (m)[12]; \
810 (c)[13] = (m)[13]; \
811 (c)[14] = (m)[14]; \
812 (c)[15] = (m)[15]; \
813 } while (0)
814
815/** @brief Set 3D vector at `o' to have coordinates `a', `b', and `c'. */
816#define VSET(o, a, b, c) do { \
817 (o)[X] = (a); \
818 (o)[Y] = (b); \
819 (o)[Z] = (c); \
820 } while (0)
821
822/** @brief Set 2D vector at `o' to have coordinates `a' and `b'. */
823#define V2SET(o, a, b) do { \
824 (o)[X] = (a); \
825 (o)[Y] = (b); \
826 } while (0)
827
828/** @brief Set 4D vector at `o' to homogeneous coordinates `a', `b', `c', and `d'. */
829#define HSET(o, a, b, c, d) do { \
830 (o)[X] = (a); \
831 (o)[Y] = (b); \
832 (o)[Z] = (c); \
833 (o)[W] = (d); \
834 } while (0)
835
836
837/** @brief Set all elements of 3D vector to same scalar value. */
838#define VSETALL(v, s) do { \
839 (v)[X] = (v)[Y] = (v)[Z] = (s); \
840 } while (0)
841
842/** @brief Set 2D vector elements to same scalar value. */
843#define V2SETALL(v, s) do { \
844 (v)[X] = (v)[Y] = (s); \
845 } while (0)
846
847/** @brief Set 4D vector elements to same scalar value. */
848#define HSETALL(v, s) do { \
849 (v)[X] = (v)[Y] = (v)[Z] = (v)[W] = (s); \
850 } while (0)
851
852
853/** @brief Set all elements of N-vector to same scalar value. */
854#define VSETALLN(v, s, n) do { \
855 size_t _j; \
856 for (_j=0; _j < (size_t)(n); _j++) v[_j]=(s); \
857 } while (0)
858
859
860/** @brief Transfer 3D vector at `v' to vector at `o'. */
861#define VMOVE(o, v) do { \
862 (o)[X] = (v)[X]; \
863 (o)[Y] = (v)[Y]; \
864 (o)[Z] = (v)[Z]; \
865 } while (0)
866
867/** @brief Move a 2D vector at `v' to vector at `o'. */
868#define V2MOVE(o, v) do { \
869 (o)[X] = (v)[X]; \
870 (o)[Y] = (v)[Y]; \
871 } while (0)
872
873/** @brief Move a homogeneous 4-tuple at `v' to `o'. */
874#define HMOVE(o, v) do { \
875 (o)[X] = (v)[X]; \
876 (o)[Y] = (v)[Y]; \
877 (o)[Z] = (v)[Z]; \
878 (o)[W] = (v)[W]; \
879 } while (0)
880
881/** @brief Transfer vector of length `n' at `v' to vector at `o'. */
882#define VMOVEN(o, v, n) do { \
883 size_t _vmove; \
884 for (_vmove = 0; _vmove < (size_t)(n); _vmove++) { \
885 (o)[_vmove] = (v)[_vmove]; \
886 } \
887 } while (0)
888
889
890/**
891 * @brief Reverse the direction of 3D vector `v' and store it in `o'.
892 *
893 * NOTE: Reversing in place works (i.e., VREVERSE(v, v))
894 */
895#define VREVERSE(o, v) do { \
896 (o)[X] = -(v)[X]; \
897 (o)[Y] = -(v)[Y]; \
898 (o)[Z] = -(v)[Z]; \
899 } while (0)
900
901/**
902 * @brief Reverse the direction of 2D vector `v' and store it in `o'.
903 *
904 * NOTE: Reversing in place works (i.e., V2REVERSE(v, v))
905 */
906#define V2REVERSE(o, v) do { \
907 (o)[X] = -(v)[X]; \
908 (o)[Y] = -(v)[Y]; \
909 } while (0)
910
911/**
912 * @brief Same as VREVERSE, but for a 4-tuple. Also useful on plane_t
913 * objects.
914 *
915 * NOTE: Reversing in place works (i.e., HREVERSE(v, v))
916 */
917#define HREVERSE(o, v) do { \
918 (o)[X] = -(v)[X]; \
919 (o)[Y] = -(v)[Y]; \
920 (o)[Z] = -(v)[Z]; \
921 (o)[W] = -(v)[W]; \
922 } while (0)
923
924/** @brief Add 3D vectors at `a' and `b', store result at `o'. */
925#define VADD2(o, a, b) do { \
926 (o)[X] = (a)[X] + (b)[X]; \
927 (o)[Y] = (a)[Y] + (b)[Y]; \
928 (o)[Z] = (a)[Z] + (b)[Z]; \
929 } while (0)
930
931/** @brief Add 2D vectors at `a' and `b', store result at `o'. */
932#define V2ADD2(o, a, b) do { \
933 (o)[X] = (a)[X] + (b)[X]; \
934 (o)[Y] = (a)[Y] + (b)[Y]; \
935 } while (0)
936
937/** @brief Add 4D vectors at `a' and `b', store result at `o'. */
938#define HADD2(o, a, b) do { \
939 (o)[X] = (a)[X] + (b)[X]; \
940 (o)[Y] = (a)[Y] + (b)[Y]; \
941 (o)[Z] = (a)[Z] + (b)[Z]; \
942 (o)[W] = (a)[W] + (b)[W]; \
943 } while (0)
944
945/**
946 * @brief Add vectors of length `n' at `a' and `b', store result at
947 * `o'.
948 */
949#define VADD2N(o, a, b, n) do { \
950 size_t _vadd2; \
951 for (_vadd2 = 0; _vadd2 < (size_t)(n); _vadd2++) { \
952 (o)[_vadd2] = (a)[_vadd2] + (b)[_vadd2]; \
953 } \
954 } while (0)
955
956
957/**
958 * @brief Subtract 3D vector at `b' from vector at `a', store result at
959 * `o'.
960 */
961#define VSUB2(o, a, b) do { \
962 (o)[X] = (a)[X] - (b)[X]; \
963 (o)[Y] = (a)[Y] - (b)[Y]; \
964 (o)[Z] = (a)[Z] - (b)[Z]; \
965 } while (0)
966
967/**
968 * @brief Subtract 2D vector at `b' from vector at `a', store result at
969 * `o'.
970 */
971#define V2SUB2(o, a, b) do { \
972 (o)[X] = (a)[X] - (b)[X]; \
973 (o)[Y] = (a)[Y] - (b)[Y]; \
974 } while (0)
975
976/**
977 * @brief Subtract 4D vector at `b' from vector at `a', store result at
978 * `o'.
979 */
980#define HSUB2(o, a, b) do { \
981 (o)[X] = (a)[X] - (b)[X]; \
982 (o)[Y] = (a)[Y] - (b)[Y]; \
983 (o)[Z] = (a)[Z] - (b)[Z]; \
984 (o)[W] = (a)[W] - (b)[W]; \
985 } while (0)
986
987/**
988 * @brief Subtract `n' length vector at `b' from `n' length vector at
989 * `a', store result at `o'.
990 */
991#define VSUB2N(o, a, b, n) do { \
992 size_t _vsub2; \
993 for (_vsub2 = 0; _vsub2 < (size_t)(n); _vsub2++) { \
994 (o)[_vsub2] = (a)[_vsub2] - (b)[_vsub2]; \
995 } \
996 } while (0)
997
998
999/** @brief 3D Vectors: O = A - B - C */
1000#define VSUB3(o, a, b, c) do { \
1001 (o)[X] = (a)[X] - (b)[X] - (c)[X]; \
1002 (o)[Y] = (a)[Y] - (b)[Y] - (c)[Y]; \
1003 (o)[Z] = (a)[Z] - (b)[Z] - (c)[Z]; \
1004 } while (0)
1005
1006/** @brief 2D Vectors: O = A - B - C */
1007#define V2SUB3(o, a, b, c) do { \
1008 (o)[X] = (a)[X] - (b)[X] - (c)[X]; \
1009 (o)[Y] = (a)[Y] - (b)[Y] - (c)[Y]; \
1010 } while (0)
1011
1012/** @brief 4D Vectors: O = A - B - C */
1013#define HSUB3(o, a, b, c) do { \
1014 (o)[X] = (a)[X] - (b)[X] - (c)[X]; \
1015 (o)[Y] = (a)[Y] - (b)[Y] - (c)[Y]; \
1016 (o)[Z] = (a)[Z] - (b)[Z] - (c)[Z]; \
1017 (o)[W] = (a)[W] - (b)[W] - (c)[W]; \
1018 } while (0)
1019
1020/** @brief Vectors: O = A - B - C for vectors of length `n'. */
1021#define VSUB3N(o, a, b, c, n) do { \
1022 size_t _vsub3; \
1023 for (_vsub3 = 0; _vsub3 < (size_t)(n); _vsub3++) { \
1024 (o)[_vsub3] = (a)[_vsub3] - (b)[_vsub3] - (c)[_vsub3]; \
1025 } \
1026 } while (0)
1027
1028
1029/** @brief Add 3 3D vectors at `a', `b', and `c', store result at `o'. */
1030#define VADD3(o, a, b, c) do { \
1031 (o)[X] = (a)[X] + (b)[X] + (c)[X]; \
1032 (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y]; \
1033 (o)[Z] = (a)[Z] + (b)[Z] + (c)[Z]; \
1034 } while (0)
1035
1036/** @brief Add 3 2D vectors at `a', `b', and `c', store result at `o'. */
1037#define V2ADD3(o, a, b, c) do { \
1038 (o)[X] = (a)[X] + (b)[X] + (c)[X]; \
1039 (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y]; \
1040 } while (0)
1041
1042/** @brief Add 3 4D vectors at `a', `b', and `c', store result at `o'. */
1043#define HADD3(o, a, b, c) do { \
1044 (o)[X] = (a)[X] + (b)[X] + (c)[X]; \
1045 (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y]; \
1046 (o)[Z] = (a)[Z] + (b)[Z] + (c)[Z]; \
1047 (o)[W] = (a)[W] + (b)[W] + (c)[W]; \
1048 } while (0)
1049
1050/**
1051 * @brief Add 3 vectors of length `n' at `a', `b', and `c', store
1052 * result at `o'.
1053 */
1054#define VADD3N(o, a, b, c, n) do { \
1055 size_t _vadd3; \
1056 for (_vadd3 = 0; _vadd3 < (size_t)(n); _vadd3++) { \
1057 (o)[_vadd3] = (a)[_vadd3] + (b)[_vadd3] + (c)[_vadd3]; \
1058 } \
1059 } while (0)
1060
1061
1062/**
1063 * @brief Add 4 vectors at `a', `b', `c', and `d', store result at
1064 * `o'.
1065 */
1066#define VADD4(o, a, b, c, d) do { \
1067 (o)[X] = (a)[X] + (b)[X] + (c)[X] + (d)[X]; \
1068 (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y] + (d)[Y]; \
1069 (o)[Z] = (a)[Z] + (b)[Z] + (c)[Z] + (d)[Z]; \
1070 } while (0)
1071
1072/**
1073 * @brief Add 4 2D vectors at `a', `b', `c', and `d', store result at
1074 * `o'.
1075 */
1076#define V2ADD4(o, a, b, c, d) do { \
1077 (o)[X] = (a)[X] + (b)[X] + (c)[X] + (d)[X]; \
1078 (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y] + (d)[Y]; \
1079 } while (0)
1080
1081/**
1082 * @brief Add 4 4D vectors at `a', `b', `c', and `d', store result at
1083 * `o'.
1084 */
1085#define HADD4(o, a, b, c, d) do { \
1086 (o)[X] = (a)[X] + (b)[X] + (c)[X] + (d)[X]; \
1087 (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y] + (d)[Y]; \
1088 (o)[Z] = (a)[Z] + (b)[Z] + (c)[Z] + (d)[Z]; \
1089 (o)[W] = (a)[W] + (b)[W] + (c)[W] + (d)[W]; \
1090 } while (0)
1091
1092/**
1093 * @brief Add 4 `n' length vectors at `a', `b', `c', and `d', store
1094 * result at `o'.
1095 */
1096#define VADD4N(o, a, b, c, d, n) do { \
1097 size_t _vadd4; \
1098 for (_vadd4 = 0; _vadd4 < (size_t)(n); _vadd4++) { \
1099 (o)[_vadd4] = (a)[_vadd4] + (b)[_vadd4] + (c)[_vadd4] + (d)[_vadd4]; \
1100 } \
1101 } while (0)
1102
1103
1104/** @brief Scale 3D vector at `v' by scalar `s', store result at `o'. */
1105#define VSCALE(o, v, s) do { \
1106 (o)[X] = (v)[X] * (s); \
1107 (o)[Y] = (v)[Y] * (s); \
1108 (o)[Z] = (v)[Z] * (s); \
1109 } while (0)
1110
1111/** @brief Scale 2D vector at `v' by scalar `s', store result at `o'. */
1112#define V2SCALE(o, v, s) do { \
1113 (o)[X] = (v)[X] * (s); \
1114 (o)[Y] = (v)[Y] * (s); \
1115 } while (0)
1116
1117/** @brief Scale 4D vector at `v' by scalar `s', store result at `o'. */
1118#define HSCALE(o, v, s) do { \
1119 (o)[X] = (v)[X] * (s); \
1120 (o)[Y] = (v)[Y] * (s); \
1121 (o)[Z] = (v)[Z] * (s); \
1122 (o)[W] = (v)[W] * (s); \
1123 } while (0)
1124
1125/**
1126 * @brief Scale vector of length `n' at `v' by scalar `s', store
1127 * result at `o'
1128 */
1129#define VSCALEN(o, v, s, n) do { \
1130 size_t _vscale; \
1131 for (_vscale = 0; _vscale < (size_t)(n); _vscale++) { \
1132 (o)[_vscale] = (v)[_vscale] * (s); \
1133 } \
1134 } while (0)
1135
1136/** @brief Normalize vector `v' to be a unit vector. */
1137#define VUNITIZE(v) do { \
1138 double _f = MAGSQ(v); \
1139 if (! NEAR_EQUAL(_f, 1.0, VUNITIZE_TOL)) { \
1140 _f = sqrt(_f); \
1141 if (_f < VDIVIDE_TOL) { \
1142 VSETALL((v), 0.0); \
1143 } else { \
1144 _f = 1.0/_f; \
1145 (v)[X] *= _f; (v)[Y] *= _f; (v)[Z] *= _f; \
1146 } \
1147 } \
1148 } while (0)
1149
1150/** @brief Normalize 2D vector `v' to be a unit vector. */
1151#define V2UNITIZE(v) do { \
1152 double _f = MAG2SQ(v); \
1153 if (! NEAR_EQUAL(_f, 1.0, VUNITIZE_TOL)) { \
1154 _f = sqrt(_f); \
1155 if (_f < VDIVIDE_TOL) { \
1156 V2SETALL((v), 0.0); \
1157 } else { \
1158 _f = 1.0/_f; \
1159 (v)[X] *= _f; (v)[Y] *= _f; \
1160 } \
1161 } \
1162 } while (0)
1163
1164/**
1165 * @brief Find the sum of two points, and scale the result. Often
1166 * used to find the midpoint.
1167 */
1168#define VADD2SCALE(o, a, b, s) do { \
1169 (o)[X] = ((a)[X] + (b)[X]) * (s); \
1170 (o)[Y] = ((a)[Y] + (b)[Y]) * (s); \
1171 (o)[Z] = ((a)[Z] + (b)[Z]) * (s); \
1172 } while (0)
1173
1174/**
1175 * @brief Find the sum of two vectors of length `n', and scale the
1176 * result by `s'. Often used to find the midpoint.
1177 */
1178#define VADD2SCALEN(o, a, b, s, n) do { \
1179 size_t _vadd2scale; \
1180 for (_vadd2scale = 0; \
1181 _vadd2scale < (size_t)(n); \
1182 _vadd2scale++) { \
1183 (o)[_vadd2scale] = ((a)[_vadd2scale] + (b)[_vadd2scale]) * (s); \
1184 } \
1185 } while (0)
1186
1187/**
1188 * @brief Find the difference between two points, and scale result.
1189 * Often used to compute bounding sphere radius given rpp points.
1190 */
1191#define VSUB2SCALE(o, a, b, s) do { \
1192 (o)[X] = ((a)[X] - (b)[X]) * (s); \
1193 (o)[Y] = ((a)[Y] - (b)[Y]) * (s); \
1194 (o)[Z] = ((a)[Z] - (b)[Z]) * (s); \
1195 } while (0)
1196
1197/**
1198 * @brief Find the difference between two vectors of length `n', and
1199 * scale result by `s'.
1200 */
1201#define VSUB2SCALEN(o, a, b, s, n) do { \
1202 size_t _vsub2scale; \
1203 for (_vsub2scale = 0; \
1204 _vsub2scale < (size_t)(n); \
1205 _vsub2scale++) { \
1206 (o)[_vsub2scale] = ((a)[_vsub2scale] - (b)[_vsub2scale]) * (s); \
1207 } \
1208 } while (0)
1209
1210
1211/**
1212 * @brief Combine together three vectors, all scaled by scalars.
1213 *
1214 * DEPRECATED: API inconsistent, use combo of other macros.
1215 */
1216#define VCOMB3(o, a, b, c, d, e, f) do { \
1217 (o)[X] = (a) * (b)[X] + (c) * (d)[X] + (e) * (f)[X]; \
1218 (o)[Y] = (a) * (b)[Y] + (c) * (d)[Y] + (e) * (f)[Y]; \
1219 (o)[Z] = (a) * (b)[Z] + (c) * (d)[Z] + (e) * (f)[Z]; \
1220 } while (0)
1221
1222/**
1223 * @brief Combine together three vectors of length `n', all scaled by
1224 * scalars.
1225 *
1226 * DEPRECATED: API inconsistent, use combo of other macros.
1227 */
1228#define VCOMB3N(o, a, b, c, d, e, f, n) do { \
1229 size_t _vcomb3; \
1230 for (_vcomb3 = 0; \
1231 _vcomb3 < (size_t)(n); \
1232 _vcomb3++) { \
1233 (o)[_vcomb3] = (a) * (b)[_vcomb3] + (c) * (d)[_vcomb3] + (e) * (f)[_vcomb3]; \
1234 } \
1235 } while (0)
1236
1237/**
1238 * @brief Combine together 2 vectors, both scaled by scalars.
1239 */
1240#define VCOMB2(o, sa, va, sb, vb) do { \
1241 (o)[X] = (sa) * (va)[X] + (sb) * (vb)[X]; \
1242 (o)[Y] = (sa) * (va)[Y] + (sb) * (vb)[Y]; \
1243 (o)[Z] = (sa) * (va)[Z] + (sb) * (vb)[Z]; \
1244 } while (0)
1245
1246/**
1247 * @brief Combine together 2 vectors of length `n', both scaled by
1248 * scalars.
1249 */
1250#define VCOMB2N(o, sa, a, sb, b, n) do { \
1251 size_t _vcomb2; \
1252 for (_vcomb2 = 0; \
1253 _vcomb2 < (size_t)(n); \
1254 _vcomb2++) { \
1255 (o)[_vcomb2] = (sa) * (va)[_vcomb2] + (sb) * (vb)[_vcomb2]; \
1256 } \
1257 } while (0)
1258
1259/**
1260 * DEPRECATED.
1261 */
1262#define VJOIN4(a, b, c, d, e, f, g, h, i, j) do { \
1263 (a)[X] = (b)[X] + (c)*(d)[X] + (e)*(f)[X] + (g)*(h)[X] + (i)*(j)[X]; \
1264 (a)[Y] = (b)[Y] + (c)*(d)[Y] + (e)*(f)[Y] + (g)*(h)[Y] + (i)*(j)[Y]; \
1265 (a)[Z] = (b)[Z] + (c)*(d)[Z] + (e)*(f)[Z] + (g)*(h)[Z] + (i)*(j)[Z]; \
1266 } while (0)
1267
1268/**
1269 * Join three scaled vectors to a base `a', storing the result in `o'.
1270 */
1271#define VJOIN3(o, a, sb, b, sc, c, sd, d) do { \
1272 (o)[X] = (a)[X] + (sb)*(b)[X] + (sc)*(c)[X] + (sd)*(d)[X]; \
1273 (o)[Y] = (a)[Y] + (sb)*(b)[Y] + (sc)*(c)[Y] + (sd)*(d)[Y]; \
1274 (o)[Z] = (a)[Z] + (sb)*(b)[Z] + (sc)*(c)[Z] + (sd)*(d)[Z]; \
1275 } while (0)
1276
1277
1278/**
1279 * @brief Compose 3D vector at `o' of:
1280 * Vector at `a' plus
1281 * scalar `sb' times vector at `b' plus
1282 * scalar `sc' times vector at `c'
1283 */
1284#define VJOIN2(o, a, sb, b, sc, c) do { \
1285 (o)[X] = (a)[X] + (sb) * (b)[X] + (sc) * (c)[X]; \
1286 (o)[Y] = (a)[Y] + (sb) * (b)[Y] + (sc) * (c)[Y]; \
1287 (o)[Z] = (a)[Z] + (sb) * (b)[Z] + (sc) * (c)[Z]; \
1288 } while (0)
1289
1290/**
1291 * @brief Compose 2D vector at `o' of:
1292 * Vector at `a' plus
1293 * scalar `sb' times vector at `b' plus
1294 * scalar `sc' times vector at `c'
1295 */
1296#define V2JOIN2(o, a, sb, b, sc, c) do { \
1297 (o)[X] = (a)[X] + (sb) * (b)[X] + (sc) * (c)[X]; \
1298 (o)[Y] = (a)[Y] + (sb) * (b)[Y] + (sc) * (c)[Y]; \
1299 } while (0)
1300
1301/**
1302 * @brief Compose 4D vector at `o' of:
1303 * Vector at `a' plus
1304 * scalar `sb' times vector at `b' plus
1305 * scalar `sc' times vector at `c'
1306 */
1307#define HJOIN2(o, a, sb, b, sc, c) do { \
1308 (o)[X] = (a)[X] + (sb) * (b)[X] + (sc) * (c)[X]; \
1309 (o)[Y] = (a)[Y] + (sb) * (b)[Y] + (sc) * (c)[Y]; \
1310 (o)[Z] = (a)[Z] + (sb) * (b)[Z] + (sc) * (c)[Z]; \
1311 (o)[W] = (a)[W] + (sb) * (b)[W] + (sc) * (c)[W]; \
1312 } while (0)
1313
1314#define VJOIN2N(o, a, sb, b, sc, c, n) do { \
1315 size_t _vjoin2; \
1316 for (_vjoin2 = 0; \
1317 _vjoin2 < (size_t)(n); \
1318 _vjoin2++) { \
1319 (o)[_vjoin2] = (a)[_vjoin2] + (sb) * (b)[_vjoin2] + (sc) * (c)[_vjoin2]; \
1320 } \
1321 } while (0)
1322
1323
1324/**
1325 * Compose 3D vector at `o' of:
1326 * vector at `a' plus
1327 * scalar `sb' times vector at `b'
1328 *
1329 * This is basically a shorthand for VSCALE();VADD2();.
1330 */
1331#define VJOIN1(o, a, sb, b) do { \
1332 (o)[X] = (a)[X] + (sb) * (b)[X]; \
1333 (o)[Y] = (a)[Y] + (sb) * (b)[Y]; \
1334 (o)[Z] = (a)[Z] + (sb) * (b)[Z]; \
1335 } while (0)
1336
1337/**
1338 * Compose 2D vector at `o' of:
1339 * vector at `a' plus
1340 * scalar `sb' times vector at `b'
1341 *
1342 * This is basically a shorthand for V2SCALE();V2ADD2();.
1343 */
1344#define V2JOIN1(o, a, sb, b) do { \
1345 (o)[X] = (a)[X] + (sb) * (b)[X]; \
1346 (o)[Y] = (a)[Y] + (sb) * (b)[Y]; \
1347 } while (0)
1348
1349/**
1350 * Compose 4D vector at `o' of:
1351 * vector at `a' plus
1352 * scalar `sb' times vector at `b'
1353 *
1354 * This is basically a shorthand for HSCALE();HADD2();.
1355 */
1356#define HJOIN1(o, a, sb, b) do { \
1357 (o)[X] = (a)[X] + (sb) * (b)[X]; \
1358 (o)[Y] = (a)[Y] + (sb) * (b)[Y]; \
1359 (o)[Z] = (a)[Z] + (sb) * (b)[Z]; \
1360 (o)[W] = (a)[W] + (sb) * (b)[W]; \
1361 } while (0)
1362
1363/**
1364 * Compose `n'-D vector at `o' of:
1365 * vector at `a' plus
1366 * scalar `sb' times vector at `b'
1367 *
1368 * This is basically a shorthand for VSCALEN();VADD2N();.
1369 */
1370#define VJOIN1N(o, a, sb, b, n) do { \
1371 size_t _vjoin1; \
1372 for (_vjoin1 = 0; \
1373 _vjoin1 < (size_t)(n); \
1374 _vjoin1++) { \
1375 (o)[_vjoin1] = (a)[_vjoin1] + (sb) * (b)[_vjoin1]; \
1376 } \
1377 } while (0)
1378
1379
1380/**
1381 * @brief Blend into vector `o'
1382 * scalar `sa' times vector at `a' plus
1383 * scalar `sb' times vector at `b'
1384 */
1385#define VBLEND2(o, sa, a, sb, b) do { \
1386 (o)[X] = (sa) * (a)[X] + (sb) * (b)[X]; \
1387 (o)[Y] = (sa) * (a)[Y] + (sb) * (b)[Y]; \
1388 (o)[Z] = (sa) * (a)[Z] + (sb) * (b)[Z]; \
1389 } while (0)
1390
1391/**
1392 * @brief Blend into vector `o'
1393 * scalar `sa' times vector at `a' plus
1394 * scalar `sb' times vector at `b'
1395 */
1396#define VBLEND2N(o, sa, a, sb, b, n) do { \
1397 size_t _vblend2; \
1398 for (_vblend2 = 0; \
1399 _vblend2 < (size_t)(n); \
1400 _vblend2++) { \
1401 (b)[_vblend2] = (sa) * (a)[_vblend2] + (sb) * (b)[_vblend2]; \
1402 } \
1403 } while (0)
1404
1405
1406/**
1407 * @brief Project vector `a' onto `b'
1408 * vector `c' is the component of `a' parallel to `b'
1409 * " `d' " " " " " orthogonal " "
1410 *
1411 * FIXME: consistency, the result should come first
1412 */
1413#define VPROJECT(a, b, c, d) do { \
1414 VSCALE(c, b, VDOT(a, b) / VDOT(b, b)); \
1415 VSUB2(d, a, c); \
1416 } while (0)
1417
1418/** @brief Return scalar magnitude squared of vector at `v' */
1419#define MAGSQ(v) ((v)[X]*(v)[X] + (v)[Y]*(v)[Y] + (v)[Z]*(v)[Z])
1420#define MAG2SQ(v) ((v)[X]*(v)[X] + (v)[Y]*(v)[Y])
1421
1422
1423/**
1424 * @brief Return scalar magnitude of the 3D vector `a'. This is
1425 * otherwise known as the Euclidean norm of the provided vector..
1426 */
1427#define MAGNITUDE(v) sqrt(MAGSQ(v))
1428
1429/**
1430 * @brief Return scalar magnitude of the 2D vector at `a'. This is
1431 * otherwise known as the Euclidean norm of the provided vector..
1432 */
1433#define MAGNITUDE2(v) sqrt(MAG2SQ(v))
1434
1435/**
1436 * @brief Store cross product of 3D vectors at `a' and `b' in vector at `o'.
1437 *
1438 * NOTE: The "right hand rule" applies. If closing your right hand
1439 * goes from `a' to `b', then your thumb points in the direction of
1440 * the cross product.
1441 *
1442 * If the angle from `a' to `b' goes clockwise, then the result vector
1443 * points "into" the plane (inward normal). Example: a=(0, 1, 0),
1444 * b=(1, 0, 0), then aXb=(0, 0, -1).
1445 *
1446 * If the angle from `a' to `b' goes counter-clockwise, then the
1447 * result vector points "out" of the plane. This outward pointing
1448 * normal is the BRL-CAD convention.
1449 */
1450#define VCROSS(o, a, b) do { \
1451 (o)[X] = (a)[Y] * (b)[Z] - (a)[Z] * (b)[Y]; \
1452 (o)[Y] = (a)[Z] * (b)[X] - (a)[X] * (b)[Z]; \
1453 (o)[Z] = (a)[X] * (b)[Y] - (a)[Y] * (b)[X]; \
1454 } while (0)
1455
1456/**
1457 * Return the analog of a cross product for 2D vectors `a' and `b'
1458 * as a scalar value. If a = (ax, ay) and b = (bx, by), then the analog
1459 * of a x b is det(a*b) = ax*by - ay*bx
1460 */
1461#define V2CROSS(a, b) ((a)[X] * (b)[Y] - (a)[Y] * (b)[X])
1462
1463/**
1464 * TODO: implement me
1465 */
1466#define HCROSS(a, b, c)
1467
1468
1469/** @brief Compute dot product of vectors at `a' and `b'. */
1470#define VDOT(a, b) ((a)[X]*(b)[X] + (a)[Y]*(b)[Y] + (a)[Z]*(b)[Z])
1471
1472#define V2DOT(a, b) ((a)[X]*(b)[X] + (a)[Y]*(b)[Y])
1473
1474#define HDOT(a, b) ((a)[X]*(b)[X] + (a)[Y]*(b)[Y] + (a)[Z]*(b)[Z] + (a)[W]*(b)[W])
1475
1476
1477/**
1478 * @brief Linearly interpolate between two 3D vectors `a' and `b' by
1479 * interpolant `t', expected in the range [0,1], with result in `o'.
1480 *
1481 * NOTE: We intentionally use the form "o = a*(1-t) + b*t" which is
1482 * mathematically equivalent to "o = a + (b-a)*t". The latter might
1483 * result in fewer math operations but cannot guarantee o==v1 when
1484 * t==1 due to floating-point arithmetic error.
1485 */
1486#define VLERP(o, a, b, t) do { \
1487 (o)[X] = (a)[X] * (1 - (t)) + (b)[X] * (t); \
1488 (o)[Y] = (a)[Y] * (1 - (t)) + (b)[Y] * (t); \
1489 (o)[Z] = (a)[Z] * (1 - (t)) + (b)[Z] * (t); \
1490 } while (0)
1491
1492/**
1493 * @brief Linearly interpolate between two 2D vectors `a' and `b' by
1494 * interpolant `t', expected in the range [0,1], with result in `o'.
1495 *
1496 * NOTE: We intentionally use the form "o = a*(1-t) + b*t" which is
1497 * mathematically equivalent to "o = a + (b-a)*t". The latter might
1498 * result in fewer math operations but cannot guarantee o==v1 when
1499 * t==1 due to floating-point arithmetic error.
1500 */
1501#define V2LERP(o, a, b, t) do { \
1502 (o)[X] = (a)[X] * (1 - (t)) + (b)[X] * (t); \
1503 (o)[Y] = (a)[Y] * (1 - (t)) + (b)[Y] * (t); \
1504 } while (0)
1505
1506/**
1507 * @brief Linearly interpolate between two 4D vectors `a' and `b' by
1508 * interpolant `t', expected in the range [0,1], with result in `o'.
1509 *
1510 * NOTE: We intentionally use the form "o = a*(1-t) + b*t" which is
1511 * mathematically equivalent to "o = a + (b-a)*t". The latter might
1512 * result in fewer math operations but cannot guarantee o==v1 when
1513 * t==1 due to floating-point arithmetic error.
1514 */
1515#define HLERP(o, a, b, t) do { \
1516 (o)[X] = (a)[X] * (1 - (t)) + (b)[X] * (t); \
1517 (o)[Y] = (a)[Y] * (1 - (t)) + (b)[Y] * (t); \
1518 (o)[Z] = (a)[Z] * (1 - (t)) + (b)[Z] * (t); \
1519 (o)[W] = (a)[W] * (1 - (t)) + (b)[W] * (t); \
1520 } while (0)
1521
1522
1523/**
1524 * @brief Subtract two points to make a vector, dot with another
1525 * vector. Returns the dot product scalar value.
1526 */
1527#define VSUB2DOT(_pt2, _pt, _vec) (\
1528 ((_pt2)[X] - (_pt)[X]) * (_vec)[X] + \
1529 ((_pt2)[Y] - (_pt)[Y]) * (_vec)[Y] + \
1530 ((_pt2)[Z] - (_pt)[Z]) * (_vec)[Z])
1531
1532/**
1533 * @brief Turn a vector into comma-separated list of elements, for
1534 * variable argument subroutines (e.g. printf()).
1535 */
1536#define V2ARGS(a) (a)[X], (a)[Y]
1537#define V3ARGS(a) (a)[X], (a)[Y], (a)[Z]
1538#define V4ARGS(a) (a)[X], (a)[Y], (a)[Z], (a)[W]
1539
1540/**
1541 * Clamp values within tolerance of an integer to that value.
1542 *
1543 * For example, INTCLAMP(10.0000123123) evaluates to 10.0
1544 *
1545 * NOTE: should use VDIVIDE_TOL here, but cannot yet. we use
1546 * VUINITIZE_TOL until floats are replaced universally with fastf_t's
1547 * since their epsilon is considerably less than that of a double.
1548 */
1549#define INTCLAMP(_a) (NEAR_EQUAL((_a), rint(_a), VUNITIZE_TOL) ? rint(_a) : (_a))
1550
1551/** Clamp a 3D vector's elements to nearby integer values. */
1552#define VINTCLAMP(_v) do { \
1553 (_v)[X] = INTCLAMP((_v)[X]); \
1554 (_v)[Y] = INTCLAMP((_v)[Y]); \
1555 (_v)[Z] = INTCLAMP((_v)[Z]); \
1556 } while (0)
1557
1558/** Clamp a 2D vector's elements to nearby integer values. */
1559#define V2INTCLAMP(_v) do { \
1560 (_v)[X] = INTCLAMP((_v)[X]); \
1561 (_v)[Y] = INTCLAMP((_v)[Y]); \
1562 } while (0)
1563
1564/** Clamp a 4D vector's elements to nearby integer values. */
1565#define HINTCLAMP(_v) do { \
1566 VINTCLAMP(_v); \
1567 (_v)[W] = INTCLAMP((_v)[W]); \
1568 } while (0)
1569
1570
1571/** @brief integer clamped versions of the previous arg macros. */
1572#define V2INTCLAMPARGS(a) INTCLAMP((a)[X]), INTCLAMP((a)[Y])
1573/** @brief integer clamped versions of the previous arg macros. */
1574#define V3INTCLAMPARGS(a) INTCLAMP((a)[X]), INTCLAMP((a)[Y]), INTCLAMP((a)[Z])
1575/** @brief integer clamped versions of the previous arg macros. */
1576#define V4INTCLAMPARGS(a) INTCLAMP((a)[X]), INTCLAMP((a)[Y]), INTCLAMP((a)[Z]), INTCLAMP((a)[W])
1577
1578/** @brief Print vector name and components on stderr. */
1579#define V2PRINT(a, b) \
1580 fprintf(stderr, "%s (%.6f, %.6g)\n", a, V2ARGS(b));
1581#define VPRINT(a, b) \
1582 fprintf(stderr, "%s (%.6f, %.6f, %.6f)\n", a, V3ARGS(b));
1583#define HPRINT(a, b) \
1584 fprintf(stderr, "%s (%.6f, %.6f, %.6f, %.6f)\n", a, V4ARGS(b));
1585
1586/**
1587 * @brief Included below are integer clamped versions of the previous
1588 * print macros.
1589 */
1590
1591#define V2INTCLAMPPRINT(a, b) \
1592 fprintf(stderr, "%s (%g, %g)\n", a, V2INTCLAMPARGS(b));
1593#define VINTCLAMPPRINT(a, b) \
1594 fprintf(stderr, "%s (%g, %g, %g)\n", a, V3INTCLAMPARGS(b));
1595#define HINTCLAMPPRINT(a, b) \
1596 fprintf(stderr, "%s (%g, %g, %g, %g)\n", a, V4INTCLAMPARGS(b));
1597
1598
1599/** @brief Vector element multiplication. Really: diagonal matrix X vect. */
1600#define VELMUL(o, a, b) do { \
1601 (o)[X] = (a)[X] * (b)[X]; \
1602 (o)[Y] = (a)[Y] * (b)[Y]; \
1603 (o)[Z] = (a)[Z] * (b)[Z]; \
1604 } while (0)
1605
1606#define VELMUL3(o, a, b, c) do { \
1607 (o)[X] = (a)[X] * (b)[X] * (c)[X]; \
1608 (o)[Y] = (a)[Y] * (b)[Y] * (c)[Y]; \
1609 (o)[Z] = (a)[Z] * (b)[Z] * (c)[Z]; \
1610 } while (0)
1611
1612/** @brief Similar to VELMUL. */
1613#define VELDIV(o, a, b) do { \
1614 (o)[X] = (a)[X] / (b)[X]; \
1615 (o)[Y] = (a)[Y] / (b)[Y]; \
1616 (o)[Z] = (a)[Z] / (b)[Z]; \
1617 } while (0)
1618
1619/**
1620 * @brief Given a direction vector, compute the inverses of each element.
1621 * When division by zero would have occurred, mark inverse as INFINITY.
1622 */
1623#define VINVDIR(_inv, _dir) do { \
1624 if ((_dir)[X] < -SQRT_SMALL_FASTF || (_dir)[X] > SQRT_SMALL_FASTF) { \
1625 (_inv)[X]=1.0/(_dir)[X]; \
1626 } else { \
1627 (_dir)[X] = 0.0; \
1628 (_inv)[X] = INFINITY; \
1629 } \
1630 if ((_dir)[Y] < -SQRT_SMALL_FASTF || (_dir)[Y] > SQRT_SMALL_FASTF) { \
1631 (_inv)[Y]=1.0/(_dir)[Y]; \
1632 } else { \
1633 (_dir)[Y] = 0.0; \
1634 (_inv)[Y] = INFINITY; \
1635 } \
1636 if ((_dir)[Z] < -SQRT_SMALL_FASTF || (_dir)[Z] > SQRT_SMALL_FASTF) { \
1637 (_inv)[Z]=1.0/(_dir)[Z]; \
1638 } else { \
1639 (_dir)[Z] = 0.0; \
1640 (_inv)[Z] = INFINITY; \
1641 } \
1642 } while (0)
1643
1644/**
1645 * @brief Apply the 3x3 part of a mat_t to a 3-tuple. This rotates a
1646 * vector without scaling it (changing its length).
1647 */
1648#define MAT3X3VEC(o, mat, vec) do { \
1649 (o)[X] = (mat)[X]*(vec)[X]+(mat)[Y]*(vec)[Y] + (mat)[ 2]*(vec)[Z]; \
1650 (o)[Y] = (mat)[4]*(vec)[X]+(mat)[5]*(vec)[Y] + (mat)[ 6]*(vec)[Z]; \
1651 (o)[Z] = (mat)[8]*(vec)[X]+(mat)[9]*(vec)[Y] + (mat)[10]*(vec)[Z]; \
1652 } while (0)
1653
1654/** @brief Multiply a 3-tuple by the 3x3 part of a mat_t. */
1655#define VEC3X3MAT(o, i, m) do { \
1656 (o)[X] = (i)[X]*(m)[X] + (i)[Y]*(m)[4] + (i)[Z]*(m)[8]; \
1657 (o)[Y] = (i)[X]*(m)[1] + (i)[Y]*(m)[5] + (i)[Z]*(m)[9]; \
1658 (o)[Z] = (i)[X]*(m)[2] + (i)[Y]*(m)[6] + (i)[Z]*(m)[10]; \
1659 } while (0)
1660
1661/** @brief Apply the 3x3 part of a mat_t to a 2-tuple (Z part=0). */
1662#define MAT3X2VEC(o, mat, vec) do { \
1663 (o)[X] = (mat)[0]*(vec)[X] + (mat)[Y]*(vec)[Y]; \
1664 (o)[Y] = (mat)[4]*(vec)[X] + (mat)[5]*(vec)[Y]; \
1665 (o)[Z] = (mat)[8]*(vec)[X] + (mat)[9]*(vec)[Y]; \
1666 } while (0)
1667
1668/** @brief Multiply a 2-tuple (Z=0) by the 3x3 part of a mat_t. */
1669#define VEC2X3MAT(o, i, m) do { \
1670 (o)[X] = (i)[X]*(m)[0] + (i)[Y]*(m)[4]; \
1671 (o)[Y] = (i)[X]*(m)[1] + (i)[Y]*(m)[5]; \
1672 (o)[Z] = (i)[X]*(m)[2] + (i)[Y]*(m)[6]; \
1673 } while (0)
1674
1675/**
1676 * @brief Apply a 4x4 matrix to a 3-tuple which is an absolute Point
1677 * in space. Output and input points should be separate arrays.
1678 */
1679#define MAT4X3PNT(o, m, i) do { \
1680 double _f; \
1681 _f = 1.0/((m)[12]*(i)[X] + (m)[13]*(i)[Y] + (m)[14]*(i)[Z] + (m)[15]); \
1682 (o)[X]=((m)[0]*(i)[X] + (m)[1]*(i)[Y] + (m)[ 2]*(i)[Z] + (m)[3]) * _f; \
1683 (o)[Y]=((m)[4]*(i)[X] + (m)[5]*(i)[Y] + (m)[ 6]*(i)[Z] + (m)[7]) * _f; \
1684 (o)[Z]=((m)[8]*(i)[X] + (m)[9]*(i)[Y] + (m)[10]*(i)[Z] + (m)[11])* _f; \
1685 } while (0)
1686
1687/**
1688 * @brief Multiply an Absolute 3-Point by a full 4x4 matrix. Output
1689 * and input points should be separate arrays.
1690 */
1691#define PNT3X4MAT(o, i, m) do { \
1692 double _f; \
1693 _f = 1.0/((i)[X]*(m)[3] + (i)[Y]*(m)[7] + (i)[Z]*(m)[11] + (m)[15]); \
1694 (o)[X]=((i)[X]*(m)[0] + (i)[Y]*(m)[4] + (i)[Z]*(m)[8] + (m)[12]) * _f; \
1695 (o)[Y]=((i)[X]*(m)[1] + (i)[Y]*(m)[5] + (i)[Z]*(m)[9] + (m)[13]) * _f; \
1696 (o)[Z]=((i)[X]*(m)[2] + (i)[Y]*(m)[6] + (i)[Z]*(m)[10] + (m)[14])* _f; \
1697 } while (0)
1698
1699/**
1700 * @brief Multiply an Absolute hvect_t 4-Point by a full 4x4 matrix.
1701 * Output and input points should be separate arrays.
1702 */
1703#define MAT4X4PNT(o, m, i) do { \
1704 (o)[X]=(m)[ 0]*(i)[X] + (m)[ 1]*(i)[Y] + (m)[ 2]*(i)[Z] + (m)[ 3]*(i)[W]; \
1705 (o)[Y]=(m)[ 4]*(i)[X] + (m)[ 5]*(i)[Y] + (m)[ 6]*(i)[Z] + (m)[ 7]*(i)[W]; \
1706 (o)[Z]=(m)[ 8]*(i)[X] + (m)[ 9]*(i)[Y] + (m)[10]*(i)[Z] + (m)[11]*(i)[W]; \
1707 (o)[W]=(m)[12]*(i)[X] + (m)[13]*(i)[Y] + (m)[14]*(i)[Z] + (m)[15]*(i)[W]; \
1708 } while (0)
1709
1710/**
1711 * @brief Apply a 4x4 matrix to a 3-tuple which is a relative Vector
1712 * in space. This macro can scale the length of the vector if [15] !=
1713 * 1.0. Output and input vectors should be separate arrays.
1714 */
1715#define MAT4X3VEC(o, m, i) do { \
1716 double _f; \
1717 _f = 1.0/((m)[15]); \
1718 (o)[X] = ((m)[0]*(i)[X] + (m)[1]*(i)[Y] + (m)[ 2]*(i)[Z]) * _f; \
1719 (o)[Y] = ((m)[4]*(i)[X] + (m)[5]*(i)[Y] + (m)[ 6]*(i)[Z]) * _f; \
1720 (o)[Z] = ((m)[8]*(i)[X] + (m)[9]*(i)[Y] + (m)[10]*(i)[Z]) * _f; \
1721 } while (0)
1722
1723#define MAT4XSCALOR(o, m, i) do { \
1724 (o) = (i) / (m)[15]; \
1725 } while (0)
1726
1727/**
1728 * @brief Multiply a Relative 3-Vector by most of a 4x4 matrix.
1729 * Output and input vectors should be separate arrays.
1730 */
1731#define VEC3X4MAT(o, i, m) do { \
1732 double _f; \
1733 _f = 1.0/((m)[15]); \
1734 (o)[X] = ((i)[X]*(m)[0] + (i)[Y]*(m)[4] + (i)[Z]*(m)[8]) * _f; \
1735 (o)[Y] = ((i)[X]*(m)[1] + (i)[Y]*(m)[5] + (i)[Z]*(m)[9]) * _f; \
1736 (o)[Z] = ((i)[X]*(m)[2] + (i)[Y]*(m)[6] + (i)[Z]*(m)[10]) * _f; \
1737 } while (0)
1738
1739/** @brief Multiply a Relative 2-Vector by most of a 4x4 matrix. */
1740#define VEC2X4MAT(o, i, m) do { \
1741 double _f; \
1742 _f = 1.0/((m)[15]); \
1743 (o)[X] = ((i)[X]*(m)[0] + (i)[Y]*(m)[4]) * _f; \
1744 (o)[Y] = ((i)[X]*(m)[1] + (i)[Y]*(m)[5]) * _f; \
1745 (o)[Z] = ((i)[X]*(m)[2] + (i)[Y]*(m)[6]) * _f; \
1746 } while (0)
1747
1748/**
1749 * @brief Included below are macros to update min and max X, Y, Z
1750 * values to contain a point
1751 */
1752
1753#define V_MIN(r, s) if ((r) > (s)) r = (s)
1754
1755#define V_MAX(r, s) if ((r) < (s)) r = (s)
1756
1757#ifdef VMIN
1758# undef VMIN
1759#endif
1760#define VMIN(r, s) do { \
1761 V_MIN((r)[X], (s)[X]); V_MIN((r)[Y], (s)[Y]); V_MIN((r)[Z], (s)[Z]); \
1762 } while (0)
1763
1764#ifdef VMAX
1765# undef VMAX
1766#endif
1767#define VMAX(r, s) do { \
1768 V_MAX((r)[X], (s)[X]); V_MAX((r)[Y], (s)[Y]); V_MAX((r)[Z], (s)[Z]); \
1769 } while (0)
1770
1771#ifdef VMINMAX
1772# undef VMINMAX
1773#endif
1774#define VMINMAX(min, max, pt) do { \
1775 VMIN((min), (pt)); VMAX((max), (pt)); \
1776 } while (0)
1777
1778/**
1779 * @brief Included below are macros to update min and max X, Y
1780 * values to contain a point
1781 */
1782
1783#define V2MIN(r, s) do { \
1784 V_MIN((r)[X], (s)[X]); V_MIN((r)[Y], (s)[Y]); \
1785 } while (0)
1786
1787#define V2MAX(r, s) do { \
1788 V_MAX((r)[X], (s)[X]); V_MAX((r)[Y], (s)[Y]); \
1789 } while (0)
1790
1791#define V2MINMAX(min, max, pt) do { \
1792 V2MIN((min), (pt)); V2MAX((max), (pt)); \
1793 } while (0)
1794
1795/**
1796 * clamp a value to a low/high number.
1797 */
1798#define CLAMP(_v, _l, _h) V_MAX((_v), (_l)); else V_MIN((_v), (_h))
1799
1800
1801/**
1802 * @brief Divide out homogeneous parameter from hvect_t, creating
1803 * vect_t.
1804 */
1805#define HDIVIDE(o, v) do { \
1806 (o)[X] = (v)[X] / (v)[W]; \
1807 (o)[Y] = (v)[Y] / (v)[W]; \
1808 (o)[Z] = (v)[Z] / (v)[W]; \
1809 } while (0)
1810
1811/**
1812 * @brief Quaternion math definitions.
1813 *
1814 * Note that the [W] component will be put in the last (i.e., third)
1815 * place rather than the first [X] (i.e., [0]) place, so that the X,
1816 * Y, and Z elements will be compatible with vectors. Only
1817 * QUAT_FROM_VROT macros depend on component locations, however.
1818 */
1819
1820/**
1821 * @brief Create Quaternion from Vector and Rotation about vector.
1822 *
1823 * To produce a quaternion representing a rotation by PI radians about
1824 * X-axis:
1825 *
1826 * VSET(axis, 1, 0, 0);
1827 * QUAT_FROM_VROT(quat, M_PI, axis);
1828 * or
1829 * QUAT_FROM_ROT(quat, M_PI, 1.0, 0.0, 0.0, 0.0);
1830 *
1831 * Alternatively, in degrees:
1832 * QUAT_FROM_ROT_DEG(quat, 180.0, 1.0, 0.0, 0.0, 0.0);
1833 */
1834#define QUAT_FROM_ROT(q, r, x, y, z) do { \
1835 fastf_t _rot = (r) * 0.5; \
1836 QSET(q, x, y, z, cos(_rot)); \
1837 VUNITIZE(q); \
1838 _rot = sin(_rot); /* _rot is really just a temp variable now */ \
1839 VSCALE(q, q, _rot); \
1840 } while (0)
1841
1842#define QUAT_FROM_VROT(q, r, v) do { \
1843 fastf_t _rot = (r) * 0.5; \
1844 VMOVE(q, v); \
1845 VUNITIZE(q); \
1846 (q)[W] = cos(_rot); \
1847 _rot = sin(_rot); /* _rot is really just a temp variable now */ \
1848 VSCALE(q, q, _rot); \
1849 } while (0)
1850
1851#define QUAT_FROM_VROT_DEG(q, r, v) \
1852 QUAT_FROM_VROT(q, ((r)*DEG2RAD), v)
1853
1854#define QUAT_FROM_ROT_DEG(q, r, x, y, z) \
1855 QUAT_FROM_ROT(q, ((r)*DEG2RAD), x, y, z)
1856
1857
1858/**
1859 * @brief Set quaternion at `a' to have coordinates `b', `c', `d', and
1860 * `e'.
1861 */
1862#define QSET(a, b, c, d, e) do { \
1863 (a)[X] = (b); \
1864 (a)[Y] = (c); \
1865 (a)[Z] = (d); \
1866 (a)[W] = (e); \
1867 } while (0)
1868
1869/** @brief Transfer quaternion at `b' to quaternion at `a'. */
1870#define QMOVE(a, b) do { \
1871 (a)[X] = (b)[X]; \
1872 (a)[Y] = (b)[Y]; \
1873 (a)[Z] = (b)[Z]; \
1874 (a)[W] = (b)[W]; \
1875 } while (0)
1876
1877/** @brief Add quaternions at `b' and `c', store result at `a'. */
1878#define QADD2(a, b, c) do { \
1879 (a)[X] = (b)[X] + (c)[X]; \
1880 (a)[Y] = (b)[Y] + (c)[Y]; \
1881 (a)[Z] = (b)[Z] + (c)[Z]; \
1882 (a)[W] = (b)[W] + (c)[W]; \
1883 } while (0)
1884
1885/**
1886 * @brief Subtract quaternion at `c' from quaternion at `b', store
1887 * result at `a'.
1888 */
1889#define QSUB2(a, b, c) do { \
1890 (a)[X] = (b)[X] - (c)[X]; \
1891 (a)[Y] = (b)[Y] - (c)[Y]; \
1892 (a)[Z] = (b)[Z] - (c)[Z]; \
1893 (a)[W] = (b)[W] - (c)[W]; \
1894 } while (0)
1895
1896/**
1897 * @brief Scale quaternion at `b' by scalar `c', store result at
1898 * `a'.
1899 */
1900#define QSCALE(a, b, c) do { \
1901 (a)[X] = (b)[X] * (c); \
1902 (a)[Y] = (b)[Y] * (c); \
1903 (a)[Z] = (b)[Z] * (c); \
1904 (a)[W] = (b)[W] * (c); \
1905 } while (0)
1906
1907/** @brief Normalize quaternion 'a' to be a unit quaternion. */
1908#define QUNITIZE(a) do { \
1909 double _f; \
1910 _f = QMAGNITUDE(a); \
1911 if (_f < VDIVIDE_TOL) _f = 0.0; else _f = 1.0/_f; \
1912 (a)[X] *= _f; (a)[Y] *= _f; (a)[Z] *= _f; (a)[W] *= _f; \
1913 } while (0)
1914
1915/** @brief Return scalar magnitude squared of quaternion at `a'. */
1916#define QMAGSQ(a) \
1917 ((a)[X]*(a)[X] + (a)[Y]*(a)[Y] \
1918 + (a)[Z]*(a)[Z] + (a)[W]*(a)[W])
1919
1920/** @brief Return scalar magnitude of quaternion at `a'. */
1921#define QMAGNITUDE(a) sqrt(QMAGSQ(a))
1922
1923/** @brief Compute dot product of quaternions at `a' and `b'. */
1924#define QDOT(a, b) \
1925 ((a)[X]*(b)[X] + (a)[Y]*(b)[Y] \
1926 + (a)[Z]*(b)[Z] + (a)[W]*(b)[W])
1927
1928/**
1929 * @brief Compute quaternion product a = b * c
1930 *
1931 * a[W] = b[W]*c[W] - VDOT(b, c);
1932 * VCROSS(temp, b, c);
1933 * VJOIN2(a, temp, b[W], c, c[W], b);
1934 */
1935#define QMUL(a, b, c) do { \
1936 (a)[W] = (b)[W]*(c)[W] - (b)[X]*(c)[X] - (b)[Y]*(c)[Y] - (b)[Z]*(c)[Z]; \
1937 (a)[X] = (b)[W]*(c)[X] + (b)[X]*(c)[W] + (b)[Y]*(c)[Z] - (b)[Z]*(c)[Y]; \
1938 (a)[Y] = (b)[W]*(c)[Y] + (b)[Y]*(c)[W] + (b)[Z]*(c)[X] - (b)[X]*(c)[Z]; \
1939 (a)[Z] = (b)[W]*(c)[Z] + (b)[Z]*(c)[W] + (b)[X]*(c)[Y] - (b)[Y]*(c)[X]; \
1940 } while (0)
1941
1942/** @brief Conjugate quaternion */
1943#define QCONJUGATE(a, b) do { \
1944 (a)[X] = -(b)[X]; \
1945 (a)[Y] = -(b)[Y]; \
1946 (a)[Z] = -(b)[Z]; \
1947 (a)[W] = (b)[W]; \
1948 } while (0)
1949
1950/** @brief Multiplicative inverse quaternion */
1951#define QINVERSE(a, b) do { \
1952 double _f = QMAGSQ(b); \
1953 if (_f < VDIVIDE_TOL) _f = 0.0; else _f = 1.0/_f; \
1954 (a)[X] = -(b)[X] * _f; \
1955 (a)[Y] = -(b)[Y] * _f; \
1956 (a)[Z] = -(b)[Z] * _f; \
1957 (a)[W] = (b)[W] * _f; \
1958 } while (0)
1959
1960/**
1961 * @brief Blend into quaternion `a'
1962 *
1963 * scalar `b' times quaternion at `c' plus
1964 * scalar `d' times quaternion at `e'
1965 */
1966#define QBLEND2(a, b, c, d, e) do { \
1967 (a)[X] = (b) * (c)[X] + (d) * (e)[X]; \
1968 (a)[Y] = (b) * (c)[Y] + (d) * (e)[Y]; \
1969 (a)[Z] = (b) * (c)[Z] + (d) * (e)[Z]; \
1970 (a)[W] = (b) * (c)[W] + (d) * (e)[W]; \
1971 } while (0)
1972
1973/**
1974 * Macros for dealing with 3-D "extents", aka bounding boxes, that are
1975 * represented as axis-aligned right parallelepipeds (RPPs). This is
1976 * stored as two points: a min point, and a max point. RPP 1 is
1977 * defined by lo1, hi1, RPP 2 by lo2, hi2.
1978 */
1979
1980/**
1981 * Compare two bounding boxes and return true if they are disjoint.
1982 */
1983#define V3RPP_DISJOINT(_l1, _h1, _l2, _h2) \
1984 ((_l1)[X] > (_h2)[X] || (_l1)[Y] > (_h2)[Y] || (_l1)[Z] > (_h2)[Z] || \
1985 (_l2)[X] > (_h1)[X] || (_l2)[Y] > (_h1)[Y] || (_l2)[Z] > (_h1)[Z])
1986
1987/**
1988 * Compare two bounding boxes and return true if they are disjoint
1989 * by at least distance tolerance.
1990 */
1991#define V3RPP_DISJOINT_TOL(_l1, _h1, _l2, _h2, _t) \
1992 ((_l1)[X] > (_h2)[X] + (_t) || \
1993 (_l1)[Y] > (_h2)[Y] + (_t) || \
1994 (_l1)[Z] > (_h2)[Z] + (_t) || \
1995 (_l2)[X] > (_h1)[X] + (_t) || \
1996 (_l2)[Y] > (_h1)[Y] + (_t) || \
1997 (_l2)[Z] > (_h1)[Z] + (_t))
1998
1999/** Compare two bounding boxes and return true If they overlap. */
2000#define V3RPP_OVERLAP(_l1, _h1, _l2, _h2) \
2001 (! ((_l1)[X] > (_h2)[X] || (_l1)[Y] > (_h2)[Y] || (_l1)[Z] > (_h2)[Z] || \
2002 (_l2)[X] > (_h1)[X] || (_l2)[Y] > (_h1)[Y] || (_l2)[Z] > (_h1)[Z]))
2003
2004/**
2005 * @brief If two extents overlap within distance tolerance, return
2006 * true.
2007 */
2008#define V3RPP_OVERLAP_TOL(_l1, _h1, _l2, _h2, _t) \
2009 (! ((_l1)[X] > (_h2)[X] + (_t) || \
2010 (_l1)[Y] > (_h2)[Y] + (_t) || \
2011 (_l1)[Z] > (_h2)[Z] + (_t) || \
2012 (_l2)[X] > (_h1)[X] + (_t) || \
2013 (_l2)[Y] > (_h1)[Y] + (_t) || \
2014 (_l2)[Z] > (_h1)[Z] + (_t)))
2015
2016/**
2017 * @brief Is the point within or on the boundary of the RPP?
2018 *
2019 * FIXME: should not be using >= <=, '=' case is unreliable
2020 */
2021#define V3PNT_IN_RPP(_pt, _lo, _hi) (\
2022 (_pt)[X] >= (_lo)[X] && (_pt)[X] <= (_hi)[X] && \
2023 (_pt)[Y] >= (_lo)[Y] && (_pt)[Y] <= (_hi)[Y] && \
2024 (_pt)[Z] >= (_lo)[Z] && (_pt)[Z] <= (_hi)[Z])
2025
2026/**
2027 * @brief Within the distance tolerance, is the point within the RPP?
2028 *
2029 * FIXME: should not be using >= <=, '=' case is unreliable
2030 */
2031#define V3PNT_IN_RPP_TOL(_pt, _lo, _hi, _t) (\
2032 (_pt)[X] >= (_lo)[X]-(_t) && (_pt)[X] <= (_hi)[X]+(_t) && \
2033 (_pt)[Y] >= (_lo)[Y]-(_t) && (_pt)[Y] <= (_hi)[Y]+(_t) && \
2034 (_pt)[Z] >= (_lo)[Z]-(_t) && (_pt)[Z] <= (_hi)[Z]+(_t))
2035
2036/**
2037 * @brief Is the point outside the RPP by at least the distance tolerance?
2038 * This will not return true if the point is on the RPP.
2039 */
2040#define V3PNT_OUT_RPP_TOL(_pt, _lo, _hi, _t) (\
2041 (_pt)[X] < (_lo)[X]-(_t) || (_pt)[X] > (_hi)[X]+(_t) || \
2042 (_pt)[Y] < (_lo)[Y]-(_t) || (_pt)[Y] > (_hi)[Y]+(_t) || \
2043 (_pt)[Z] < (_lo)[Z]-(_t) || (_pt)[Z] > (_hi)[Z]+(_t))
2044
2045/**
2046 * @brief Determine if one bounding box is within another. Also
2047 * returns true if the boxes are the same.
2048 *
2049 * FIXME: should not be using >= <=, '=' case is unreliable
2050 */
2051#define V3RPP1_IN_RPP2(_lo1, _hi1, _lo2, _hi2) (\
2052 (_lo1)[X] >= (_lo2)[X] && (_hi1)[X] <= (_hi2)[X] && \
2053 (_lo1)[Y] >= (_lo2)[Y] && (_hi1)[Y] <= (_hi2)[Y] && \
2054 (_lo1)[Z] >= (_lo2)[Z] && (_hi1)[Z] <= (_hi2)[Z])
2055
2056/** Convert an azimuth/elevation to a direction vector. */
2057#define V3DIR_FROM_AZEL(_d, _a, _e) do { \
2058 fastf_t _c_e = cos(_e); \
2059 (_d)[X] = cos(_a) * _c_e; \
2060 (_d)[Y] = sin(_a) * _c_e; \
2061 (_d)[Z] = sin(_e); \
2062 } while (0)
2063
2064/** Convert a direction vector to azimuth/elevation (in radians). */
2065#define AZEL_FROM_V3DIR(_a, _e, _d) do { \
2066 (_a) = ((NEAR_ZERO((_d)[X], SMALL_FASTF)) && (NEAR_ZERO((_d)[Y], SMALL_FASTF))) ? 0.0 : atan2(-((_d)[Y]), -((_d)[X])) * -RAD2DEG; \
2067 (_e) = atan2(-((_d)[Z]), sqrt((_d)[X]*(_d)[X] + (_d)[Y]*(_d)[Y])) * -RAD2DEG; \
2068 } while (0)
2069
2070
2071/** Swap two 3D vectors */
2072#define VSWAP(_a, _b) do { \
2073 fastf_t _t; \
2074 _t = (_a)[X]; \
2075 (_a)[X] = (_b)[X]; \
2076 (_b)[X] = _t; \
2077 _t = (_a)[Y]; \
2078 (_a)[Y] = (_b)[Y]; \
2079 (_b)[Y] = _t; \
2080 _t = (_a)[Z]; \
2081 (_a)[Z] = (_b)[Z]; \
2082 (_b)[Z] = _t; \
2083 } while (0)
2084
2085/** Swap two 2D vectors */
2086#define V2SWAP(_a, _b) do { \
2087 fastf_t _t; \
2088 _t = (_a)[X]; \
2089 (_a)[X] = (_b)[X]; \
2090 (_b)[X] = _t; \
2091 _t = (_a)[Y]; \
2092 (_a)[Y] = (_b)[Y]; \
2093 (_b)[Y] = _t; \
2094 } while (0)
2095
2096/** Swap two 4D vectors */
2097#define HSWAP(_a, _b) do { \
2098 fastf_t _t; \
2099 _t = (_a)[X]; \
2100 (_a)[X] = (_b)[X]; \
2101 (_b)[X] = _t; \
2102 _t = (_a)[Y]; \
2103 (_a)[Y] = (_b)[Y]; \
2104 (_b)[Y] = _t; \
2105 _t = (_a)[Z]; \
2106 (_a)[Z] = (_b)[Z]; \
2107 (_b)[Z] = _t; \
2108 _t = (_a)[W]; \
2109 (_a)[W] = (_b)[W]; \
2110 (_b)[W] = _t; \
2111 } while (0)
2112
2113/** Swap two 4x4 matrices */
2114#define MAT_SWAP(_a, _b) do { \
2115 mat_t _t; \
2116 MAT_COPY(_t, (_a)); \
2117 MAT_COPY((_a), (_b)); \
2118 MAT_COPY((_b), _t); \
2119 } while (0)
2120
2121/*** Macros suitable for declaration statement initialization. ***/
2122
2123/**
2124 * 3D vector macro suitable for declaration statement initialization.
2125 * this sets all vector elements to the specified value similar to
2126 * VSETALL() but as an initializer array declaration instead of as a
2127 * statement.
2128 */
2129#define VINITALL(_v) {(_v), (_v), (_v)}
2130
2131/**
2132 * 2D vector macro suitable for declaration statement initialization.
2133 * this sets all vector elements to the specified value similar to
2134 * VSETALLN(hvect_t,val,2) but as an initializer array declaration
2135 * instead of as a statement.
2136 */
2137#define V2INITALL(_v) {(_v), (_v), (_v)}
2138
2139/**
2140 * 4D homogeneous vector macro suitable for declaration statement
2141 * initialization. this sets all vector elements to the specified
2142 * value similar to VSETALLN(hvect_t,val,4) but as an initializer
2143 * array declaration instead of as a statement.
2144 */
2145#define HINITALL(_v) {(_v), (_v), (_v), (_v)}
2146
2147/**
2148 * 3D vector macro suitable for declaration statement initialization.
2149 * this sets all vector elements to zero similar to calling
2150 * VSETALL(0.0) but as an initializer array declaration instead of as
2151 * a statement.
2152 */
2153#define VINIT_ZERO {0.0, 0.0, 0.0}
2154
2155/**
2156 * 2D vector macro suitable for declaration statement initialization.
2157 * this sets all vector elements to zero similar to calling
2158 * V2SETALL(0.0) but as an initializer array declaration instead of as
2159 * a statement.
2160 */
2161#define V2INIT_ZERO {0.0, 0.0}
2162
2163/**
2164 * 4D homogeneous vector macro suitable for declaration statement
2165 * initialization. this sets all vector elements to zero similar to
2166 * calling VSETALLN(hvect_t,0.0,4) but as an initializer array
2167 * declaration instead of as a statement.
2168 */
2169#define HINIT_ZERO {0.0, 0.0, 0.0, 0.0}
2170
2171/**
2172 * matrix macro suitable for declaration statement initialization.
2173 * this sets up an identity matrix similar to calling MAT_IDN but as
2174 * an initializer array declaration instead of as a statement.
2175 */
2176#define MAT_INIT_IDN {1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0}
2177
2178/**
2179 * matrix macro suitable for declaration statement initialization.
2180 * this sets up a zero matrix similar to calling MAT_ZERO but as an
2181 * initializer array declaration instead of as a statement.
2182 */
2183#define MAT_INIT_ZERO {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}
2184
2185
2186#ifdef __cplusplus
2187} /* end extern "C" */
2188#endif
2189
2190#endif /* VMATH_H */
2191
2192/** @} */
2193/*
2194 * Local Variables:
2195 * mode: C
2196 * tab-width: 8
2197 * indent-tabs-mode: t
2198 * c-file-style: "stroustrup"
2199 * End:
2200 * ex: shiftwidth=4 tabstop=8
2201 */
Header file for the BRL-CAD common definitions.
fastf_t * pointp_t
pointer to a 3-tuple point
Definition: vmath.h:354
fastf_t vect_t[ELEMENTS_PER_VECT]
3-tuple vector
Definition: vmath.h:345
fastf_t * point2dp_t
pointer to a 2-tuple point
Definition: vmath.h:342
double fastf_t
fastest 64-bit (or larger) floating point type
Definition: vmath.h:330
#define ELEMENTS_PER_POINT
number of fastf_t's per point_t
Definition: vmath.h:310
fastf_t mat_t[ELEMENTS_PER_MAT]
4x4 matrix
Definition: vmath.h:366
fastf_t hvect_t[ELEMENTS_PER_HVECT]
4-tuple vector
Definition: vmath.h:357
enum vmath_matrix_component_ vmath_matrix_component
#define ELEMENTS_PER_PLANE
number of fastf_t's per plane_t
Definition: vmath.h:319
fastf_t point2d_t[ELEMENTS_PER_POINT2D]
2-tuple point
Definition: vmath.h:339
#define ELEMENTS_PER_HVECT
number of fastf_t's per hvect_t (homogeneous vector)
Definition: vmath.h:313
fastf_t * vect2dp_t
pointer to a 2-tuple vector
Definition: vmath.h:336
#define ELEMENTS_PER_POINT2D
number of fastf_t's per point2d_t
Definition: vmath.h:304
#define ELEMENTS_PER_VECT2D
number of fastf_t's per vect2d_t
Definition: vmath.h:301
fastf_t hpoint_t[ELEMENTS_PER_HPOINT]
4-tuple point
Definition: vmath.h:363
fastf_t plane_t[ELEMENTS_PER_PLANE]
Definition of a plane equation.
Definition: vmath.h:393
vmath_vector_component_
Definition: vmath.h:396
fastf_t * matp_t
pointer to a 4x4 matrix
Definition: vmath.h:369
#define ELEMENTS_PER_HPOINT
number of fastf_t's per hpt_t (homogeneous point)
Definition: vmath.h:316
fastf_t point_t[ELEMENTS_PER_POINT]
3-tuple point
Definition: vmath.h:351
#define ELEMENTS_PER_VECT
number of fastf_t's per vect_t
Definition: vmath.h:307
hvect_t quat_t
4-element quaternion
Definition: vmath.h:360
fastf_t * vectp_t
pointer to a 3-tuple vector
Definition: vmath.h:348
#define ELEMENTS_PER_MAT
number of fastf_t's per mat_t
Definition: vmath.h:322
fastf_t vect2d_t[ELEMENTS_PER_VECT2D]
2-tuple vector
Definition: vmath.h:333
enum vmath_vector_component_ vmath_vector_component
vmath_matrix_component_
Definition: vmath.h:408
@ H
Definition: vmath.h:401
@ Y
Definition: vmath.h:398
@ X
Definition: vmath.h:397
@ Z
Definition: vmath.h:399
@ W
Definition: vmath.h:400
@ MSA
Definition: vmath.h:415
@ MDZ
Definition: vmath.h:414
@ MSX
Definition: vmath.h:409
@ MDX
Definition: vmath.h:410
@ MDY
Definition: vmath.h:412
@ MSZ
Definition: vmath.h:413
@ MSY
Definition: vmath.h:411