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 quat_t */
321#define ELEMENTS_PER_QUAT 4
323/** @brief number of fastf_t's per mat_t */
324#define ELEMENTS_PER_MAT (ELEMENTS_PER_PLANE*ELEMENTS_PER_PLANE)
326
327/*
328 * Fundamental types
329 */
330
331/** @brief fastest 64-bit (or larger) floating point type */
332typedef double fastf_t;
333
334/** @brief 2-tuple vector */
337/** @brief pointer to a 2-tuple vector */
338typedef fastf_t *vect2dp_t;
340/** @brief 2-tuple point */
343/** @brief pointer to a 2-tuple point */
344typedef fastf_t *point2dp_t;
346/** @brief 3-tuple vector */
349/** @brief pointer to a 3-tuple vector */
350typedef fastf_t *vectp_t;
352/** @brief 3-tuple point */
355/** @brief pointer to a 3-tuple point */
356typedef fastf_t *pointp_t;
358/** @brief 4-tuple vector */
361/** @brief 4-element quaternion */
362typedef hvect_t quat_t;
364/** @brief 4-tuple point */
367/** @brief 4x4 matrix */
370/** @brief pointer to a 4x4 matrix */
371typedef fastf_t *matp_t;
373/**
374 * @brief Definition of a plane equation
376 * A plane is defined by a unit-length outward pointing normal vector
377 * (N), and the perpendicular (shortest) distance from the origin to
378 * the plane (in element N[W]).
379 *
380 * The plane consists of all points P=(x, y, z) such that
381 *@n VDOT(P, N) - N[W] == 0
382 *@n that is,
383 *@n N[X]*x + N[Y]*y + N[Z]*z - N[W] == 0
384 *
385 * The inside of the halfspace bounded by the plane
386 * consists of all points P such that
387 *@n VDOT(P, N) - N[W] <= 0
388 *
389 * A ray with direction D is classified w.r.t. the plane by
390 *
391 *@n VDOT(D, N) < 0 ray enters halfspace defined by plane
392 *@n VDOT(D, N) == 0 ray is parallel to plane
393 *@n VDOT(D, N) > 0 ray exits halfspace defined by plane
394 */
396
397/** Vector component names for homogeneous (4-tuple) vectors */
398typedef enum vmath_vector_component_ {
399 X = 0,
400 Y = 1,
401 Z = 2,
402 W = 3,
403 H = W
406/**
407 * Locations of deltas (MD*) and scaling values (MS*) in a 4x4
408 * Homogeneous Transform matrix
409 */
410typedef enum vmath_matrix_component_ {
411 MSX = 0,
412 MDX = 3,
413 MSY = 5,
414 MDY = 7,
415 MSZ = 10,
416 MDZ = 11,
417 MSA = 15
420/**
421 * Evaluates truthfully whether a number is not within valid range of
422 * INFINITY to -INFINITY exclusive (open set).
423 */
424#define INVALID(n) (!((n) > -INFINITY && (n) < INFINITY))
425
426/**
427 * Evaluates truthfully whether any components of a vector are not
428 * within a valid range.
429 */
430#define VINVALID(v) (INVALID((v)[X]) || INVALID((v)[Y]) || INVALID((v)[Z]))
431
432/**
433 * Evaluates truthfully whether any components of a 2D vector are not
434 * within a valid range.
435 */
436#define V2INVALID(v) (INVALID((v)[X]) || INVALID((v)[Y]))
437
438/**
439 * Evaluates truthfully whether any components of a 4D vector are not
440 * within a valid range.
441 */
442#define HINVALID(v) (INVALID((v)[X]) || INVALID((v)[Y]) || INVALID((v)[Z]) || INVALID((v)[W]))
443
444/**
445 * Return truthfully whether a value is within a specified epsilon
446 * distance from zero.
447 */
448#ifdef KEITH_WANTS_THIS
449/* this is a proposed change to equality/zero testing. prior behavior
450 * evaluated as an open set. this would change the behavior to that
451 * of a closed set so that you can perform exact comparisons against
452 * the tolerance and get a match. examples that fail with the current
453 * macro: tol=0.1; 1.1 == 1.0 or tol=0; 1==1
454 *
455 * these need to be tested carefully to make sure we pass ALL
456 * regression and integration tests, which will require some
457 * concerted effort to coordinate prior to a release. first step is
458 * to evaluate impact on performance and behavior of our tests.
459 */
460# define NEAR_ZERO(val, epsilon) (!(((val) < -(epsilon)) || ((val) > (epsilon))))
461# define NEAR_ZERO(val, epsilon) (!(((val) < -(epsilon))) && !(((val) > (epsilon))))
462#else
463# define NEAR_ZERO(val, epsilon) (((val) > -(epsilon)) && ((val) < (epsilon)))
464#endif
465
466/**
467 * Return truthfully whether all elements of a given vector are within
468 * a specified epsilon distance from zero.
469 */
470#define VNEAR_ZERO(v, tol) \
471 (NEAR_ZERO(v[X], (tol)) \
472 && NEAR_ZERO(v[Y], (tol)) \
473 && NEAR_ZERO(v[Z], (tol)))
475/**
476 * Test for all elements of `v' being smaller than `tol'.
477 * Version for degree 2 vectors.
478 */
479#define V2NEAR_ZERO(v, tol) (NEAR_ZERO(v[X], tol) && NEAR_ZERO(v[Y], tol))
480
481/**
482 * Test for all elements of `v' being smaller than `tol'.
483 * Version for homogeneous 4D vectors.
484 */
485#define HNEAR_ZERO(v, tol) \
486 (NEAR_ZERO(v[X], (tol)) \
487 && NEAR_ZERO(v[Y], (tol)) \
488 && NEAR_ZERO(v[Z], (tol)) \
489 && NEAR_ZERO(v[W], (tol)))
490
491
492/**
493 * Return truthfully whether a value is within a minimum
494 * representation tolerance from zero.
495 */
496#define ZERO(_a) NEAR_ZERO((_a), SMALL_FASTF)
497
498/**
499 * Return truthfully whether a vector is within a minimum
500 * representation tolerance from zero.
501 */
502#define VZERO(_a) VNEAR_ZERO((_a), SMALL_FASTF)
503
504/**
505 * Return truthfully whether a 2d vector is within a minimum
506 * representation tolerance from zero.
507 */
508#define V2ZERO(_a) V2NEAR_ZERO((_a), SMALL_FASTF)
509
510/**
511 * Return truthfully whether a homogenized 4-element vector is within
512 * a minimum representation tolerance from zero.
513 */
514#define HZERO(_a) HNEAR_ZERO((_a), SMALL_FASTF)
515
516
517/**
518 * Return truthfully whether two values are within a specified epsilon
519 * distance from each other.
520 */
521#define NEAR_EQUAL(_a, _b, _tol) NEAR_ZERO((_a) - (_b), (_tol))
522
523/**
524 * Return truthfully whether two 3D vectors are approximately equal,
525 * within a specified absolute tolerance.
526 */
527#define VNEAR_EQUAL(_a, _b, _tol) \
528 (NEAR_EQUAL((_a)[X], (_b)[X], (_tol)) \
529 && NEAR_EQUAL((_a)[Y], (_b)[Y], (_tol)) \
530 && NEAR_EQUAL((_a)[Z], (_b)[Z], (_tol)))
532/**
533 * Return truthfully whether two 2D vectors are approximately equal,
534 * within a specified absolute tolerance.
535 */
536#define V2NEAR_EQUAL(a, b, tol) \
537 (NEAR_EQUAL((a)[X], (b)[X], tol) \
538 && NEAR_EQUAL((a)[Y], (b)[Y], tol))
539
540/**
541 * Return truthfully whether two 4D vectors are approximately equal,
542 * within a specified absolute tolerance.
543 */
544#define HNEAR_EQUAL(_a, _b, _tol) \
545 (NEAR_EQUAL((_a)[X], (_b)[X], (_tol)) \
546 && NEAR_EQUAL((_a)[Y], (_b)[Y], (_tol)) \
547 && NEAR_EQUAL((_a)[Z], (_b)[Z], (_tol)) \
548 && NEAR_EQUAL((_a)[W], (_b)[W], (_tol)))
549
550/**
551 * Return truthfully whether two values are within a minimum
552 * representation tolerance from each other.
553 */
554#define EQUAL(_a, _b) NEAR_EQUAL((_a), (_b), SMALL_FASTF)
555
556
557/**
558 * Return truthfully whether two vectors are equal within a minimum
559 * representation tolerance.
560 */
561#define VEQUAL(_a, _b) VNEAR_EQUAL((_a), (_b), SMALL_FASTF)
562
563/**
564 * @brief Return truthfully whether two 2D vectors are equal within
565 * a minimum representation tolerance.
566 */
567#define V2EQUAL(_a, _b) V2NEAR_EQUAL((_a), (_b), SMALL_FASTF)
568
569/**
570 * @brief Return truthfully whether two higher degree vectors are
571 * equal within a minimum representation tolerance.
572 */
573#define HEQUAL(_a, _b) HNEAR_EQUAL((_a), (_b), SMALL_FASTF)
574
575
576/** @brief Compute distance from a point to a plane. */
577#define DIST_PNT_PLANE(_pt, _pl) (VDOT(_pt, _pl) - (_pl)[W])
578
579/** @brief Compute squared distance between two 3D points. */
580#define DIST_PNT_PNT_SQ(_a, _b) \
581 (((_a)[X]-(_b)[X])*((_a)[X]-(_b)[X]) + \
582 ((_a)[Y]-(_b)[Y])*((_a)[Y]-(_b)[Y]) + \
583 ((_a)[Z]-(_b)[Z])*((_a)[Z]-(_b)[Z]))
585/** @brief Compute distance between two 3D points. */
586#define DIST_PNT_PNT(_a, _b) sqrt(DIST_PNT_PNT_SQ(_a, _b))
587
588/** @brief Compute squared distance between two 2D points. */
589#define DIST_PNT2_PNT2_SQ(_a, _b) \
590 (((_a)[X]-(_b)[X])*((_a)[X]-(_b)[X]) + \
591 ((_a)[Y]-(_b)[Y])*((_a)[Y]-(_b)[Y]))
592
593/** @brief Compute distance between two 2D poitns. */
594#define DIST_PNT2_PNT2(_a, _b) sqrt(DIST_PNT2_PNT2_SQ(_a, _b))
595
596
597/** @brief set translation values of 4x4 matrix with x, y, z values. */
598#define MAT_DELTAS(_m, _x, _y, _z) do { \
599 (_m)[MDX] = (_x); \
600 (_m)[MDY] = (_y); \
601 (_m)[MDZ] = (_z); \
602 } while (0)
603
604/** @brief set translation values of 4x4 matrix from a vector. */
605#define MAT_DELTAS_VEC(_m, _v) \
606 MAT_DELTAS(_m, (_v)[X], (_v)[Y], (_v)[Z])
607
608/**
609 * @brief set translation values of 4x4 matrix from a reversed
610 * vector.
611 */
612#define MAT_DELTAS_VEC_NEG(_m, _v) \
613 MAT_DELTAS(_m, -(_v)[X], -(_v)[Y], -(_v)[Z])
614
615/** @brief get translation values of 4x4 matrix to a vector. */
616#define MAT_DELTAS_GET(_v, _m) do { \
617 (_v)[X] = (_m)[MDX]; \
618 (_v)[Y] = (_m)[MDY]; \
619 (_v)[Z] = (_m)[MDZ]; \
620 } while (0)
621
622/**
623 * @brief get translation values of 4x4 matrix to a vector,
624 * reversed.
625 */
626#define MAT_DELTAS_GET_NEG(_v, _m) do { \
627 (_v)[X] = -(_m)[MDX]; \
628 (_v)[Y] = -(_m)[MDY]; \
629 (_v)[Z] = -(_m)[MDZ]; \
630 } while (0)
631
632/**
633 * @brief increment translation elements in a 4x4 matrix with x, y, z
634 * values.
635 */
636#define MAT_DELTAS_ADD(_m, _x, _y, _z) do { \
637 (_m)[MDX] += (_x); \
638 (_m)[MDY] += (_y); \
639 (_m)[MDZ] += (_z); \
640 } while (0)
641
642/**
643 * @brief increment translation elements in a 4x4 matrix from a
644 * vector.
645 */
646#define MAT_DELTAS_ADD_VEC(_m, _v) do { \
647 (_m)[MDX] += (_v)[X]; \
648 (_m)[MDY] += (_v)[Y]; \
649 (_m)[MDZ] += (_v)[Z]; \
650 } while (0)
651
652/**
653 * @brief decrement translation elements in a 4x4 matrix with x, y, z
654 * values.
655 */
656#define MAT_DELTAS_SUB(_m, _x, _y, _z) do { \
657 (_m)[MDX] -= (_x); \
658 (_m)[MDY] -= (_y); \
659 (_m)[MDZ] -= (_z); \
660 } while (0)
661
662/**
663 * @brief decrement translation elements in a 4x4 matrix from a
664 * vector.
665 */
666#define MAT_DELTAS_SUB_VEC(_m, _v) do { \
667 (_m)[MDX] -= (_v)[X]; \
668 (_m)[MDY] -= (_v)[Y]; \
669 (_m)[MDZ] -= (_v)[Z]; \
670 } while (0)
671
672/**
673 * @brief decrement translation elements in a 4x4 matrix with x, y, z
674 * values.
675 */
676#define MAT_DELTAS_MUL(_m, _x, _y, _z) do { \
677 (_m)[MDX] *= (_x); \
678 (_m)[MDY] *= (_y); \
679 (_m)[MDZ] *= (_z); \
680 } while (0)
681
682/**
683 * @brief decrement translation elements in a 4x4 matrix from a
684 * vector.
685 */
686#define MAT_DELTAS_MUL_VEC(_m, _v) do { \
687 (_m)[MDX] *= (_v)[X]; \
688 (_m)[MDY] *= (_v)[Y]; \
689 (_m)[MDZ] *= (_v)[Z]; \
690 } while (0)
691
692/** @brief set scale of 4x4 matrix from xyz. */
693#define MAT_SCALE(_m, _x, _y, _z) do { \
694 (_m)[MSX] = _x; \
695 (_m)[MSY] = _y; \
696 (_m)[MSZ] = _z; \
697 } while (0)
698
699/** @brief set scale of 4x4 matrix from vector. */
700#define MAT_SCALE_VEC(_m, _v) do { \
701 (_m)[MSX] = (_v)[X]; \
702 (_m)[MSY] = (_v)[Y]; \
703 (_m)[MSZ] = (_v)[Z]; \
704 } while (0)
705
706/** @brief set uniform scale of 4x4 matrix from scalar. */
707#define MAT_SCALE_ALL(_m, _s) (_m)[MSA] = (_s)
708
709/** @brief add to scaling elements in a 4x4 matrix from xyz. */
710#define MAT_SCALE_ADD(_m, _x, _y, _z) do { \
711 (_m)[MSX] += _x; \
712 (_m)[MSY] += _y; \
713 (_m)[MSZ] += _z; \
714 } while (0)
715
716/** @brief add to scaling elements in a 4x4 matrix from vector. */
717#define MAT_SCALE_ADD_VEC(_m, _v) do { \
718 (_m)[MSX] += (_v)[X]; \
719 (_m)[MSY] += (_v)[Y]; \
720 (_m)[MSZ] += (_v)[Z]; \
721 } while (0)
722
723/** @brief subtract from scaling elements in a 4x4 matrix from xyz. */
724#define MAT_SCALE_SUB(_m, _x, _y, _z) do { \
725 (_m)[MSX] -= _x; \
726 (_m)[MSY] -= _y; \
727 (_m)[MSZ] -= _z; \
728 } while (0)
729
730/**
731 * @brief subtract from scaling elements in a 4x4 matrix from
732 * vector.
733 */
734#define MAT_SCALE_SUB_VEC(_m, _v) do { \
735 (_m)[MSX] -= (_v)[X]; \
736 (_m)[MSY] -= (_v)[Y]; \
737 (_m)[MSZ] -= (_v)[Z]; \
738 } while (0)
739
740/** @brief multiply scaling elements in a 4x4 matrix from xyz. */
741#define MAT_SCALE_MUL(_m, _x, _y, _z) do { \
742 (_m)[MSX] *= _x; \
743 (_m)[MSY] *= _y; \
744 (_m)[MSZ] *= _z; \
745 } while (0)
746
747/** @brief multiply scaling elements in a 4x4 matrix from vector. */
748#define MAT_SCALE_MUL_VEC(_m, _v) do { \
749 (_m)[MSX] *= (_v)[X]; \
750 (_m)[MSY] *= (_v)[Y]; \
751 (_m)[MSZ] *= (_v)[Z]; \
752 } while (0)
753
754
755/**
756 * In following are macro versions of librt/mat.c functions for when
757 * speed really matters.
758 */
759
760
761/** @brief Zero a matrix. */
762#define MAT_ZERO(m) do { \
763 (m)[0] = (m)[1] = (m)[2] = (m)[3] = \
764 (m)[4] = (m)[5] = (m)[6] = (m)[7] = \
765 (m)[8] = (m)[9] = (m)[10] = (m)[11] = \
766 (m)[12] = (m)[13] = (m)[14] = (m)[15] = 0.0; \
767 } while (0)
768
769/** @brief Set matrix to identity. */
770#define MAT_IDN(m) do { \
771 (m)[1] = (m)[2] = (m)[3] = (m)[4] = \
772 (m)[6] = (m)[7] = (m)[8] = (m)[9] = \
773 (m)[11] = (m)[12] = (m)[13] = (m)[14] = 0.0; \
774 (m)[0] = (m)[5] = (m)[10] = (m)[15] = 1.0; \
775 } while (0)
776
777/**
778 * @brief set t to the transpose of matrix m
779 *
780 * NOTE: This implementation will not transpose in-place or
781 * overlapping matrices (e.g., MAT_TRANSPOSE(m, m) will be wrong).
782 */
783#define MAT_TRANSPOSE(t, m) do { \
784 (t)[0] = (m)[0]; \
785 (t)[4] = (m)[1]; \
786 (t)[8] = (m)[2]; \
787 (t)[12] = (m)[3]; \
788 (t)[1] = (m)[4]; \
789 (t)[5] = (m)[5]; \
790 (t)[9] = (m)[6]; \
791 (t)[13] = (m)[7]; \
792 (t)[2] = (m)[8]; \
793 (t)[6] = (m)[9]; \
794 (t)[10] = (m)[10]; \
795 (t)[14] = (m)[11]; \
796 (t)[3] = (m)[12]; \
797 (t)[7] = (m)[13]; \
798 (t)[11] = (m)[14]; \
799 (t)[15] = (m)[15]; \
800 } while (0)
801
802/** @brief Copy a matrix `m' into `c'. */
803#define MAT_COPY(c, m) do { \
804 (c)[0] = (m)[0]; \
805 (c)[1] = (m)[1]; \
806 (c)[2] = (m)[2]; \
807 (c)[3] = (m)[3]; \
808 (c)[4] = (m)[4]; \
809 (c)[5] = (m)[5]; \
810 (c)[6] = (m)[6]; \
811 (c)[7] = (m)[7]; \
812 (c)[8] = (m)[8]; \
813 (c)[9] = (m)[9]; \
814 (c)[10] = (m)[10]; \
815 (c)[11] = (m)[11]; \
816 (c)[12] = (m)[12]; \
817 (c)[13] = (m)[13]; \
818 (c)[14] = (m)[14]; \
819 (c)[15] = (m)[15]; \
820 } while (0)
821
822/** @brief Set 3D vector at `o' to have coordinates `a', `b', and `c'. */
823#define VSET(o, a, b, c) do { \
824 (o)[X] = (a); \
825 (o)[Y] = (b); \
826 (o)[Z] = (c); \
827 } while (0)
828
829/** @brief Set 2D vector at `o' to have coordinates `a' and `b'. */
830#define V2SET(o, a, b) do { \
831 (o)[X] = (a); \
832 (o)[Y] = (b); \
833 } while (0)
835/** @brief Set 4D vector at `o' to homogeneous coordinates `a', `b', `c', and `d'. */
836#define HSET(o, a, b, c, d) do { \
837 (o)[X] = (a); \
838 (o)[Y] = (b); \
839 (o)[Z] = (c); \
840 (o)[W] = (d); \
841 } while (0)
842
843
844/** @brief Set all elements of 3D vector to same scalar value. */
845#define VSETALL(v, s) do { \
846 (v)[X] = (v)[Y] = (v)[Z] = (s); \
847 } while (0)
848
849/** @brief Set 2D vector elements to same scalar value. */
850#define V2SETALL(v, s) do { \
851 (v)[X] = (v)[Y] = (s); \
852 } while (0)
853
854/** @brief Set 4D vector elements to same scalar value. */
855#define HSETALL(v, s) do { \
856 (v)[X] = (v)[Y] = (v)[Z] = (v)[W] = (s); \
857 } while (0)
858
860/** @brief Set all elements of N-vector to same scalar value. */
861#define VSETALLN(v, s, n) do { \
862 int _j; \
863 for (_j=0; _j < (int)(n); _j++) v[_j]=(s); \
864 } while (0)
866
867/** @brief Transfer 3D vector at `v' to vector at `o'. */
868#define VMOVE(o, v) do { \
869 (o)[X] = (v)[X]; \
870 (o)[Y] = (v)[Y]; \
871 (o)[Z] = (v)[Z]; \
872 } while (0)
873
874/** @brief Move a 2D vector at `v' to vector at `o'. */
875#define V2MOVE(o, v) do { \
876 (o)[X] = (v)[X]; \
877 (o)[Y] = (v)[Y]; \
878 } while (0)
880/** @brief Move a homogeneous 4-tuple at `v' to `o'. */
881#define HMOVE(o, v) do { \
882 (o)[X] = (v)[X]; \
883 (o)[Y] = (v)[Y]; \
884 (o)[Z] = (v)[Z]; \
885 (o)[W] = (v)[W]; \
886 } while (0)
887
888/** @brief Transfer vector of length `n' at `v' to vector at `o'. */
889#define VMOVEN(o, v, n) do { \
890 int _vmove; \
891 for (_vmove = 0; _vmove < (int)(n); _vmove++) { \
892 (o)[_vmove] = (v)[_vmove]; \
893 } \
894 } while (0)
895
896
897/**
898 * @brief Reverse the direction of 3D vector `v' and store it in `o'.
899 *
900 * NOTE: Reversing in place works (i.e., VREVERSE(v, v))
901 */
902#define VREVERSE(o, v) do { \
903 (o)[X] = -(v)[X]; \
904 (o)[Y] = -(v)[Y]; \
905 (o)[Z] = -(v)[Z]; \
906 } while (0)
907
908/**
909 * @brief Reverse the direction of 2D vector `v' and store it in `o'.
910 *
911 * NOTE: Reversing in place works (i.e., V2REVERSE(v, v))
912 */
913#define V2REVERSE(o, v) do { \
914 (o)[X] = -(v)[X]; \
915 (o)[Y] = -(v)[Y]; \
916 } while (0)
918/**
919 * @brief Same as VREVERSE, but for a 4-tuple. Also useful on plane_t
920 * objects.
921 *
922 * NOTE: Reversing in place works (i.e., HREVERSE(v, v))
923 */
924#define HREVERSE(o, v) do { \
925 (o)[X] = -(v)[X]; \
926 (o)[Y] = -(v)[Y]; \
927 (o)[Z] = -(v)[Z]; \
928 (o)[W] = -(v)[W]; \
929 } while (0)
930
931/** @brief Add 3D vectors at `a' and `b', store result at `o'. */
932#define VADD2(o, a, b) do { \
933 (o)[X] = (a)[X] + (b)[X]; \
934 (o)[Y] = (a)[Y] + (b)[Y]; \
935 (o)[Z] = (a)[Z] + (b)[Z]; \
936 } while (0)
937
938/** @brief Add 2D vectors at `a' and `b', store result at `o'. */
939#define V2ADD2(o, a, b) do { \
940 (o)[X] = (a)[X] + (b)[X]; \
941 (o)[Y] = (a)[Y] + (b)[Y]; \
942 } while (0)
944/** @brief Add 4D vectors at `a' and `b', store result at `o'. */
945#define HADD2(o, a, b) do { \
946 (o)[X] = (a)[X] + (b)[X]; \
947 (o)[Y] = (a)[Y] + (b)[Y]; \
948 (o)[Z] = (a)[Z] + (b)[Z]; \
949 (o)[W] = (a)[W] + (b)[W]; \
950 } while (0)
951
952/**
953 * @brief Add vectors of length `n' at `a' and `b', store result at
954 * `o'.
955 */
956#define VADD2N(o, a, b, n) do { \
957 int _vadd2; \
958 for (_vadd2 = 0; _vadd2 < (int)(n); _vadd2++) { \
959 (o)[_vadd2] = (a)[_vadd2] + (b)[_vadd2]; \
960 } \
961 } while (0)
962
963
964/**
965 * @brief Subtract 3D vector at `b' from vector at `a', store result at
966 * `o'.
967 */
968#define VSUB2(o, a, b) do { \
969 (o)[X] = (a)[X] - (b)[X]; \
970 (o)[Y] = (a)[Y] - (b)[Y]; \
971 (o)[Z] = (a)[Z] - (b)[Z]; \
972 } while (0)
973
974/**
975 * @brief Subtract 2D vector at `b' from vector at `a', store result at
976 * `o'.
977 */
978#define V2SUB2(o, a, b) do { \
979 (o)[X] = (a)[X] - (b)[X]; \
980 (o)[Y] = (a)[Y] - (b)[Y]; \
981 } while (0)
983/**
984 * @brief Subtract 4D vector at `b' from vector at `a', store result at
985 * `o'.
986 */
987#define HSUB2(o, a, b) do { \
988 (o)[X] = (a)[X] - (b)[X]; \
989 (o)[Y] = (a)[Y] - (b)[Y]; \
990 (o)[Z] = (a)[Z] - (b)[Z]; \
991 (o)[W] = (a)[W] - (b)[W]; \
992 } while (0)
993
994/**
995 * @brief Subtract `n' length vector at `b' from `n' length vector at
996 * `a', store result at `o'.
997 */
998#define VSUB2N(o, a, b, n) do { \
999 int _vsub2; \
1000 for (_vsub2 = 0; _vsub2 < (int)(n); _vsub2++) { \
1001 (o)[_vsub2] = (a)[_vsub2] - (b)[_vsub2]; \
1002 } \
1003 } while (0)
1004
1005
1006/** @brief 3D Vectors: O = A - B - C */
1007#define VSUB3(o, a, b, c) do { \
1008 (o)[X] = (a)[X] - (b)[X] - (c)[X]; \
1009 (o)[Y] = (a)[Y] - (b)[Y] - (c)[Y]; \
1010 (o)[Z] = (a)[Z] - (b)[Z] - (c)[Z]; \
1011 } while (0)
1012
1013/** @brief 2D Vectors: O = A - B - C */
1014#define V2SUB3(o, a, b, c) do { \
1015 (o)[X] = (a)[X] - (b)[X] - (c)[X]; \
1016 (o)[Y] = (a)[Y] - (b)[Y] - (c)[Y]; \
1017 } while (0)
1019/** @brief 4D Vectors: O = A - B - C */
1020#define HSUB3(o, a, b, c) do { \
1021 (o)[X] = (a)[X] - (b)[X] - (c)[X]; \
1022 (o)[Y] = (a)[Y] - (b)[Y] - (c)[Y]; \
1023 (o)[Z] = (a)[Z] - (b)[Z] - (c)[Z]; \
1024 (o)[W] = (a)[W] - (b)[W] - (c)[W]; \
1025 } while (0)
1026
1027/** @brief Vectors: O = A - B - C for vectors of length `n'. */
1028#define VSUB3N(o, a, b, c, n) do { \
1029 int _vsub3; \
1030 for (_vsub3 = 0; _vsub3 < (int)(n); _vsub3++) { \
1031 (o)[_vsub3] = (a)[_vsub3] - (b)[_vsub3] - (c)[_vsub3]; \
1032 } \
1033 } while (0)
1034
1035
1036/** @brief Add 3 3D vectors at `a', `b', and `c', store result at `o'. */
1037#define VADD3(o, a, b, c) do { \
1038 (o)[X] = (a)[X] + (b)[X] + (c)[X]; \
1039 (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y]; \
1040 (o)[Z] = (a)[Z] + (b)[Z] + (c)[Z]; \
1041 } while (0)
1042
1043/** @brief Add 3 2D vectors at `a', `b', and `c', store result at `o'. */
1044#define V2ADD3(o, a, b, c) do { \
1045 (o)[X] = (a)[X] + (b)[X] + (c)[X]; \
1046 (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y]; \
1047 } while (0)
1049/** @brief Add 3 4D vectors at `a', `b', and `c', store result at `o'. */
1050#define HADD3(o, a, b, c) do { \
1051 (o)[X] = (a)[X] + (b)[X] + (c)[X]; \
1052 (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y]; \
1053 (o)[Z] = (a)[Z] + (b)[Z] + (c)[Z]; \
1054 (o)[W] = (a)[W] + (b)[W] + (c)[W]; \
1055 } while (0)
1056
1057/**
1058 * @brief Add 3 vectors of length `n' at `a', `b', and `c', store
1059 * result at `o'.
1060 */
1061#define VADD3N(o, a, b, c, n) do { \
1062 int _vadd3; \
1063 for (_vadd3 = 0; _vadd3 < (int)(n); _vadd3++) { \
1064 (o)[_vadd3] = (a)[_vadd3] + (b)[_vadd3] + (c)[_vadd3]; \
1065 } \
1066 } while (0)
1067
1068
1069/**
1070 * @brief Add 4 vectors at `a', `b', `c', and `d', store result at
1071 * `o'.
1072 */
1073#define VADD4(o, a, b, c, d) do { \
1074 (o)[X] = (a)[X] + (b)[X] + (c)[X] + (d)[X]; \
1075 (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y] + (d)[Y]; \
1076 (o)[Z] = (a)[Z] + (b)[Z] + (c)[Z] + (d)[Z]; \
1077 } while (0)
1078
1079/**
1080 * @brief Add 4 2D vectors at `a', `b', `c', and `d', store result at
1081 * `o'.
1082 */
1083#define V2ADD4(o, a, b, c, d) do { \
1084 (o)[X] = (a)[X] + (b)[X] + (c)[X] + (d)[X]; \
1085 (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y] + (d)[Y]; \
1086 } while (0)
1088/**
1089 * @brief Add 4 4D vectors at `a', `b', `c', and `d', store result at
1090 * `o'.
1091 */
1092#define HADD4(o, a, b, c, d) do { \
1093 (o)[X] = (a)[X] + (b)[X] + (c)[X] + (d)[X]; \
1094 (o)[Y] = (a)[Y] + (b)[Y] + (c)[Y] + (d)[Y]; \
1095 (o)[Z] = (a)[Z] + (b)[Z] + (c)[Z] + (d)[Z]; \
1096 (o)[W] = (a)[W] + (b)[W] + (c)[W] + (d)[W]; \
1097 } while (0)
1098
1099/**
1100 * @brief Add 4 `n' length vectors at `a', `b', `c', and `d', store
1101 * result at `o'.
1102 */
1103#define VADD4N(o, a, b, c, d, n) do { \
1104 int _vadd4; \
1105 for (_vadd4 = 0; _vadd4 < (int)(n); _vadd4++) { \
1106 (o)[_vadd4] = (a)[_vadd4] + (b)[_vadd4] + (c)[_vadd4] + (d)[_vadd4]; \
1107 } \
1108 } while (0)
1109
1110
1111/** @brief Scale 3D vector at `v' by scalar `s', store result at `o'. */
1112#define VSCALE(o, v, s) do { \
1113 (o)[X] = (v)[X] * (s); \
1114 (o)[Y] = (v)[Y] * (s); \
1115 (o)[Z] = (v)[Z] * (s); \
1116 } while (0)
1117
1118/** @brief Scale 2D vector at `v' by scalar `s', store result at `o'. */
1119#define V2SCALE(o, v, s) do { \
1120 (o)[X] = (v)[X] * (s); \
1121 (o)[Y] = (v)[Y] * (s); \
1122 } while (0)
1124/** @brief Scale 4D vector at `v' by scalar `s', store result at `o'. */
1125#define HSCALE(o, v, s) do { \
1126 (o)[X] = (v)[X] * (s); \
1127 (o)[Y] = (v)[Y] * (s); \
1128 (o)[Z] = (v)[Z] * (s); \
1129 (o)[W] = (v)[W] * (s); \
1130 } while (0)
1131
1132/**
1133 * @brief Scale vector of length `n' at `v' by scalar `s', store
1134 * result at `o'
1135 */
1136#define VSCALEN(o, v, s, n) do { \
1137 int _vscale; \
1138 for (_vscale = 0; _vscale < (int)(n); _vscale++) { \
1139 (o)[_vscale] = (v)[_vscale] * (s); \
1140 } \
1141 } while (0)
1142
1143/**
1144 * @brief Normalize vector `v' to be a unit vector.
1145 *
1146 * If input is near a zero-vector, we clamp to zero for stability.
1147 */
1148#define VUNITIZE(v) do { \
1149 double _f = MAGSQ(v); \
1150 if (! NEAR_EQUAL(_f, 1.0, VUNITIZE_TOL)) { \
1151 _f = sqrt(_f); \
1152 if (_f < VDIVIDE_TOL) { \
1153 VSETALL((v), 0.0); \
1154 } else { \
1155 _f = 1.0/_f; \
1156 (v)[X] *= _f; (v)[Y] *= _f; (v)[Z] *= _f; \
1157 } \
1158 } \
1159 } while (0)
1160
1161/**
1162 * @brief Normalize 2D vector `v' to be a unit vector.
1163 *
1164 * If input is near a zero-vector, we clamp to zero for stability.
1165 */
1166#define V2UNITIZE(v) do { \
1167 double _f = MAG2SQ(v); \
1168 if (! NEAR_EQUAL(_f, 1.0, VUNITIZE_TOL)) { \
1169 _f = sqrt(_f); \
1170 if (_f < VDIVIDE_TOL) { \
1171 V2SETALL((v), 0.0); \
1172 } else { \
1173 _f = 1.0/_f; \
1174 (v)[X] *= _f; (v)[Y] *= _f; \
1175 } \
1176 } \
1177 } while (0)
1178
1179/**
1180 * @brief Find the sum of two points, and scale the result. Often
1181 * used to find the midpoint.
1182 */
1183#define VADD2SCALE(o, a, b, s) do { \
1184 (o)[X] = ((a)[X] + (b)[X]) * (s); \
1185 (o)[Y] = ((a)[Y] + (b)[Y]) * (s); \
1186 (o)[Z] = ((a)[Z] + (b)[Z]) * (s); \
1187 } while (0)
1188
1189/**
1190 * @brief Find the sum of two vectors of length `n', and scale the
1191 * result by `s'. Often used to find the midpoint.
1192 */
1193#define VADD2SCALEN(o, a, b, s, n) do { \
1194 int _vadd2scale; \
1195 for (_vadd2scale = 0; \
1196 _vadd2scale < (int)(n); \
1197 _vadd2scale++) { \
1198 (o)[_vadd2scale] = ((a)[_vadd2scale] + (b)[_vadd2scale]) * (s); \
1199 } \
1200 } while (0)
1201
1202/**
1203 * @brief Find the difference between two points, and scale result.
1204 * Often used to compute bounding sphere radius given rpp points.
1205 */
1206#define VSUB2SCALE(o, a, b, s) do { \
1207 (o)[X] = ((a)[X] - (b)[X]) * (s); \
1208 (o)[Y] = ((a)[Y] - (b)[Y]) * (s); \
1209 (o)[Z] = ((a)[Z] - (b)[Z]) * (s); \
1210 } while (0)
1211
1212/**
1213 * @brief Find the difference between two vectors of length `n', and
1214 * scale result by `s'.
1215 */
1216#define VSUB2SCALEN(o, a, b, s, n) do { \
1217 int _vsub2scale; \
1218 for (_vsub2scale = 0; \
1219 _vsub2scale < (int)(n); \
1220 _vsub2scale++) { \
1221 (o)[_vsub2scale] = ((a)[_vsub2scale] - (b)[_vsub2scale]) * (s); \
1222 } \
1223 } while (0)
1224
1225/**
1226 * @brief Combine together 2 vectors, both scaled by scalars.
1227 */
1228#define VCOMB2(o, sa, va, sb, vb) do { \
1229 (o)[X] = (sa) * (va)[X] + (sb) * (vb)[X]; \
1230 (o)[Y] = (sa) * (va)[Y] + (sb) * (vb)[Y]; \
1231 (o)[Z] = (sa) * (va)[Z] + (sb) * (vb)[Z]; \
1232 } while (0)
1233
1234/**
1235 * @brief Combine together 2 vectors of length `n', both scaled by
1236 * scalars.
1237 */
1238#define VCOMB2N(o, sa, va, sb, vb, n) do { \
1239 int _vcomb2; \
1240 for (_vcomb2 = 0; \
1241 _vcomb2 < (int)(n); \
1242 _vcomb2++) { \
1243 (o)[_vcomb2] = (sa) * (va)[_vcomb2] + (sb) * (vb)[_vcomb2]; \
1244 } \
1245 } while (0)
1246
1247
1248/**
1249 * @brief Combine together 3 vectors, scaled by scalars.
1250 */
1251#define VCOMB3(o, sa, va, sb, vb, sc, vc) do { \
1252 (o)[X] = (sa) * (va)[X] + (sb) * (vb)[X] + (sc) * (vc)[X]; \
1253 (o)[Y] = (sa) * (va)[Y] + (sb) * (vb)[Y] + (sc) * (vc)[Y]; \
1254 (o)[Z] = (sa) * (va)[Z] + (sb) * (vb)[Z] + (sc) * (vc)[Z]; \
1255 } while (0)
1256
1257/**
1258 * @brief Combine together 3 vectors of length `n', both scaled by
1259 * scalars.
1260 */
1261#define VCOMB3N(o, sa, va, sb, vb, sc, vc, n) do { \
1262 int _vcomb3; \
1263 for (_vcomb3 = 0; \
1264 _vcomb3 < (int)(n); \
1265 _vcomb3++) { \
1266 (o)[_vcomb3] = (sa) * (va)[_vcomb3] + (sb) * (vb)[_vcomb3] + (sc) * (vc)[_vcomb3]; \
1267 } \
1268 } while (0)
1269
1270
1271/**
1272 * Compose 3D vector at `o' of:
1273 * vector at `va' plus
1274 * scalar `sb' times vector at `vb'
1275 *
1276 * This is basically a shorthand for VSCALE();VADD2();.
1277 */
1278#define VJOIN1(o, va, sb, vb) do { \
1279 (o)[X] = (va)[X] + (sb) * (vb)[X]; \
1280 (o)[Y] = (va)[Y] + (sb) * (vb)[Y]; \
1281 (o)[Z] = (va)[Z] + (sb) * (vb)[Z]; \
1282 } while (0)
1283
1284/**
1285 * Compose 2D vector at `o' of:
1286 * vector at `va' plus
1287 * scalar `sb' times vector at `vb'
1288 *
1289 * This is basically a shorthand for V2SCALE();V2ADD2();.
1290 */
1291#define V2JOIN1(o, va, sb, vb) do { \
1292 (o)[X] = (va)[X] + (sb) * (vb)[X]; \
1293 (o)[Y] = (va)[Y] + (sb) * (vb)[Y]; \
1294 } while (0)
1296/**
1297 * Compose 4D vector at `o' of:
1298 * vector at `a' plus
1299 * scalar `sb' times vector at `b'
1300 *
1301 * This is basically a shorthand for HSCALE();HADD2();.
1302 */
1303#define HJOIN1(o, va, sb, vb) do { \
1304 (o)[X] = (va)[X] + (sb) * (vb)[X]; \
1305 (o)[Y] = (va)[Y] + (sb) * (vb)[Y]; \
1306 (o)[Z] = (va)[Z] + (sb) * (vb)[Z]; \
1307 (o)[W] = (va)[W] + (sb) * (vb)[W]; \
1308 } while (0)
1309
1310/**
1311 * Compose `n'-D vector at `o' of:
1312 * vector at `va' plus
1313 * scalar `sb' times vector at `vb'
1314 *
1315 * This is basically a shorthand for VSCALEN();VADD2N();.
1316 */
1317#define VJOIN1N(o, va, sb, vb, n) do { \
1318 int _vjoin1; \
1319 for (_vjoin1 = 0; \
1320 _vjoin1 < (int)(n); \
1321 _vjoin1++) { \
1322 (o)[_vjoin1] = (va)[_vjoin1] + (sb) * (vb)[_vjoin1]; \
1323 } \
1324 } while (0)
1325
1326
1327/**
1328 * @brief Compose 3D vector at `o' of:
1329 * Vector at `va' plus
1330 * scalar `sb' times vector at `vb' plus
1331 * scalar `sc' times vector at `vc'
1332 */
1333#define VJOIN2(o, va, sb, vb, sc, vc) do { \
1334 (o)[X] = (va)[X] + (sb) * (vb)[X] + (sc) * (vc)[X]; \
1335 (o)[Y] = (va)[Y] + (sb) * (vb)[Y] + (sc) * (vc)[Y]; \
1336 (o)[Z] = (va)[Z] + (sb) * (vb)[Z] + (sc) * (vc)[Z]; \
1337 } while (0)
1338
1339/**
1340 * @brief Compose 2D vector at `o' of:
1341 * Vector at `va' plus
1342 * scalar `sb' times vector at `vb' plus
1343 * scalar `sc' times vector at `vc'
1344 */
1345#define V2JOIN2(o, va, sb, vb, sc, vc) do { \
1346 (o)[X] = (va)[X] + (sb) * (vb)[X] + (sc) * (vc)[X]; \
1347 (o)[Y] = (va)[Y] + (sb) * (vb)[Y] + (sc) * (vc)[Y]; \
1348 } while (0)
1350/**
1351 * @brief Compose 4D vector at `o' of:
1352 * Vector at `va' plus
1353 * scalar `sb' times vector at `vb' plus
1354 * scalar `sc' times vector at `vc'
1355 */
1356#define HJOIN2(o, a, sb, b, sc, c) do { \
1357 (o)[X] = (a)[X] + (sb) * (b)[X] + (sc) * (c)[X]; \
1358 (o)[Y] = (a)[Y] + (sb) * (b)[Y] + (sc) * (c)[Y]; \
1359 (o)[Z] = (a)[Z] + (sb) * (b)[Z] + (sc) * (c)[Z]; \
1360 (o)[W] = (a)[W] + (sb) * (b)[W] + (sc) * (c)[W]; \
1361 } while (0)
1362
1363#define VJOIN2N(o, va, sb, vb, sc, vc, n) do { \
1364 int _vjoin2; \
1365 for (_vjoin2 = 0; \
1366 _vjoin2 < (int)(n); \
1367 _vjoin2++) { \
1368 (o)[_vjoin2] = (va)[_vjoin2] + (sb) * (vb)[_vjoin2] + (sc) * (vc)[_vjoin2]; \
1369 } \
1370 } while (0)
1371
1372
1373/**
1374 * Join three scaled vectors to a base `a', storing the result in `o'.
1375 */
1376#define VJOIN3(o, va, sb, vb, sc, vc, sd, vd) do { \
1377 (o)[X] = (va)[X] + (sb)*(vb)[X] + (sc)*(vc)[X] + (sd)*(vd)[X]; \
1378 (o)[Y] = (va)[Y] + (sb)*(vb)[Y] + (sc)*(vc)[Y] + (sd)*(vd)[Y]; \
1379 (o)[Z] = (va)[Z] + (sb)*(vb)[Z] + (sc)*(vc)[Z] + (sd)*(vd)[Z]; \
1380 } while (0)
1381
1382
1383/**
1384 * @brief Blend into vector `o'
1385 * scalar `sa' times vector at `a' plus
1386 * scalar `sb' times vector at `b'
1387 */
1388#define VBLEND2(o, sa, va, sb, vb) do { \
1389 (o)[X] = (sa) * (va)[X] + (sb) * (vb)[X]; \
1390 (o)[Y] = (sa) * (va)[Y] + (sb) * (vb)[Y]; \
1391 (o)[Z] = (sa) * (va)[Z] + (sb) * (vb)[Z]; \
1392 } while (0)
1393
1394/**
1395 * @brief Blend into vector `o'
1396 * scalar `sa' times vector at `va' plus
1397 * scalar `sb' times vector at `vb'
1398 */
1399#define VBLEND2N(o, sa, va, sb, vb, n) do { \
1400 int _vblend2; \
1401 for (_vblend2 = 0; \
1402 _vblend2 < (int)(n); \
1403 _vblend2++) { \
1404 (o)[_vblend2] = (sa) * (va)[_vblend2] + (sb) * (vb)[_vblend2]; \
1405 } \
1406 } while (0)
1407
1408
1409/**
1410 * @brief Project vector `a' onto `b'
1411 * vector `c' is the component of `a' parallel to `b'
1412 * " `d' " " " " " orthogonal " "
1413 *
1414 * FIXME: consistency, the result should come first
1415 */
1416#define VPROJECT(a, b, c, d) do { \
1417 double _dot = VDOT((b), (b)); \
1418 if (NEAR_ZERO(_dot, SQRT_SMALL_FASTF)) { \
1419 VSCALE((c), (b), 0.0); \
1420 } else { \
1421 VSCALE((c), (b), VDOT((a), (b)) / _dot); \
1422 } \
1423 VSUB2((d), (a), (c)); \
1424 } while (0)
1425
1426/** @brief Return scalar magnitude squared of vector at `v' */
1427#define MAGSQ(v) ((v)[X]*(v)[X] + (v)[Y]*(v)[Y] + (v)[Z]*(v)[Z])
1428#define MAG2SQ(v) ((v)[X]*(v)[X] + (v)[Y]*(v)[Y])
1429
1430
1431/**
1432 * @brief Return scalar magnitude of the 3D vector `a'. This is
1433 * otherwise known as the Euclidean norm of the provided vector..
1434 */
1435#define MAGNITUDE(v) sqrt(MAGSQ(v))
1436
1437/**
1438 * @brief Return scalar magnitude of the 2D vector at `a'. This is
1439 * otherwise known as the Euclidean norm of the provided vector..
1441#define MAGNITUDE2(v) sqrt(MAG2SQ(v))
1442
1443/**
1444 * @brief Store cross product of 3D vectors at `a' and `b' in vector at `o'.
1445 *
1446 * NOTE: The "right hand rule" applies. If closing your right hand
1447 * goes from `a' to `b', then your thumb points in the direction of
1448 * the cross product.
1449 *
1450 * If the angle from `a' to `b' goes clockwise, then the result vector
1451 * points "into" the plane (inward normal). Example: a=(0, 1, 0),
1452 * b=(1, 0, 0), then aXb=(0, 0, -1).
1453 *
1454 * If the angle from `a' to `b' goes counter-clockwise, then the
1455 * result vector points "out" of the plane. This outward pointing
1456 * normal is the BRL-CAD convention.
1457 */
1458#define VCROSS(o, a, b) do { \
1459 (o)[X] = (a)[Y] * (b)[Z] - (a)[Z] * (b)[Y]; \
1460 (o)[Y] = (a)[Z] * (b)[X] - (a)[X] * (b)[Z]; \
1461 (o)[Z] = (a)[X] * (b)[Y] - (a)[Y] * (b)[X]; \
1462 } while (0)
1464/**
1465 * Return the analog of a cross product for 2D vectors `a' and `b'
1466 * as a scalar value. If a = (ax, ay) and b = (bx, by), then the analog
1467 * of a x b is det(a*b) = ax*by - ay*bx
1468 */
1469#define V2CROSS(a, b) ((a)[X] * (b)[Y] - (a)[Y] * (b)[X])
1470
1471/**
1472 * @brief Store the cross product of homogeneous 3D vectors at `a' and
1473 * `b' at `o'.
1475 * XYZ components contain cross product of the homogeneous numerators,
1476 * while W contains product of the input homogeneous coordinates:
1477 *
1478 * o[X,Y,Z] = a[X,Y,Z] x b[X,Y,Z]
1479 * o[W] = a[W] * b[W]
1480 *
1481 * Consequently, when a[W] and b[W] are non-zero, dividing out o[W]
1482 * produces the cross product of the dehomogenized inputs. Zero-input
1483 * W produces a zero-output W, representing a direction at infininty.
1484 *
1485 * Callers needing vect_t can use HDIVIDE().
1486 */
1487#define HCROSS(o, a, b) do { \
1488 VCROSS((o), (a), (b)); \
1489 (o)[W] = (a)[W] * (b)[W]; \
1490 } while (0)
1491
1493/** @brief Compute dot product of vectors at `a' and `b'. */
1494#define VDOT(a, b) ((a)[X]*(b)[X] + (a)[Y]*(b)[Y] + (a)[Z]*(b)[Z])
1495
1496#define V2DOT(a, b) ((a)[X]*(b)[X] + (a)[Y]*(b)[Y])
1497
1498#define HDOT(a, b) ((a)[X]*(b)[X] + (a)[Y]*(b)[Y] + (a)[Z]*(b)[Z] + (a)[W]*(b)[W])
1500
1502 * @brief Linearly interpolate between two 3D vectors `a' and `b' by
1503 * interpolant `t', expected in the range [0,1], with result in `o'.
1504 *
1505 * NOTE: We intentionally use the form "o = a*(1-t) + b*t" which is
1506 * mathematically equivalent to "o = a + (b-a)*t". The latter might
1507 * result in fewer math operations but cannot guarantee o==v1 when
1508 * t==1 due to floating-point arithmetic error.
1509 */
1510#define VLERP(o, a, b, t) do { \
1511 (o)[X] = (a)[X] * (1 - (t)) + (b)[X] * (t); \
1512 (o)[Y] = (a)[Y] * (1 - (t)) + (b)[Y] * (t); \
1513 (o)[Z] = (a)[Z] * (1 - (t)) + (b)[Z] * (t); \
1514 } while (0)
1516/**
1517 * @brief Linearly interpolate between two 2D vectors `a' and `b' by
1518 * interpolant `t', expected in the range [0,1], with result in `o'.
1519 *
1520 * NOTE: We intentionally use the form "o = a*(1-t) + b*t" which is
1521 * mathematically equivalent to "o = a + (b-a)*t". The latter might
1522 * result in fewer math operations but cannot guarantee o==v1 when
1523 * t==1 due to floating-point arithmetic error.
1524 */
1525#define V2LERP(o, a, b, t) do { \
1526 (o)[X] = (a)[X] * (1 - (t)) + (b)[X] * (t); \
1527 (o)[Y] = (a)[Y] * (1 - (t)) + (b)[Y] * (t); \
1528 } while (0)
1529
1531 * @brief Linearly interpolate between two 4D vectors `a' and `b' by
1532 * interpolant `t', expected in the range [0,1], with result in `o'.
1533 *
1534 * NOTE: We intentionally use the form "o = a*(1-t) + b*t" which is
1535 * mathematically equivalent to "o = a + (b-a)*t". The latter might
1536 * result in fewer math operations but cannot guarantee o==v1 when
1537 * t==1 due to floating-point arithmetic error.
1538 */
1539#define HLERP(o, a, b, t) do { \
1540 (o)[X] = (a)[X] * (1 - (t)) + (b)[X] * (t); \
1541 (o)[Y] = (a)[Y] * (1 - (t)) + (b)[Y] * (t); \
1542 (o)[Z] = (a)[Z] * (1 - (t)) + (b)[Z] * (t); \
1543 (o)[W] = (a)[W] * (1 - (t)) + (b)[W] * (t); \
1544 } while (0)
1545
1546
1547/**
1548 * @brief Subtract two points to make a vector, dot with another
1549 * vector. Returns the dot product scalar value.
1550 */
1551#define VSUB2DOT(_pt2, _pt, _vec) (\
1552 ((_pt2)[X] - (_pt)[X]) * (_vec)[X] + \
1553 ((_pt2)[Y] - (_pt)[Y]) * (_vec)[Y] + \
1554 ((_pt2)[Z] - (_pt)[Z]) * (_vec)[Z])
1555
1557 * @brief Turn a vector into comma-separated list of elements, for
1558 * variable argument subroutines (e.g. printf()).
1559 */
1560#define V2ARGS(a) (a)[X], (a)[Y]
1561#define V3ARGS(a) (a)[X], (a)[Y], (a)[Z]
1562#define V4ARGS(a) (a)[X], (a)[Y], (a)[Z], (a)[W]
1563
1564/**
1565 * Clamp values within tolerance of an integer to that value.
1567 * For example, INTCLAMP(10.0000123123) evaluates to 10.0
1568 *
1569 * NOTE: should use VDIVIDE_TOL here, but cannot yet. we use
1570 * VUINITIZE_TOL until floats are replaced universally with fastf_t's
1571 * since their epsilon is considerably less than that of a double.
1572 */
1573#define INTCLAMP(_a) (NEAR_EQUAL((_a), rint(_a), VUNITIZE_TOL) ? rint(_a) : (_a))
1574
1575/** Clamp a 3D vector's elements to nearby integer values. */
1576#define VINTCLAMP(_v) do { \
1577 (_v)[X] = INTCLAMP((_v)[X]); \
1578 (_v)[Y] = INTCLAMP((_v)[Y]); \
1579 (_v)[Z] = INTCLAMP((_v)[Z]); \
1580 } while (0)
1582/** Clamp a 2D vector's elements to nearby integer values. */
1583#define V2INTCLAMP(_v) do { \
1584 (_v)[X] = INTCLAMP((_v)[X]); \
1585 (_v)[Y] = INTCLAMP((_v)[Y]); \
1586 } while (0)
1587
1588/** Clamp a 4D vector's elements to nearby integer values. */
1589#define HINTCLAMP(_v) do { \
1590 VINTCLAMP(_v); \
1591 (_v)[W] = INTCLAMP((_v)[W]); \
1592 } while (0)
1593
1595/** @brief integer clamped versions of the previous arg macros. */
1596#define V2INTCLAMPARGS(a) INTCLAMP((a)[X]), INTCLAMP((a)[Y])
1597/** @brief integer clamped versions of the previous arg macros. */
1598#define V3INTCLAMPARGS(a) INTCLAMP((a)[X]), INTCLAMP((a)[Y]), INTCLAMP((a)[Z])
1599/** @brief integer clamped versions of the previous arg macros. */
1600#define V4INTCLAMPARGS(a) INTCLAMP((a)[X]), INTCLAMP((a)[Y]), INTCLAMP((a)[Z]), INTCLAMP((a)[W])
1602/** @brief Print vector name and components on stderr. */
1603#define V2PRINT(a, b) \
1604 fprintf(stderr, "%s (%.6f, %.6g)\n", a, V2ARGS(b))
1605#define VPRINT(a, b) \
1606 fprintf(stderr, "%s (%.6f, %.6f, %.6f)\n", a, V3ARGS(b))
1607#define HPRINT(a, b) \
1608 fprintf(stderr, "%s (%.6f, %.6f, %.6f, %.6f)\n", a, V4ARGS(b))
1609
1611 * @brief Included below are integer clamped versions of the previous
1612 * print macros.
1613 */
1614
1615#define V2INTCLAMPPRINT(a, b) \
1616 fprintf(stderr, "%s (%g, %g)\n", a, V2INTCLAMPARGS(b))
1617#define VINTCLAMPPRINT(a, b) \
1618 fprintf(stderr, "%s (%g, %g, %g)\n", a, V3INTCLAMPARGS(b))
1619#define HINTCLAMPPRINT(a, b) \
1620 fprintf(stderr, "%s (%g, %g, %g, %g)\n", a, V4INTCLAMPARGS(b))
1621
1623/** @brief Vector element multiplication. Really: diagonal matrix X vect. */
1624#define VELMUL(o, a, b) do { \
1625 (o)[X] = (a)[X] * (b)[X]; \
1626 (o)[Y] = (a)[Y] * (b)[Y]; \
1627 (o)[Z] = (a)[Z] * (b)[Z]; \
1628 } while (0)
1630#define VELMUL3(o, a, b, c) do { \
1631 (o)[X] = (a)[X] * (b)[X] * (c)[X]; \
1632 (o)[Y] = (a)[Y] * (b)[Y] * (c)[Y]; \
1633 (o)[Z] = (a)[Z] * (b)[Z] * (c)[Z]; \
1634 } while (0)
1636/** @brief Similar to VELMUL. */
1637#define VELDIV(o, a, b) do { \
1638 (o)[X] = (a)[X] / (b)[X]; \
1639 (o)[Y] = (a)[Y] / (b)[Y]; \
1640 (o)[Z] = (a)[Z] / (b)[Z]; \
1641 } while (0)
1643/**
1644 * @brief Given a direction vector, compute the inverses of each
1645 * element. When division by near-zero would have occurred, inverse
1646 * is set to INFINITY and input direction vector is clamped to zero.
1647 */
1648#define VINVDIR(_inv, _dir) do { \
1649 if (NEAR_ZERO((_dir)[X], SQRT_SMALL_FASTF)) { \
1650 (_dir)[X] = 0.0; \
1651 (_inv)[X] = INFINITY; \
1652 } else { \
1653 (_inv)[X]=1.0/(_dir)[X]; \
1654 } \
1655 if (NEAR_ZERO((_dir)[Y], SQRT_SMALL_FASTF)) { \
1656 (_dir)[Y] = 0.0; \
1657 (_inv)[Y] = INFINITY; \
1658 } else { \
1659 (_inv)[Y]=1.0/(_dir)[Y]; \
1660 } \
1661 if (NEAR_ZERO((_dir)[Z], SQRT_SMALL_FASTF)) { \
1662 (_dir)[Z] = 0.0; \
1663 (_inv)[Z] = INFINITY; \
1664 } else { \
1665 (_inv)[Z]=1.0/(_dir)[Z]; \
1666 } \
1667 } while (0)
1668
1669/**
1670 * @brief Apply the 3x3 part of a mat_t to a 3-tuple. This rotates a
1671 * vector without scaling it (changing its length).
1672 */
1673#define MAT3X3VEC(o, mat, vec) do { \
1674 (o)[X] = (mat)[X]*(vec)[X]+(mat)[Y]*(vec)[Y] + (mat)[ 2]*(vec)[Z]; \
1675 (o)[Y] = (mat)[4]*(vec)[X]+(mat)[5]*(vec)[Y] + (mat)[ 6]*(vec)[Z]; \
1676 (o)[Z] = (mat)[8]*(vec)[X]+(mat)[9]*(vec)[Y] + (mat)[10]*(vec)[Z]; \
1677 } while (0)
1679/** @brief Multiply a 3-tuple by the 3x3 part of a mat_t. */
1680#define VEC3X3MAT(o, i, m) do { \
1681 (o)[X] = (i)[X]*(m)[X] + (i)[Y]*(m)[4] + (i)[Z]*(m)[8]; \
1682 (o)[Y] = (i)[X]*(m)[1] + (i)[Y]*(m)[5] + (i)[Z]*(m)[9]; \
1683 (o)[Z] = (i)[X]*(m)[2] + (i)[Y]*(m)[6] + (i)[Z]*(m)[10]; \
1684 } while (0)
1686/** @brief Apply the 3x3 part of a mat_t to a 2-tuple (Z part=0). */
1687#define MAT3X2VEC(o, mat, vec) do { \
1688 (o)[X] = (mat)[0]*(vec)[X] + (mat)[Y]*(vec)[Y]; \
1689 (o)[Y] = (mat)[4]*(vec)[X] + (mat)[5]*(vec)[Y]; \
1690 (o)[Z] = (mat)[8]*(vec)[X] + (mat)[9]*(vec)[Y]; \
1691 } while (0)
1693/** @brief Multiply a 2-tuple (Z=0) by the 3x3 part of a mat_t. */
1694#define VEC2X3MAT(o, i, m) do { \
1695 (o)[X] = (i)[X]*(m)[0] + (i)[Y]*(m)[4]; \
1696 (o)[Y] = (i)[X]*(m)[1] + (i)[Y]*(m)[5]; \
1697 (o)[Z] = (i)[X]*(m)[2] + (i)[Y]*(m)[6]; \
1698 } while (0)
1700/**
1701 * @brief Apply a 4x4 matrix to a 3-tuple which is an absolute Point
1702 * in space. Output and input points should be separate arrays.
1703 */
1704#define MAT4X3PNT(o, m, i) do { \
1705 double _f; \
1706 _f = 1.0/((m)[12]*(i)[X] + (m)[13]*(i)[Y] + (m)[14]*(i)[Z] + (m)[15]); \
1707 (o)[X]=((m)[0]*(i)[X] + (m)[1]*(i)[Y] + (m)[ 2]*(i)[Z] + (m)[3]) * _f; \
1708 (o)[Y]=((m)[4]*(i)[X] + (m)[5]*(i)[Y] + (m)[ 6]*(i)[Z] + (m)[7]) * _f; \
1709 (o)[Z]=((m)[8]*(i)[X] + (m)[9]*(i)[Y] + (m)[10]*(i)[Z] + (m)[11])* _f; \
1710 } while (0)
1711
1712/**
1713 * @brief Multiply an Absolute 3-Point by a full 4x4 matrix. Output
1714 * and input points should be separate arrays.
1715 */
1716#define PNT3X4MAT(o, i, m) do { \
1717 double _f; \
1718 _f = 1.0/((i)[X]*(m)[3] + (i)[Y]*(m)[7] + (i)[Z]*(m)[11] + (m)[15]); \
1719 (o)[X]=((i)[X]*(m)[0] + (i)[Y]*(m)[4] + (i)[Z]*(m)[8] + (m)[12]) * _f; \
1720 (o)[Y]=((i)[X]*(m)[1] + (i)[Y]*(m)[5] + (i)[Z]*(m)[9] + (m)[13]) * _f; \
1721 (o)[Z]=((i)[X]*(m)[2] + (i)[Y]*(m)[6] + (i)[Z]*(m)[10] + (m)[14])* _f; \
1722 } while (0)
1723
1724/**
1725 * @brief Multiply an Absolute hvect_t 4-Point by a full 4x4 matrix.
1726 * Output and input points should be separate arrays.
1727 */
1728#define MAT4X4PNT(o, m, i) do { \
1729 (o)[X]=(m)[ 0]*(i)[X] + (m)[ 1]*(i)[Y] + (m)[ 2]*(i)[Z] + (m)[ 3]*(i)[W]; \
1730 (o)[Y]=(m)[ 4]*(i)[X] + (m)[ 5]*(i)[Y] + (m)[ 6]*(i)[Z] + (m)[ 7]*(i)[W]; \
1731 (o)[Z]=(m)[ 8]*(i)[X] + (m)[ 9]*(i)[Y] + (m)[10]*(i)[Z] + (m)[11]*(i)[W]; \
1732 (o)[W]=(m)[12]*(i)[X] + (m)[13]*(i)[Y] + (m)[14]*(i)[Z] + (m)[15]*(i)[W]; \
1733 } while (0)
1734
1735/**
1736 * @brief Apply a 4x4 matrix to a 3-tuple which is a relative Vector
1737 * in space. This macro can scale the length of the vector if [15] !=
1738 * 1.0. Output and input vectors should be separate arrays.
1739 */
1740#define MAT4X3VEC(o, m, i) do { \
1741 double _f; \
1742 _f = 1.0/((m)[15]); \
1743 (o)[X] = ((m)[0]*(i)[X] + (m)[1]*(i)[Y] + (m)[ 2]*(i)[Z]) * _f; \
1744 (o)[Y] = ((m)[4]*(i)[X] + (m)[5]*(i)[Y] + (m)[ 6]*(i)[Z]) * _f; \
1745 (o)[Z] = ((m)[8]*(i)[X] + (m)[9]*(i)[Y] + (m)[10]*(i)[Z]) * _f; \
1746 } while (0)
1747
1748#define MAT4XSCALAR(o, m, i) do { \
1749 (o) = (i) / (m)[15]; \
1750 } while (0)
1751
1752/**
1753 * @brief Multiply a Relative 3-Vector by most of a 4x4 matrix.
1754 * Output and input vectors should be separate arrays.
1755 */
1756#define VEC3X4MAT(o, i, m) do { \
1757 double _f; \
1758 _f = 1.0/((m)[15]); \
1759 (o)[X] = ((i)[X]*(m)[0] + (i)[Y]*(m)[4] + (i)[Z]*(m)[8]) * _f; \
1760 (o)[Y] = ((i)[X]*(m)[1] + (i)[Y]*(m)[5] + (i)[Z]*(m)[9]) * _f; \
1761 (o)[Z] = ((i)[X]*(m)[2] + (i)[Y]*(m)[6] + (i)[Z]*(m)[10]) * _f; \
1762 } while (0)
1763
1764/** @brief Multiply a Relative 2-Vector by most of a 4x4 matrix. */
1765#define VEC2X4MAT(o, i, m) do { \
1766 double _f; \
1767 _f = 1.0/((m)[15]); \
1768 (o)[X] = ((i)[X]*(m)[0] + (i)[Y]*(m)[4]) * _f; \
1769 (o)[Y] = ((i)[X]*(m)[1] + (i)[Y]*(m)[5]) * _f; \
1770 (o)[Z] = ((i)[X]*(m)[2] + (i)[Y]*(m)[6]) * _f; \
1771 } while (0)
1772
1773/**
1774 * @brief Included below are macros to update min and max X, Y, Z
1775 * values to contain a point
1776 */
1777
1778#define V_MIN(r, s) if ((r) > (s)) r = (s)
1779
1780#define V_MAX(r, s) if ((r) < (s)) r = (s)
1781
1782#ifdef VMIN
1783# undef VMIN
1784#endif
1785#define VMIN(r, s) do { \
1786 V_MIN((r)[X], (s)[X]); V_MIN((r)[Y], (s)[Y]); V_MIN((r)[Z], (s)[Z]); \
1787 } while (0)
1788
1789#ifdef VMAX
1790# undef VMAX
1791#endif
1792#define VMAX(r, s) do { \
1793 V_MAX((r)[X], (s)[X]); V_MAX((r)[Y], (s)[Y]); V_MAX((r)[Z], (s)[Z]); \
1794 } while (0)
1795
1796#ifdef VMINMAX
1797# undef VMINMAX
1798#endif
1799#define VMINMAX(min, max, pt) do { \
1800 VMIN((min), (pt)); VMAX((max), (pt)); \
1801 } while (0)
1802
1803/**
1804 * @brief Included below are macros to update min and max X, Y
1805 * values to contain a point
1806 */
1807
1808#define V2MIN(r, s) do { \
1809 V_MIN((r)[X], (s)[X]); V_MIN((r)[Y], (s)[Y]); \
1810 } while (0)
1811
1812#define V2MAX(r, s) do { \
1813 V_MAX((r)[X], (s)[X]); V_MAX((r)[Y], (s)[Y]); \
1814 } while (0)
1815
1816#define V2MINMAX(min, max, pt) do { \
1817 V2MIN((min), (pt)); V2MAX((max), (pt)); \
1818 } while (0)
1819
1820
1822 * @brief clamp a value to a low/high number.
1823 */
1824#define CLAMP(_v, _l, _h) do { \
1825 V_MAX((_v), (_l)); else V_MIN((_v), (_h)); \
1826 } while (0)
1827
1828/**
1829 * @brief clamp a vector to a low/high number.
1830 */
1831#define VCLAMP(_v, _l, _h) do { \
1832 CLAMP(_v[X], _l, _h); \
1833 CLAMP(_v[Y], _l, _h); \
1834 CLAMP(_v[Z], _l, _h); \
1835 } while (0)
1837/**
1838 * @brief clamp a 2D vector to a low/high number.
1839 */
1840#define V2CLAMP(_v, _l, _h) do { \
1841 CLAMP(_v[X], _l, _h); \
1842 CLAMP(_v[Y], _l, _h); \
1843 } while (0)
1844
1846 * @brief clamp a 4D vector to a low/high number.
1847 */
1848#define HCLAMP(_v, _l, _h) do { \
1849 CLAMP(_v[X], _l, _h); \
1850 CLAMP(_v[Y], _l, _h); \
1851 CLAMP(_v[Z], _l, _h); \
1852 CLAMP(_v[W], _l, _h); \
1853 } while (0)
1854
1855
1856/**
1857 * @brief Divide out homogeneous parameter from hvect_t, creating
1858 * vect_t.
1859 */
1860#define HDIVIDE(o, v) do { \
1861 if (NEAR_ZERO((v)[W], SMALL_FASTF)) { \
1862 HSETALL((o), 0.0); \
1863 } else { \
1864 (o)[X] = (v)[X] / (v)[W]; \
1865 (o)[Y] = (v)[Y] / (v)[W]; \
1866 (o)[Z] = (v)[Z] / (v)[W]; \
1867 (o)[W] = 1.0; \
1868 } \
1869 } while (0)
1870
1871/**
1872 * @brief Quaternion math definitions.
1873 *
1874 * Note that the [W] component will be put in the last (i.e., third)
1875 * place rather than the first [X] (i.e., [0]) place, so that the X,
1876 * Y, and Z elements will be compatible with vectors. Only
1877 * QUAT_FROM_VROT macros depend on component locations, however.
1878 */
1879
1880/**
1881 * @brief Create Quaternion from Vector and Rotation about vector.
1882 *
1883 * To produce a quaternion representing a rotation by PI radians about
1884 * X-axis:
1885 *
1886 * VSET(axis, 1, 0, 0);
1887 * QUAT_FROM_VROT(quat, M_PI, axis);
1888 * or
1889 * QUAT_FROM_ROT(quat, M_PI, 1.0, 0.0, 0.0, 0.0);
1890 *
1891 * Alternatively, in degrees:
1892 * QUAT_FROM_ROT_DEG(quat, 180.0, 1.0, 0.0, 0.0, 0.0);
1893 */
1894#define QUAT_FROM_ROT(q, r, x, y, z) do { \
1895 fastf_t _rot = (r) * 0.5; \
1896 QSET(q, x, y, z, cos(_rot)); \
1897 VUNITIZE(q); \
1898 _rot = sin(_rot); /* _rot is really just a temp variable now */ \
1899 VSCALE(q, q, _rot); \
1900 } while (0)
1901
1902#define QUAT_FROM_VROT(q, r, v) do { \
1903 fastf_t _rot = (r) * 0.5; \
1904 VMOVE(q, v); \
1905 VUNITIZE(q); \
1906 (q)[W] = cos(_rot); \
1907 _rot = sin(_rot); /* _rot is really just a temp variable now */ \
1908 VSCALE(q, q, _rot); \
1909 } while (0)
1910
1911#define QUAT_FROM_VROT_DEG(q, r, v) \
1912 QUAT_FROM_VROT(q, ((r)*DEG2RAD), v)
1913
1914#define QUAT_FROM_ROT_DEG(q, r, x, y, z) \
1915 QUAT_FROM_ROT(q, ((r)*DEG2RAD), x, y, z)
1917
1918/**
1919 * @brief Set quaternion at `a' to have coordinates `b', `c', `d', and
1920 * `e'.
1921 */
1922#define QSET(a, b, c, d, e) do { \
1923 (a)[X] = (b); \
1924 (a)[Y] = (c); \
1925 (a)[Z] = (d); \
1926 (a)[W] = (e); \
1927 } while (0)
1928
1929/** @brief Transfer quaternion at `b' to quaternion at `a'. */
1930#define QMOVE(a, b) do { \
1931 (a)[X] = (b)[X]; \
1932 (a)[Y] = (b)[Y]; \
1933 (a)[Z] = (b)[Z]; \
1934 (a)[W] = (b)[W]; \
1935 } while (0)
1936
1937/** @brief Add quaternions at `b' and `c', store result at `a'. */
1938#define QADD2(a, b, c) do { \
1939 (a)[X] = (b)[X] + (c)[X]; \
1940 (a)[Y] = (b)[Y] + (c)[Y]; \
1941 (a)[Z] = (b)[Z] + (c)[Z]; \
1942 (a)[W] = (b)[W] + (c)[W]; \
1943 } while (0)
1944
1945/**
1946 * @brief Subtract quaternion at `c' from quaternion at `b', store
1947 * result at `a'.
1948 */
1949#define QSUB2(a, b, c) do { \
1950 (a)[X] = (b)[X] - (c)[X]; \
1951 (a)[Y] = (b)[Y] - (c)[Y]; \
1952 (a)[Z] = (b)[Z] - (c)[Z]; \
1953 (a)[W] = (b)[W] - (c)[W]; \
1954 } while (0)
1955
1956/**
1957 * @brief Scale quaternion at `b' by scalar `c', result at `a'.
1958 */
1959#define QSCALE(a, b, c) do { \
1960 (a)[X] = (b)[X] * (c); \
1961 (a)[Y] = (b)[Y] * (c); \
1962 (a)[Z] = (b)[Z] * (c); \
1963 (a)[W] = (b)[W] * (c); \
1964 } while (0)
1965
1966/**
1967 * @brief Normalize quaternion 'a' to be a unit quaternion.
1968 */
1969#define QUNITIZE(a) do { \
1970 double _f; \
1971 _f = QMAGNITUDE(a); \
1972 if (_f < VDIVIDE_TOL) _f = 0.0; else _f = 1.0/_f; \
1973 (a)[X] *= _f; (a)[Y] *= _f; (a)[Z] *= _f; (a)[W] *= _f; \
1974 } while (0)
1975
1976/** @brief Return scalar magnitude squared of quaternion at `a'. */
1977#define QMAGSQ(a) \
1978 ((a)[X]*(a)[X] + (a)[Y]*(a)[Y] \
1979 + (a)[Z]*(a)[Z] + (a)[W]*(a)[W])
1980
1981/** @brief Return scalar magnitude of quaternion at `a'. */
1982#define QMAGNITUDE(a) sqrt(QMAGSQ(a))
1983
1984/** @brief Compute dot product of quaternions at `a' and `b'. */
1985#define QDOT(a, b) \
1986 ((a)[X]*(b)[X] + (a)[Y]*(b)[Y] \
1987 + (a)[Z]*(b)[Z] + (a)[W]*(b)[W])
1988
1989/**
1990 * @brief Compute quaternion product a = b * c
1991 *
1992 * a[W] = b[W]*c[W] - VDOT(b, c);
1993 * VCROSS(temp, b, c);
1994 * VJOIN2(a, temp, b[W], c, c[W], b);
1995 */
1996#define QMUL(a, b, c) do { \
1997 (a)[W] = (b)[W]*(c)[W] - (b)[X]*(c)[X] - (b)[Y]*(c)[Y] - (b)[Z]*(c)[Z]; \
1998 (a)[X] = (b)[W]*(c)[X] + (b)[X]*(c)[W] + (b)[Y]*(c)[Z] - (b)[Z]*(c)[Y]; \
1999 (a)[Y] = (b)[W]*(c)[Y] + (b)[Y]*(c)[W] + (b)[Z]*(c)[X] - (b)[X]*(c)[Z]; \
2000 (a)[Z] = (b)[W]*(c)[Z] + (b)[Z]*(c)[W] + (b)[X]*(c)[Y] - (b)[Y]*(c)[X]; \
2001 } while (0)
2002
2003/** @brief Conjugate quaternion */
2004#define QCONJUGATE(a, b) do { \
2005 (a)[X] = -(b)[X]; \
2006 (a)[Y] = -(b)[Y]; \
2007 (a)[Z] = -(b)[Z]; \
2008 (a)[W] = (b)[W]; \
2009 } while (0)
2010
2011/**
2012 * @brief Multiplicative inverse quaternion
2013 */
2014#define QINVERSE(a, b) do { \
2015 double _f = QMAGSQ(b); \
2016 if (_f < VDIVIDE_TOL) _f = 0.0; else _f = 1.0/_f; \
2017 (a)[X] = -(b)[X] * _f; \
2018 (a)[Y] = -(b)[Y] * _f; \
2019 (a)[Z] = -(b)[Z] * _f; \
2020 (a)[W] = (b)[W] * _f; \
2021 } while (0)
2022
2023/**
2024 * @brief Blend into quaternion `a'
2025 *
2026 * scalar `b' times quaternion at `c' plus
2027 * scalar `d' times quaternion at `e'
2028 */
2029#define QBLEND2(a, b, c, d, e) do { \
2030 (a)[X] = (b) * (c)[X] + (d) * (e)[X]; \
2031 (a)[Y] = (b) * (c)[Y] + (d) * (e)[Y]; \
2032 (a)[Z] = (b) * (c)[Z] + (d) * (e)[Z]; \
2033 (a)[W] = (b) * (c)[W] + (d) * (e)[W]; \
2034 } while (0)
2035
2036/**
2037 * Macros for dealing with 3-D "extents", aka bounding boxes, that are
2038 * represented as axis-aligned right parallelepipeds (RPPs). This is
2039 * stored as two points: a min point, and a max point. RPP 1 is
2040 * defined by lo1, hi1, RPP 2 by lo2, hi2.
2041 */
2042
2043/**
2044 * Compare two bounding boxes and return true if they are disjoint.
2045 */
2046#define V3RPP_DISJOINT(_l1, _h1, _l2, _h2) \
2047 ((_l1)[X] > (_h2)[X] || (_l1)[Y] > (_h2)[Y] || (_l1)[Z] > (_h2)[Z] || \
2048 (_l2)[X] > (_h1)[X] || (_l2)[Y] > (_h1)[Y] || (_l2)[Z] > (_h1)[Z])
2049
2050/**
2051 * Compare two bounding boxes and return true if they are disjoint
2052 * by at least distance tolerance.
2053 */
2054#define V3RPP_DISJOINT_TOL(_l1, _h1, _l2, _h2, _t) \
2055 ((_l1)[X] > (_h2)[X] + (_t) || \
2056 (_l1)[Y] > (_h2)[Y] + (_t) || \
2057 (_l1)[Z] > (_h2)[Z] + (_t) || \
2058 (_l2)[X] > (_h1)[X] + (_t) || \
2059 (_l2)[Y] > (_h1)[Y] + (_t) || \
2060 (_l2)[Z] > (_h1)[Z] + (_t))
2061
2062/** Compare two bounding boxes and return true If they overlap. */
2063#define V3RPP_OVERLAP(_l1, _h1, _l2, _h2) \
2064 (! ((_l1)[X] > (_h2)[X] || (_l1)[Y] > (_h2)[Y] || (_l1)[Z] > (_h2)[Z] || \
2065 (_l2)[X] > (_h1)[X] || (_l2)[Y] > (_h1)[Y] || (_l2)[Z] > (_h1)[Z]))
2066
2067/**
2068 * @brief If two extents overlap within distance tolerance, return
2069 * true.
2070 */
2071#define V3RPP_OVERLAP_TOL(_l1, _h1, _l2, _h2, _t) \
2072 (! ((_l1)[X] > (_h2)[X] + (_t) || \
2073 (_l1)[Y] > (_h2)[Y] + (_t) || \
2074 (_l1)[Z] > (_h2)[Z] + (_t) || \
2075 (_l2)[X] > (_h1)[X] + (_t) || \
2076 (_l2)[Y] > (_h1)[Y] + (_t) || \
2077 (_l2)[Z] > (_h1)[Z] + (_t)))
2078
2079/**
2080 * @brief Is the point within or on the boundary of the RPP?
2081 *
2082 * FIXME: should not be using >= <=, '=' case is unreliable
2083 */
2084#define V3PNT_IN_RPP(_pt, _lo, _hi) (\
2085 (_pt)[X] >= (_lo)[X] && (_pt)[X] <= (_hi)[X] && \
2086 (_pt)[Y] >= (_lo)[Y] && (_pt)[Y] <= (_hi)[Y] && \
2087 (_pt)[Z] >= (_lo)[Z] && (_pt)[Z] <= (_hi)[Z])
2088
2089/**
2090 * @brief Within the distance tolerance, is the point within the RPP?
2091 *
2092 * FIXME: should not be using >= <=, '=' case is unreliable
2093 */
2094#define V3PNT_IN_RPP_TOL(_pt, _lo, _hi, _t) (\
2095 (_pt)[X] >= (_lo)[X]-(_t) && (_pt)[X] <= (_hi)[X]+(_t) && \
2096 (_pt)[Y] >= (_lo)[Y]-(_t) && (_pt)[Y] <= (_hi)[Y]+(_t) && \
2097 (_pt)[Z] >= (_lo)[Z]-(_t) && (_pt)[Z] <= (_hi)[Z]+(_t))
2098
2099/**
2100 * @brief Is the point outside the RPP by at least the distance tolerance?
2101 * This will not return true if the point is on the RPP.
2102 */
2103#define V3PNT_OUT_RPP_TOL(_pt, _lo, _hi, _t) (\
2104 (_pt)[X] < (_lo)[X]-(_t) || (_pt)[X] > (_hi)[X]+(_t) || \
2105 (_pt)[Y] < (_lo)[Y]-(_t) || (_pt)[Y] > (_hi)[Y]+(_t) || \
2106 (_pt)[Z] < (_lo)[Z]-(_t) || (_pt)[Z] > (_hi)[Z]+(_t))
2107
2108/**
2109 * @brief Determine if one bounding box is within another. Also
2110 * returns true if the boxes are the same.
2111 *
2112 * FIXME: should not be using >= <=, '=' case is unreliable
2113 */
2114#define V3RPP1_IN_RPP2(_lo1, _hi1, _lo2, _hi2) (\
2115 (_lo1)[X] >= (_lo2)[X] && (_hi1)[X] <= (_hi2)[X] && \
2116 (_lo1)[Y] >= (_lo2)[Y] && (_hi1)[Y] <= (_hi2)[Y] && \
2117 (_lo1)[Z] >= (_lo2)[Z] && (_hi1)[Z] <= (_hi2)[Z])
2118
2119
2120/** Swap two 3D vectors */
2121#define VSWAP(_a, _b) do { \
2122 fastf_t _t; \
2123 _t = (_a)[X]; \
2124 (_a)[X] = (_b)[X]; \
2125 (_b)[X] = _t; \
2126 _t = (_a)[Y]; \
2127 (_a)[Y] = (_b)[Y]; \
2128 (_b)[Y] = _t; \
2129 _t = (_a)[Z]; \
2130 (_a)[Z] = (_b)[Z]; \
2131 (_b)[Z] = _t; \
2132 } while (0)
2133
2134/** Swap two 2D vectors */
2135#define V2SWAP(_a, _b) do { \
2136 fastf_t _t; \
2137 _t = (_a)[X]; \
2138 (_a)[X] = (_b)[X]; \
2139 (_b)[X] = _t; \
2140 _t = (_a)[Y]; \
2141 (_a)[Y] = (_b)[Y]; \
2142 (_b)[Y] = _t; \
2143 } while (0)
2144
2145/** Swap two 4D vectors */
2146#define HSWAP(_a, _b) do { \
2147 fastf_t _t; \
2148 _t = (_a)[X]; \
2149 (_a)[X] = (_b)[X]; \
2150 (_b)[X] = _t; \
2151 _t = (_a)[Y]; \
2152 (_a)[Y] = (_b)[Y]; \
2153 (_b)[Y] = _t; \
2154 _t = (_a)[Z]; \
2155 (_a)[Z] = (_b)[Z]; \
2156 (_b)[Z] = _t; \
2157 _t = (_a)[W]; \
2158 (_a)[W] = (_b)[W]; \
2159 (_b)[W] = _t; \
2160 } while (0)
2161
2162/** Swap two 4x4 matrices */
2163#define MAT_SWAP(_a, _b) do { \
2164 mat_t _t; \
2165 MAT_COPY(_t, (_a)); \
2166 MAT_COPY((_a), (_b)); \
2167 MAT_COPY((_b), _t); \
2168 } while (0)
2169
2170/*** Macros suitable for declaration statement initialization. ***/
2172/**
2173 * 3D vector macro suitable for declaration statement initialization.
2174 * this sets all vector elements to the specified value similar to
2175 * VSETALL() but as an initializer array declaration instead of as a
2176 * statement.
2177 */
2178#define VINITALL(_v) {(_v), (_v), (_v)}
2179
2180/**
2181 * 2D vector macro suitable for declaration statement initialization.
2182 * this sets all vector elements to the specified value similar to
2183 * VSETALLN(hvect_t,val,2) but as an initializer array declaration
2184 * instead of as a statement.
2185 */
2186#define V2INITALL(_v) {(_v), (_v)}
2187
2188/**
2189 * 4D homogeneous vector macro suitable for declaration statement
2190 * initialization. this sets all vector elements to the specified
2191 * value similar to VSETALLN(hvect_t,val,4) but as an initializer
2192 * array declaration instead of as a statement.
2193 */
2194#define HINITALL(_v) {(_v), (_v), (_v), (_v)}
2195
2196/**
2197 * 3D vector macro suitable for declaration statement initialization.
2198 * this sets all vector elements to zero similar to calling
2199 * VSETALL(0.0) but as an initializer array declaration instead of as
2200 * a statement.
2201 */
2202#define VINIT_ZERO {0.0, 0.0, 0.0}
2203
2204/**
2205 * 2D vector macro suitable for declaration statement initialization.
2206 * this sets all vector elements to zero similar to calling
2207 * V2SETALL(0.0) but as an initializer array declaration instead of as
2208 * a statement.
2209 */
2210#define V2INIT_ZERO {0.0, 0.0}
2211
2212/**
2213 * 4D homogeneous vector macro suitable for declaration statement
2214 * initialization. this sets all vector elements to zero similar to
2215 * calling VSETALLN(hvect_t,0.0,4) but as an initializer array
2216 * declaration instead of as a statement.
2217 */
2218#define HINIT_ZERO {0.0, 0.0, 0.0, 0.0}
2219
2220/**
2221 * 4D homogeneous vector macro suitable for identityt declaration
2222 * statement initialization. this sets all vector elements to zero
2223 * except for W, set to 1.0, suitable for init declaration.
2224 */
2225#define HINIT_IDN {0.0, 0.0, 0.0, 1.0}
2227/**
2228 * matrix macro suitable for declaration statement initialization.
2229 * this sets up a zero matrix similar to calling MAT_ZERO but as an
2230 * initializer array declaration instead of as a statement.
2231 */
2232#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}
2234/**
2235 * matrix macro suitable for declaration statement initialization.
2236 * this sets up an identity matrix similar to calling MAT_IDN but as
2237 * an initializer array declaration instead of as a statement.
2238 */
2239#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}
2241
2242#ifdef __cplusplus
2243} /* end extern "C" */
2244#endif
2245
2246#endif /* VMATH_H */
2248/** @} */
2249/*
2250 * Local Variables:
2251 * mode: C
2252 * tab-width: 8
2253 * indent-tabs-mode: t
2254 * c-file-style: "stroustrup"
2255 * End:
2256 * ex: shiftwidth=4 tabstop=8
2257 */
Header file for the BRL-CAD common definitions.
fastf_t * pointp_t
pointer to a 3-tuple point
Definition vmath.h:360
fastf_t vect_t[ELEMENTS_PER_VECT]
3-tuple vector
Definition vmath.h:351
fastf_t * point2dp_t
pointer to a 2-tuple point
Definition vmath.h:348
double fastf_t
fastest 64-bit (or larger) floating point type
Definition vmath.h:336
#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:372
fastf_t hvect_t[ELEMENTS_PER_HVECT]
4-tuple vector
Definition vmath.h:363
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:345
#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:342
#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:369
fastf_t plane_t[ELEMENTS_PER_PLANE]
Definition of a plane equation.
Definition vmath.h:399
vmath_vector_component_
Definition vmath.h:402
fastf_t * matp_t
pointer to a 4x4 matrix
Definition vmath.h:375
#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:357
#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:366
fastf_t * vectp_t
pointer to a 3-tuple vector
Definition vmath.h:354
#define ELEMENTS_PER_MAT
number of fastf_t's per mat_t
Definition vmath.h:328
fastf_t vect2d_t[ELEMENTS_PER_VECT2D]
2-tuple vector
Definition vmath.h:339
enum vmath_vector_component_ vmath_vector_component
vmath_matrix_component_
Definition vmath.h:414
@ H
Definition vmath.h:407
@ Y
Definition vmath.h:404
@ X
Definition vmath.h:403
@ Z
Definition vmath.h:405
@ W
Definition vmath.h:406
@ MSA
Definition vmath.h:421
@ MDZ
Definition vmath.h:420
@ MSX
Definition vmath.h:415
@ MDX
Definition vmath.h:416
@ MDY
Definition vmath.h:418
@ MSZ
Definition vmath.h:419
@ MSY
Definition vmath.h:417