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