vmath.h

Go to the documentation of this file.
00001 /*                         V M A T H . H
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 2004-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 /** @addtogroup mat */
00022 /*@{*/
00023 /** @file vmath.h
00024  *
00025  *@brief vector/matrix math
00026  *
00027  *  This header file defines many commonly used 3D vector math macros,
00028  *  and operates on vect_t, point_t, mat_t, and quat_t objects.
00029  *
00030  *  Note that while many people in the computer graphics field use
00031  *  post-multiplication with row vectors (ie, vector * matrix * matrix ...)
00032  *  the BRL-CAD system uses the more traditional representation of
00033  *  column vectors (ie, ... matrix * matrix * vector).  (The matrices
00034  *  in these two representations are the transposes of each other). Therefore,
00035  *  when transforming a vector by a matrix, pre-multiplication is used, ie:
00036  *
00037  *              view_vec = model2view_mat * model_vec
00038  *
00039  *  Furthermore, additional transformations are multiplied on the left, ie:
00040  *
00041 <tt> @code 
00042  *              vec'  =  T1 * vec
00043  *              vec'' =  T2 * T1 * vec  =  T2 * vec'
00044 @endcode </tt>
00045  *
00046  *  The most notable implication of this is the location of the
00047  *  "delta" (translation) values in the matrix, ie:
00048  *
00049  <tt> @code
00050  *        x'     ( R0   R1   R2   Dx )      x
00051  *        y' =   ( R4   R5   R6   Dy )   *  y
00052  *        z'     ( R8   R9   R10  Dz )      z
00053  *        w'     (  0    0    0   1/s)      w
00054 @endcode </tt>
00055  *
00056  *  @par Note -
00057  *      vect_t objects are 3-tuples
00058  *@n    hvect_t objects are 4-tuples
00059  *
00060  *  Most of these macros require that the result be in
00061  *  separate storage, distinct from the input parameters,
00062  *  except where noted.
00063  *
00064  *  When writing macros like this, it is very important that any
00065  *  variables which are declared within code blocks inside a macro
00066  *  start with an underscore.  This prevents any name conflicts with
00067  *  user-provided parameters.  For example:
00068  *      { register double _f; stuff; }
00069  *
00070  *  @author Michael John Muuss
00071  *      
00072  *
00073  *  @par Source
00074  *      The U. S. Army Research Laboratory
00075  * @n   Aberdeen Proving Ground, Maryland  21005
00076  *
00077  *  Include Sequencing -
00078 @code
00079         #include <stdio.h>
00080         #include <math.h>
00081         #include "machine.h"    /_* For fastf_t definition on this machine *_/
00082         #include "vmath.h"
00083 @endcode
00084  *
00085  * @par  Libraries Used
00086  *      -lm -lc
00087  *
00088  *  $Header: /cvsroot/brlcad/brlcad/include/vmath.h,v 14.14 2006/09/18 05:24:07 lbutler Exp $
00089  */
00090 
00091 #ifndef VMATH_H
00092 #define VMATH_H seen
00093 
00094 #include "common.h"
00095 
00096 /* for sqrt(), sin(), cos(), rint(), etc */
00097 #ifdef HAVE_MATH_H
00098 #  include <math.h>
00099 #endif
00100 
00101 /* for floating point tolerances and other math constants */
00102 #ifdef HAVE_FLOAT_H
00103 #  include <float.h>
00104 #endif
00105 
00106 __BEGIN_DECLS
00107 
00108 #ifndef M_PI
00109 #  define M_E           2.7182818284590452354   /* e */
00110 #  define M_LOG2E       1.4426950408889634074   /* log_2 e */
00111 #  define M_LOG10E      0.43429448190325182765  /* log_10 e */
00112 #  define M_LN2         0.69314718055994530942  /* log_e 2 */
00113 #  define M_LN10        2.30258509299404568402  /* log_e 10 */
00114 #  define M_PI          3.14159265358979323846  /* pi */
00115 #  define M_PI_2        1.57079632679489661923  /* pi/2 */
00116 #  define M_PI_4        0.78539816339744830962  /* pi/4 */
00117 #  define M_1_PI        0.31830988618379067154  /* 1/pi */
00118 #  define M_2_PI        0.63661977236758134308  /* 2/pi */
00119 #  define M_2_SQRTPI    1.12837916709551257390  /* 2/sqrt(pi) */
00120 #  define M_SQRT2       1.41421356237309504880  /* sqrt(2) */
00121 #  define M_SQRT1_2     0.70710678118654752440  /* 1/sqrt(2) */
00122 #  define M_SQRT2_DIV2  0.70710678118654752440  /* 1/sqrt(2) */
00123 #endif
00124 #ifndef PI
00125 #  define PI M_PI
00126 #endif
00127 
00128 /* minimum computation tolerances */
00129 #ifdef vax
00130 #  define VDIVIDE_TOL   ( 1.0e-10 )
00131 #  define VUNITIZE_TOL  ( 1.0e-7 )
00132 #else
00133 #  ifdef DBL_EPSILON
00134 #    define VDIVIDE_TOL         ( DBL_EPSILON )
00135 #  else
00136 #    define VDIVIDE_TOL         ( 1.0e-20 )
00137 #  endif
00138 #  ifdef FLT_EPSILON
00139 #    define VUNITIZE_TOL        ( FLT_EPSILON )
00140 #  else
00141 #    define VUNITIZE_TOL        ( 1.0e-15 )
00142 #  endif
00143 #endif
00144 
00145 /** @brief # of fastf_t's per vect_t */
00146 #define ELEMENTS_PER_VECT       3      
00147 #define ELEMENTS_PER_PT         3
00148 /** @brief # of fastf_t's per hvect_t */
00149 #define HVECT_LEN               4      
00150 #define HPT_LEN                 4
00151 
00152 /** @brief # of fastf_t's per plane_t */
00153 #define ELEMENTS_PER_PLANE      4
00154 #define ELEMENTS_PER_MAT        (4*4)
00155 
00156 /*
00157  * Types for matrixes and vectors.
00158  */
00159 /** @brief 4x4 matrix */
00160 typedef fastf_t mat_t[ELEMENTS_PER_MAT]; 
00161 typedef fastf_t *matp_t;
00162 
00163 /** @brief 3-tuple vector */
00164 typedef fastf_t vect_t[ELEMENTS_PER_VECT];  
00165 typedef fastf_t *vectp_t;
00166 
00167 /** @brief 3-tuple point */
00168 typedef fastf_t point_t[ELEMENTS_PER_PT];  
00169 typedef fastf_t *pointp_t;
00170 
00171 typedef fastf_t point2d_t[2];
00172 
00173 /** @brief 4-tuple vector */
00174 typedef fastf_t hvect_t[HVECT_LEN];   
00175 
00176 /** @brief 4-tuple point */
00177 typedef fastf_t hpoint_t[HPT_LEN];    
00178 
00179 /** @brief 4-element quaternion */
00180 #define quat_t  hvect_t         
00181 
00182 /**
00183  * return truthfully whether a value is within some epsilon from zero
00184  */
00185 #define NEAR_ZERO(val,epsilon)  ( ((val) > -epsilon) && ((val) < epsilon) )
00186 
00187 /**
00188  * clamp a value to a low/high number
00189  */
00190 #define CLAMP(_v, _l, _h) if ((_v) < (_l)) _v = _l; else if ((_v) > (_h)) _v = _h
00191 
00192 /**
00193  * @brief
00194  *  Definition of a plane equation
00195  *
00196  *  A plane is defined by a unit-length outward pointing normal vector (N),
00197  *  and the perpendicular (shortest) distance from the origin to the plane
00198  *  (in element N[3]).
00199  *
00200  *  The plane consists of all points P=(x,y,z) such that
00201  *@n    VDOT(P,N) - N[3] == 0
00202  *@n  that is,
00203  *@n    N[X]*x + N[Y]*y + N[Z]*z - N[3] == 0
00204  *
00205  *  The inside of the halfspace bounded by the plane
00206  *  consists of all points P such that
00207  *@n    VDOT(P,N) - N[3] <= 0
00208  *
00209  *  A ray with direction D is classified w.r.t. the plane by
00210  *
00211  *@n    VDOT(D,N) < 0   ray enters halfspace defined by plane
00212  *@n    VDOT(D,N) == 0  ray is parallel to plane
00213  *@n    VDOT(D,N) > 0   ray exits halfspace defined by plane
00214  */
00215 typedef fastf_t plane_t[ELEMENTS_PER_PLANE];
00216 
00217 /** @brief Compute distance from a point to a plane */
00218 #define DIST_PT_PLANE(_pt, _pl) (VDOT(_pt, _pl) - (_pl)[H])
00219 
00220 /** @brief Compute distance between two points */
00221 #define DIST_PT_PT(a,b)         sqrt( \
00222         ((a)[X]-(b)[X])*((a)[X]-(b)[X]) + \
00223         ((a)[Y]-(b)[Y])*((a)[Y]-(b)[Y]) + \
00224         ((a)[Z]-(b)[Z])*((a)[Z]-(b)[Z]) )
00225 
00226 /* Element names in homogeneous vector (4-tuple) */
00227 #define X       0
00228 #define Y       1
00229 #define Z       2
00230 #define H       3
00231 #define W       H
00232 
00233 /* Locations of deltas in 4x4 Homogenous Transform matrix */
00234 #define MDX     3
00235 #define MDY     7
00236 #define MDZ     11
00237 
00238 /** @brief set translation values of 4x4 matrix with x, y, z values */
00239 #define MAT_DELTAS(m,x,y,z)     { \
00240                         (m)[MDX] = (x); \
00241                         (m)[MDY] = (y); \
00242                         (m)[MDZ] = (z); }
00243 
00244 /** @brief set translation values of 4x4 matrix from a vector */
00245 #define MAT_DELTAS_VEC(_m,_v)   \
00246                         MAT_DELTAS(_m, (_v)[X], (_v)[Y], (_v)[Z] )
00247 
00248 /** @brief set translation values of 4x4 matrix from a reversed vector */
00249 #define MAT_DELTAS_VEC_NEG(_m,_v)       \
00250                         MAT_DELTAS(_m,-(_v)[X],-(_v)[Y],-(_v)[Z] )
00251 
00252 /** @brief get translation values of 4x4 matrix to a vector */
00253 #define MAT_DELTAS_GET(_v,_m)   { \
00254                         (_v)[X] = (_m)[MDX]; \
00255                         (_v)[Y] = (_m)[MDY]; \
00256                         (_v)[Z] = (_m)[MDZ]; }
00257 
00258 /** @brief get translation values of 4x4 matrix to a vector, reversed */
00259 #define MAT_DELTAS_GET_NEG(_v,_m)       { \
00260                         (_v)[X] = -(_m)[MDX]; \
00261                         (_v)[Y] = -(_m)[MDY]; \
00262                         (_v)[Z] = -(_m)[MDZ]; }
00263 
00264 /* Locations of scaling values in 4x4 Homogenous Transform matrix */
00265 #define MSX     0
00266 #define MSY     5
00267 #define MSZ     10
00268 #define MSA     15
00269 
00270 /** @brief set scale of 4x4 matrix from xyz */
00271 #define MAT_SCALE(_m, _x, _y, _z) { \
00272         (_m)[MSX] = _x; \
00273         (_m)[MSY] = _y; \
00274         (_m)[MSZ] = _z; }
00275 
00276 /** @brief set scale of 4x4 matrix from vector */
00277 #define MAT_SCALE_VEC(_m, _v) {\
00278         (_m)[MSX] = (_v)[X]; \
00279         (_m)[MSY] = (_v)[Y]; \
00280         (_m)[MSZ] = (_v)[Z]; }
00281 
00282 /** @brief set uniform scale of 4x4 matrix from scalar */
00283 #define MAT_SCALE_ALL(_m, _s) (_m)[MSA] = (_s)
00284 
00285 
00286 /* Macro versions of librt/mat.c functions, for when speed really matters */
00287 
00288 /** @brief zero a matrix */
00289 #define MAT_ZERO(m)     { \
00290         (m)[0] = (m)[1] = (m)[2] = (m)[3] = \
00291         (m)[4] = (m)[5] = (m)[6] = (m)[7] = \
00292         (m)[8] = (m)[9] = (m)[10] = (m)[11] = \
00293         (m)[12] = (m)[13] = (m)[14] = (m)[15] = 0.0;}
00294 
00295 /* # define MAT_ZERO(m) {\
00296         register int _j; \
00297         for(_j=0; _j<16; _j++) (m)[_j]=0.0; }
00298   */
00299 
00300 /** @brief set matrix to identity */
00301 #define MAT_IDN(m)      {\
00302         (m)[1] = (m)[2] = (m)[3] = (m)[4] =\
00303         (m)[6] = (m)[7] = (m)[8] = (m)[9] = \
00304         (m)[11] = (m)[12] = (m)[13] = (m)[14] = 0.0;\
00305         (m)[0] = (m)[5] = (m)[10] = (m)[15] = 1.0;}
00306 
00307 /* #define MAT_IDN(m)   {\
00308         int _j; for(_j=0;_j<16;_j++) (m)[_j]=0.0;\
00309         (m)[0] = (m)[5] = (m)[10] = (m)[15] = 1.0;}
00310   */
00311 
00312 /** @brief copy a matrix */
00313 #define MAT_COPY( d, s )        { \
00314         (d)[0] = (s)[0];\
00315         (d)[1] = (s)[1];\
00316         (d)[2] = (s)[2];\
00317         (d)[3] = (s)[3];\
00318         (d)[4] = (s)[4];\
00319         (d)[5] = (s)[5];\
00320         (d)[6] = (s)[6];\
00321         (d)[7] = (s)[7];\
00322         (d)[8] = (s)[8];\
00323         (d)[9] = (s)[9];\
00324         (d)[10] = (s)[10];\
00325         (d)[11] = (s)[11];\
00326         (d)[12] = (s)[12];\
00327         (d)[13] = (s)[13];\
00328         (d)[14] = (s)[14];\
00329         (d)[15] = (s)[15]; }
00330 
00331 /* #define MAT_COPY(o,m)   VMOVEN(o,m,16)  */
00332 
00333 /** @brief Set vector at `a' to have coordinates `b', `c', `d' */
00334 #define VSET(a,b,c,d)   { \
00335                         (a)[X] = (b);\
00336                         (a)[Y] = (c);\
00337                         (a)[Z] = (d); }
00338 
00339 /** @brief Set all elements of vector to same scalar value */
00340 #define VSETALL(a,s)    { (a)[X] = (a)[Y] = (a)[Z] = (s); }
00341 
00342 /** @brief Set all elements of N-vector to same scalar value */
00343 #define VSETALLN(v,s,n)  {\
00344         register int _j;\
00345         for (_j=0; _j<n; _j++) v[_j]=(s);}
00346 
00347 /** @brief Transfer vector at `b' to vector at `a' */
00348 #define VMOVE(a,b)      { \
00349                         (a)[X] = (b)[X];\
00350                         (a)[Y] = (b)[Y];\
00351                         (a)[Z] = (b)[Z]; }
00352 
00353 /** @brief Transfer vector of length `n' at `b' to vector at `a' */
00354 #define VMOVEN(a,b,n) \
00355         { register int _vmove; \
00356         for(_vmove = 0; _vmove < (n); _vmove++) \
00357                 (a)[_vmove] = (b)[_vmove]; \
00358         }
00359 
00360 /** @brief Move a homogeneous 4-tuple */
00361 #define HMOVE(a,b)      { \
00362                         (a)[X] = (b)[X];\
00363                         (a)[Y] = (b)[Y];\
00364                         (a)[Z] = (b)[Z];\
00365                         (a)[W] = (b)[W]; }
00366 
00367 /** @brief move a 2D vector.
00368  * This naming convention seems better than the VMOVE_2D version below
00369 */
00370 #define V2MOVE(a,b)     { \
00371                         (a)[X] = (b)[X];\
00372                         (a)[Y] = (b)[Y]; }
00373 
00374 /** @brief Reverse the direction of vector b and store it in a */
00375 #define VREVERSE(a,b)   { \
00376                         (a)[X] = -(b)[X]; \
00377                         (a)[Y] = -(b)[Y]; \
00378                         (a)[Z] = -(b)[Z]; }
00379 
00380 /** @brief Same as VREVERSE, but for a 4-tuple.  Also useful on plane_t objects */
00381 #define HREVERSE(a,b)   { \
00382                         (a)[X] = -(b)[X]; \
00383                         (a)[Y] = -(b)[Y]; \
00384                         (a)[Z] = -(b)[Z]; \
00385                         (a)[W] = -(b)[W]; }
00386 
00387 /** @brief Add vectors at `b' and `c', store result at `a' */
00388 #ifdef SHORT_VECTORS
00389 #define VADD2(a,b,c) VADD2N(a,b,c, 3)
00390 #else
00391 #define VADD2(a,b,c)    { \
00392                         (a)[X] = (b)[X] + (c)[X];\
00393                         (a)[Y] = (b)[Y] + (c)[Y];\
00394                         (a)[Z] = (b)[Z] + (c)[Z]; }
00395 #endif /* SHORT_VECTORS */
00396 
00397 /** @brief Add vectors of length `n' at `b' and `c', store result at `a' */
00398 #define VADD2N(a,b,c,n) \
00399         { register int _vadd2; \
00400         for(_vadd2 = 0; _vadd2 < (n); _vadd2++) \
00401                 (a)[_vadd2] = (b)[_vadd2] + (c)[_vadd2]; \
00402         }
00403 
00404 #define V2ADD2(a,b,c)   { \
00405                         (a)[X] = (b)[X] + (c)[X];\
00406                         (a)[Y] = (b)[Y] + (c)[Y];}
00407 
00408 /** @brief Subtract vector at `c' from vector at `b', store result at `a' */
00409 #ifdef SHORT_VECTORS
00410 #define VSUB2(a,b,c)    VSUB2N(a,b,c, 3)
00411 #else
00412 #define VSUB2(a,b,c)    { \
00413                         (a)[X] = (b)[X] - (c)[X];\
00414                         (a)[Y] = (b)[Y] - (c)[Y];\
00415                         (a)[Z] = (b)[Z] - (c)[Z]; }
00416 #endif /* SHORT_VECTORS */
00417 
00418 /** @brief Subtract `n' length vector at `c' from vector at `b', store result at `a' */
00419 #define VSUB2N(a,b,c,n) \
00420         { register int _vsub2; \
00421         for(_vsub2 = 0; _vsub2 < (n); _vsub2++) \
00422                 (a)[_vsub2] = (b)[_vsub2] - (c)[_vsub2]; \
00423         }
00424 
00425 #define V2SUB2(a,b,c)   { \
00426                         (a)[X] = (b)[X] - (c)[X];\
00427                         (a)[Y] = (b)[Y] - (c)[Y];}
00428 
00429 /** @brief Vectors:  A = B - C - D */
00430 #ifdef SHORT_VECTORS
00431 #define VSUB3(a,b,c,d) VSUB3(a,b,c,d, 3)
00432 #else
00433 #define VSUB3(a,b,c,d)  { \
00434                         (a)[X] = (b)[X] - (c)[X] - (d)[X];\
00435                         (a)[Y] = (b)[Y] - (c)[Y] - (d)[Y];\
00436                         (a)[Z] = (b)[Z] - (c)[Z] - (d)[Z]; }
00437 #endif /* SHORT_VECTORS */
00438 
00439 /** @brief Vectors:  A = B - C - D for vectors of length `n' */
00440 #define VSUB3N(a,b,c,d,n) \
00441         { register int _vsub3; \
00442         for(_vsub3 = 0; _vsub3 < (n); _vsub3++) \
00443                 (a)[_vsub3] = (b)[_vsub3] - (c)[_vsub3] - (d)[_vsub3]; \
00444         }
00445 
00446 /** @brief Add 3 vectors at `b', `c', and `d', store result at `a' */
00447 #ifdef SHORT_VECTORS
00448 #define VADD3(a,b,c,d) VADD3N(a,b,c,d, 3)
00449 #else
00450 #define VADD3(a,b,c,d)  { \
00451                         (a)[X] = (b)[X] + (c)[X] + (d)[X];\
00452                         (a)[Y] = (b)[Y] + (c)[Y] + (d)[Y];\
00453                         (a)[Z] = (b)[Z] + (c)[Z] + (d)[Z]; }
00454 #endif /* SHORT_VECTORS */
00455 
00456 /** @brief Add 3 vectors of length `n' at `b', `c', and `d', store result at `a' */
00457 #define VADD3N(a,b,c,d,n) \
00458         { register int _vadd3; \
00459         for(_vadd3 = 0; _vadd3 < (n); _vadd3++) \
00460                 (a)[_vadd3] = (b)[_vadd3] + (c)[_vadd3] + (d)[_vadd3]; \
00461         }
00462 
00463 /** @brief Add 4 vectors at `b', `c', `d', and `e', store result at `a' */
00464 #ifdef SHORT_VECTORS
00465 #define VADD4(a,b,c,d,e) VADD4N(a,b,c,d,e, 3)
00466 #else
00467 #define VADD4(a,b,c,d,e) { \
00468                         (a)[X] = (b)[X] + (c)[X] + (d)[X] + (e)[X];\
00469                         (a)[Y] = (b)[Y] + (c)[Y] + (d)[Y] + (e)[Y];\
00470                         (a)[Z] = (b)[Z] + (c)[Z] + (d)[Z] + (e)[Z]; }
00471 #endif /* SHORT_VECTORS */
00472 
00473 /** @brief Add 4 `n' length vectors at `b', `c', `d', and `e', store result at `a' */
00474 #define VADD4N(a,b,c,d,e,n) \
00475         { register int _vadd4; \
00476         for(_vadd4 = 0; _vadd4 < (n); _vadd4++) \
00477                 (a)[_vadd4] = (b)[_vadd4] + (c)[_vadd4] + (d)[_vadd4] + (e)[_vadd4];\
00478         }
00479 
00480 /** @brief Scale vector at `b' by scalar `c', store result at `a' */
00481 #ifdef SHORT_VECTORS
00482 #define VSCALE(a,b,c) VSCALEN(a,b,c, 3)
00483 #else
00484 #define VSCALE(a,b,c)   { \
00485                         (a)[X] = (b)[X] * (c);\
00486                         (a)[Y] = (b)[Y] * (c);\
00487                         (a)[Z] = (b)[Z] * (c); }
00488 #endif /* SHORT_VECTORS */
00489 
00490 #define HSCALE(a,b,c)   { \
00491                         (a)[X] = (b)[X] * (c);\
00492                         (a)[Y] = (b)[Y] * (c);\
00493                         (a)[Z] = (b)[Z] * (c);\
00494                         (a)[W] = (b)[W] * (c); }
00495 
00496 /** @brief Scale vector of length `n' at `b' by scalar `c', store result at `a' */
00497 #define VSCALEN(a,b,c,n) \
00498         { register int _vscale; \
00499         for(_vscale = 0; _vscale < (n); _vscale++) \
00500                 (a)[_vscale] = (b)[_vscale] * (c); \
00501         }
00502 
00503 #define V2SCALE(a,b,c)  { \
00504                         (a)[X] = (b)[X] * (c);\
00505                         (a)[Y] = (b)[Y] * (c); }
00506 
00507 /** @brief Normalize vector `a' to be a unit vector */
00508 #ifdef SHORT_VECTORS
00509 #define VUNITIZE(a) { \
00510         register double _f = MAGSQ(a); \
00511         register int _vunitize; \
00512         if ( ! NEAR_ZERO( _f-1.0, VUNITIZE_TOL ) ) { \
00513                 _f = sqrt( _f ); \
00514                 if( _f < VDIVIDE_TOL ) { VSETALL( (a), 0.0 ); } else { \
00515                         _f = 1.0/_f; \
00516                         for(_vunitize = 0; _vunitize < 3; _vunitize++) \
00517                                 (a)[_vunitize] *= _f; \
00518                 } \
00519         } \
00520 }
00521 #else
00522 #define VUNITIZE(a)     { \
00523         register double _f = MAGSQ(a); \
00524         if ( ! NEAR_ZERO( _f-1.0, VUNITIZE_TOL ) ) { \
00525                 _f = sqrt( _f ); \
00526                 if( _f < VDIVIDE_TOL ) { VSETALL( (a), 0.0 ); } else { \
00527                         _f = 1.0/_f; \
00528                         (a)[X] *= _f; (a)[Y] *= _f; (a)[Z] *= _f; \
00529                 } \
00530         } \
00531 }
00532 #endif /* SHORT_VECTORS */
00533 
00534 /** @brief If vector magnitude is too small, return an error code */
00535 #define VUNITIZE_RET(a,ret)     { \
00536                         register double _f; _f = MAGNITUDE(a); \
00537                         if( _f < VDIVIDE_TOL ) return(ret); \
00538                         _f = 1.0/_f; \
00539                         (a)[X] *= _f; (a)[Y] *= _f; (a)[Z] *= _f; }
00540 
00541 /** @brief
00542  *  Find the sum of two points, and scale the result.
00543  *  Often used to find the midpoint.
00544  */
00545 #ifdef SHORT_VECTORS
00546 #define VADD2SCALE( o, a, b, s )        VADD2SCALEN( o, a, b, s, 3 )
00547 #else
00548 #define VADD2SCALE( o, a, b, s )        { \
00549                                         (o)[X] = ((a)[X] + (b)[X]) * (s); \
00550                                         (o)[Y] = ((a)[Y] + (b)[Y]) * (s); \
00551                                         (o)[Z] = ((a)[Z] + (b)[Z]) * (s); }
00552 #endif
00553 
00554 #define VADD2SCALEN( o, a, b, n ) \
00555         { register int _vadd2scale; \
00556         for( _vadd2scale = 0; _vadd2scale < (n); _vadd2scale++ ) \
00557                 (o)[_vadd2scale] = ((a)[_vadd2scale] + (b)[_vadd2scale]) * (s); \
00558         }
00559 
00560 /** @brief
00561  *  Find the difference between two points, and scale result.
00562  *  Often used to compute bounding sphere radius given rpp points.
00563  */
00564 #ifdef SHORT_VECTORS
00565 #define VSUB2SCALE( o, a, b, s )        VSUB2SCALEN( o, a, b, s, 3 )
00566 #else
00567 #define VSUB2SCALE( o, a, b, s )        { \
00568                                         (o)[X] = ((a)[X] - (b)[X]) * (s); \
00569                                         (o)[Y] = ((a)[Y] - (b)[Y]) * (s); \
00570                                         (o)[Z] = ((a)[Z] - (b)[Z]) * (s); }
00571 #endif
00572 
00573 #define VSUB2SCALEN( o, a, b, n ) \
00574         { register int _vsub2scale; \
00575         for( _vsub2scale = 0; _vsub2scale < (n); _vsub2scale++ ) \
00576                 (o)[_vsub2scale] = ((a)[_vsub2scale] - (b)[_vsub2scale]) * (s); \
00577         }
00578 
00579 
00580 /** @brief
00581  *  Combine together several vectors, scaled by a scalar
00582  */
00583 #ifdef SHORT_VECTORS
00584 #define VCOMB3(o, a,b, c,d, e,f)        VCOMB3N(o, a,b, c,d, e,f, 3)
00585 #else
00586 #define VCOMB3(o, a,b, c,d, e,f)        {\
00587         (o)[X] = (a) * (b)[X] + (c) * (d)[X] + (e) * (f)[X];\
00588         (o)[Y] = (a) * (b)[Y] + (c) * (d)[Y] + (e) * (f)[Y];\
00589         (o)[Z] = (a) * (b)[Z] + (c) * (d)[Z] + (e) * (f)[Z];}
00590 #endif /* SHORT_VECTORS */
00591 
00592 #define VCOMB3N(o, a,b, c,d, e,f, n)    {\
00593         { register int _vcomb3; \
00594         for(_vcomb3 = 0; _vcomb3 < (n); _vcomb3++) \
00595                 (o)[_vcomb3] = (a) * (b)[_vcomb3] + (c) * (d)[_vcomb3] + (e) * (f)[_vcomb3]; \
00596         } }
00597 
00598 #ifdef SHORT_VECTORS
00599 #define VCOMB2(o, a,b, c,d)     VCOMB2N(o, a,b, c,d, 3)
00600 #else
00601 #define VCOMB2(o, a,b, c,d)     {\
00602         (o)[X] = (a) * (b)[X] + (c) * (d)[X];\
00603         (o)[Y] = (a) * (b)[Y] + (c) * (d)[Y];\
00604         (o)[Z] = (a) * (b)[Z] + (c) * (d)[Z];}
00605 #endif /* SHORT_VECTORS */
00606 
00607 #define VCOMB2N(o, a,b, c,d, n) {\
00608         { register int _vcomb2; \
00609         for(_vcomb2 = 0; _vcomb2 < (n); _vcomb2++) \
00610                 (o)[_vcomb2] = (a) * (b)[_vcomb2] + (c) * (d)[_vcomb2]; \
00611         } }
00612 
00613 #define VJOIN4(a,b,c,d,e,f,g,h,i,j)     { \
00614         (a)[X] = (b)[X] + (c)*(d)[X] + (e)*(f)[X] + (g)*(h)[X] + (i)*(j)[X];\
00615         (a)[Y] = (b)[Y] + (c)*(d)[Y] + (e)*(f)[Y] + (g)*(h)[Y] + (i)*(j)[Y];\
00616         (a)[Z] = (b)[Z] + (c)*(d)[Z] + (e)*(f)[Z] + (g)*(h)[Z] + (i)*(j)[Z]; }
00617 
00618 #define VJOIN3(a,b,c,d,e,f,g,h)         { \
00619         (a)[X] = (b)[X] + (c)*(d)[X] + (e)*(f)[X] + (g)*(h)[X];\
00620         (a)[Y] = (b)[Y] + (c)*(d)[Y] + (e)*(f)[Y] + (g)*(h)[Y];\
00621         (a)[Z] = (b)[Z] + (c)*(d)[Z] + (e)*(f)[Z] + (g)*(h)[Z]; }
00622 
00623 /** @brief Compose vector at `a' of:
00624  *      Vector at `b' plus
00625  *      scalar `c' times vector at `d' plus
00626  *      scalar `e' times vector at `f'
00627  */
00628 #ifdef SHORT_VECTORS
00629 #define VJOIN2(a,b,c,d,e,f)     VJOIN2N(a,b,c,d,e,f,3)
00630 #else
00631 #define VJOIN2(a,b,c,d,e,f)     { \
00632         (a)[X] = (b)[X] + (c) * (d)[X] + (e) * (f)[X];\
00633         (a)[Y] = (b)[Y] + (c) * (d)[Y] + (e) * (f)[Y];\
00634         (a)[Z] = (b)[Z] + (c) * (d)[Z] + (e) * (f)[Z]; }
00635 #endif /* SHORT_VECTORS */
00636 
00637 #define VJOIN2N(a,b,c,d,e,f,n)  \
00638         { register int _vjoin2; \
00639         for(_vjoin2 = 0; _vjoin2 < (n); _vjoin2++) \
00640                 (a)[_vjoin2] = (b)[_vjoin2] + (c) * (d)[_vjoin2] + (e) * (f)[_vjoin2]; \
00641         }
00642 
00643 #ifdef SHORT_VECTORS
00644 #define VJOIN1(a,b,c,d)         VJOIN1N(a,b,c,d,3)
00645 #else
00646 #define VJOIN1(a,b,c,d)         { \
00647         (a)[X] = (b)[X] + (c) * (d)[X];\
00648         (a)[Y] = (b)[Y] + (c) * (d)[Y];\
00649         (a)[Z] = (b)[Z] + (c) * (d)[Z]; }
00650 #endif /* SHORT_VECTORS */
00651 
00652 #define VJOIN1N(a,b,c,d,n) \
00653         { register int _vjoin1; \
00654         for(_vjoin1 = 0; _vjoin1 < (n); _vjoin1++) \
00655                 (a)[_vjoin1] = (b)[_vjoin1] + (c) * (d)[_vjoin1]; \
00656         }
00657 
00658 #define HJOIN1(a,b,c,d) { \
00659                         (a)[X] = (b)[X] + (c) * (d)[X]; \
00660                         (a)[Y] = (b)[Y] + (c) * (d)[Y]; \
00661                         (a)[Z] = (b)[Z] + (c) * (d)[Z]; \
00662                         (a)[W] = (b)[W] + (c) * (d)[W]; }
00663 
00664 #define V2JOIN1(a,b,c,d)        { \
00665                         (a)[X] = (b)[X] + (c) * (d)[X];\
00666                         (a)[Y] = (b)[Y] + (c) * (d)[Y]; }
00667 
00668 /** @brief
00669  *  Blend into vector `a'
00670  *      scalar `b' times vector at `c' plus
00671  *      scalar `d' times vector at `e'
00672  */
00673 #ifdef SHORT_VECTORS
00674 #define VBLEND2(a,b,c,d,e)      VBLEND2N(a,b,c,d,e,3)
00675 #else
00676 #define VBLEND2(a,b,c,d,e)      { \
00677         (a)[X] = (b) * (c)[X] + (d) * (e)[X];\
00678         (a)[Y] = (b) * (c)[Y] + (d) * (e)[Y];\
00679         (a)[Z] = (b) * (c)[Z] + (d) * (e)[Z]; }
00680 #endif /* SHORT_VECTORS */
00681 
00682 #define VBLEND2N(a,b,c,d,e,n)   \
00683         { register int _vblend2; \
00684         for(_vblend2 = 0; _vblend2 < (n); _vblend2++) \
00685                 (a)[_vblend2] = (b) * (c)[_vblend2] + (d) * (e)[_vblend2]; \
00686         }
00687 
00688 /** @brief Return scalar magnitude squared of vector at `a' */
00689 #define MAGSQ(a)        ( (a)[X]*(a)[X] + (a)[Y]*(a)[Y] + (a)[Z]*(a)[Z] )
00690 #define MAG2SQ(a)       ( (a)[X]*(a)[X] + (a)[Y]*(a)[Y] )
00691 
00692 /** @brief Return scalar magnitude of vector at `a' */
00693 #define MAGNITUDE(a)    sqrt( MAGSQ( a ) )
00694 
00695 /** @brief
00696  *  Store cross product of vectors at `b' and `c' in vector at `a'.
00697  *  Note that the "right hand rule" applies:
00698  *  If closing your right hand goes from `b' to `c', then your
00699  *  thumb points in the direction of the cross product.
00700  *
00701  *  If the angle from `b' to `c' goes clockwise, then
00702  *  the result vector points "into" the plane (inward normal).
00703  *  Example:  b=(0,1,0), c=(1,0,0), then bXc=(0,0,-1).
00704  *
00705  *  If the angle from `b' to `c' goes counter-clockwise, then
00706  *  the result vector points "out" of the plane.
00707  *  This outward pointing normal is the BRL convention.
00708  */
00709 #define VCROSS(a,b,c)   { \
00710                         (a)[X] = (b)[Y] * (c)[Z] - (b)[Z] * (c)[Y];\
00711                         (a)[Y] = (b)[Z] * (c)[X] - (b)[X] * (c)[Z];\
00712                         (a)[Z] = (b)[X] * (c)[Y] - (b)[Y] * (c)[X]; }
00713 
00714 /** @brief Compute dot product of vectors at `a' and `b' */
00715 #define VDOT(a,b)       ( (a)[X]*(b)[X] + (a)[Y]*(b)[Y] + (a)[Z]*(b)[Z] )
00716 
00717 #define V2DOT(a,b)      ( (a)[X]*(b)[X] + (a)[Y]*(b)[Y] )
00718 
00719 /** @brief Subtract two points to make a vector, dot with another vector */
00720 #define VSUB2DOT(_pt2, _pt, _vec)       ( \
00721         ((_pt2)[X] - (_pt)[X]) * (_vec)[X] + \
00722         ((_pt2)[Y] - (_pt)[Y]) * (_vec)[Y] + \
00723         ((_pt2)[Z] - (_pt)[Z]) * (_vec)[Z] )
00724 
00725 /** @brief Turn a vector into comma-separated list of elements, for subroutine args */
00726 #define V2ARGS(a)       (a)[X], (a)[Y]
00727 #define V3ARGS(a)       (a)[X], (a)[Y], (a)[Z]
00728 #define V4ARGS(a)       (a)[X], (a)[Y], (a)[Z], (a)[W]
00729 
00730 /** @brief integer clamped versions of the previous arg macros */
00731 #define V2INTCLAMPARGS(a)       INTCLAMP((a)[X]), INTCLAMP((a)[Y])
00732 /** @brief integer clamped versions of the previous arg macros */
00733 #define V3INTCLAMPARGS(a)       INTCLAMP((a)[X]), INTCLAMP((a)[Y]), INTCLAMP((a)[Z])
00734 /** @brief integer clamped versions of the previous arg macros */
00735 #define V4INTCLAMPARGS(a)       INTCLAMP((a)[X]), INTCLAMP((a)[Y]), INTCLAMP((a)[Z]), INTCLAMP((a)[W])
00736 
00737 /** @brief Print vector name and components on stderr */
00738 #define V2PRINT(a,b)    \
00739         (void)fprintf(stderr,"%s (%g, %g)\n", a, V2ARGS(b) );
00740 #define VPRINT(a,b)     \
00741         (void)fprintf(stderr,"%s (%g, %g, %g)\n", a, V3ARGS(b) );
00742 #define HPRINT(a,b)     \
00743         (void)fprintf(stderr,"%s (%g, %g, %g, %g)\n", a, V4ARGS(b) );
00744 
00745 /** @brief integer clamped versions of the previous print macros */
00746 #define V2INTCLAMPPRINT(a,b)    \
00747         (void)fprintf(stderr,"%s (%g, %g)\n", a, V2INTCLAMPARGS(b) );
00748 #define VINTCLAMPPRINT(a,b)     \
00749         (void)fprintf(stderr,"%s (%g, %g, %g)\n", a, V3INTCLAMPARGS(b) );
00750 #define HINTCLAMPPRINT(a,b)     \
00751         (void)fprintf(stderr,"%s (%g, %g, %g, %g)\n", a, V4INTCLAMPARGS(b) );
00752 
00753 #ifdef __cplusplus
00754 #define CPP_V3PRINT( _os, _title, _p )  (_os) << (_title) << "=(" << \
00755         (_p)[X] << ", " << (_p)[Y] << ")\n";
00756 #define CPP_VPRINT( _os, _title, _p )   (_os) << (_title) << "=(" << \
00757         (_p)[X] << ", " << (_p)[Y] << ", " << (_p)[Z] << ")\n";
00758 #define CPP_HPRINT( _os, _title, _p )   (_os) << (_title) << "=(" << \
00759         (_p)[X] << ", " << (_p)[Y] << ", " << (_p)[Z] << "," << (_p)[W]<< ")\n";
00760 #endif
00761 
00762 /**
00763  * if a value is within computation tolerance of an integer, clamp the
00764  * value to that integer.  XXX - should use VDIVIDE_TOL here, but
00765  * cannot yet until floats are replaced universally with fastf_t's
00766  * since their epsilon is considerably less than that of a double.
00767  */
00768 #define INTCLAMP(_a)    ( NEAR_ZERO((_a) - rint(_a), VUNITIZE_TOL) ? rint(_a) : (_a) )
00769 
00770 /** @brief Vector element multiplication.  Really: diagonal matrix X vect */
00771 #ifdef SHORT_VECTORS
00772 #define VELMUL(a,b,c) \
00773         { register int _velmul; \
00774         for(_velmul = 0; _velmul < 3; _velmul++) \
00775                 (a)[_velmul] = (b)[_velmul] * (c)[_velmul]; \
00776         }
00777 #else
00778 #define VELMUL(a,b,c)   { \
00779         (a)[X] = (b)[X] * (c)[X];\
00780         (a)[Y] = (b)[Y] * (c)[Y];\
00781         (a)[Z] = (b)[Z] * (c)[Z]; }
00782 #endif /* SHORT_VECTORS */
00783 
00784 #ifdef SHORT_VECTORS
00785 #define VELMUL3(a,b,c,d) \
00786         { register int _velmul; \
00787         for(_velmul = 0; _velmul < 3; _velmul++) \
00788                 (a)[_velmul] = (b)[_velmul] * (c)[_velmul] * (d)[_velmul]; \
00789         }
00790 #else
00791 #define VELMUL3(a,b,c,d)        { \
00792         (a)[X] = (b)[X] * (c)[X] * (d)[X];\
00793         (a)[Y] = (b)[Y] * (c)[Y] * (d)[Y];\
00794         (a)[Z] = (b)[Z] * (c)[Z] * (d)[Z]; }
00795 #endif /* SHORT_VECTORS */
00796 
00797 /** @brief Similar to VELMUL */
00798 #define VELDIV(a,b,c)   { \
00799         (a)[0] = (b)[0] / (c)[0];\
00800         (a)[1] = (b)[1] / (c)[1];\
00801         (a)[2] = (b)[2] / (c)[2]; }
00802 
00803 /** @brief Given a direction vector, compute the inverses of each element.
00804  * When division by zero would have occured, mark inverse as INFINITY. */
00805 #define VINVDIR( _inv, _dir )   { \
00806         if( (_dir)[X] < -SQRT_SMALL_FASTF || (_dir)[X] > SQRT_SMALL_FASTF )  { \
00807                 (_inv)[X]=1.0/(_dir)[X]; \
00808         } else { \
00809                 (_dir)[X] = 0.0; \
00810                 (_inv)[X] = INFINITY; \
00811         } \
00812         if( (_dir)[Y] < -SQRT_SMALL_FASTF || (_dir)[Y] > SQRT_SMALL_FASTF )  { \
00813                 (_inv)[Y]=1.0/(_dir)[Y]; \
00814         } else { \
00815                 (_dir)[Y] = 0.0; \
00816                 (_inv)[Y] = INFINITY; \
00817         } \
00818         if( (_dir)[Z] < -SQRT_SMALL_FASTF || (_dir)[Z] > SQRT_SMALL_FASTF )  { \
00819                 (_inv)[Z]=1.0/(_dir)[Z]; \
00820         } else { \
00821                 (_dir)[Z] = 0.0; \
00822                 (_inv)[Z] = INFINITY; \
00823         } \
00824     }
00825 
00826 /** @brief Apply the 3x3 part of a mat_t to a 3-tuple.
00827  * This rotates a vector without scaling it (changing its length) 
00828  */
00829 #ifdef SHORT_VECTORS
00830 #define MAT3X3VEC(o,mat,vec) \
00831         { register int _m3x3v; \
00832         for(_m3x3v = 0; _m3x3v < 3; _m3x3v++) \
00833                 (o)[_m3x3v] = (mat)[4*_m3x3v+0]*(vec)[X] + \
00834                           (mat)[4*_m3x3v+1]*(vec)[Y] + \
00835                           (mat)[4*_m3x3v+2]*(vec)[Z]; \
00836         }
00837 #else
00838 #define MAT3X3VEC(o,mat,vec)    { \
00839         (o)[X] = (mat)[X]*(vec)[X]+(mat)[Y]*(vec)[Y] + (mat)[ 2]*(vec)[Z]; \
00840         (o)[Y] = (mat)[4]*(vec)[X]+(mat)[5]*(vec)[Y] + (mat)[ 6]*(vec)[Z]; \
00841         (o)[Z] = (mat)[8]*(vec)[X]+(mat)[9]*(vec)[Y] + (mat)[10]*(vec)[Z]; }
00842 #endif /* SHORT_VECTORS */
00843 
00844 /** @brief Multiply a 3-tuple by the 3x3 part of a mat_t. */
00845 #ifdef SHORT_VECTORS
00846 #define VEC3X3MAT(o,i,m) \
00847         { register int _v3x3m; \
00848         for(_v3x3m = 0; _v3x3m < 3; _v3x3m++) \
00849                 (o)[_v3x3m] = (i)[X]*(m)[_v3x3m] + \
00850                         (i)[Y]*(m)[_v3x3m+4] + \
00851                         (i)[Z]*(m)[_v3x3m+8]; \
00852         }
00853 #else
00854 #define VEC3X3MAT(o,i,m)        { \
00855         (o)[X] = (i)[X]*(m)[X] + (i)[Y]*(m)[4] + (i)[Z]*(m)[8]; \
00856         (o)[Y] = (i)[X]*(m)[1] + (i)[Y]*(m)[5] + (i)[Z]*(m)[9]; \
00857         (o)[Z] = (i)[X]*(m)[2] + (i)[Y]*(m)[6] + (i)[Z]*(m)[10]; }
00858 #endif /* SHORT_VECTORS */
00859 
00860 /** @brief Apply the 3x3 part of a mat_t to a 2-tuple (Z part=0). */
00861 #ifdef SHORT_VECTORS
00862 #define MAT3X2VEC(o,mat,vec) \
00863         { register int _m3x2v; \
00864         for(_m3x2v = 0; _m3x2v < 3; _m3x2v++) \
00865                 (o)[_m3x2v] = (mat)[4*_m3x2v]*(vec)[X] + \
00866                         (mat)[4*_m3x2v+1]*(vec)[Y]; \
00867         }
00868 #else
00869 #define MAT3X2VEC(o,mat,vec)    { \
00870         (o)[X] = (mat)[0]*(vec)[X] + (mat)[Y]*(vec)[Y]; \
00871         (o)[Y] = (mat)[4]*(vec)[X] + (mat)[5]*(vec)[Y]; \
00872         (o)[Z] = (mat)[8]*(vec)[X] + (mat)[9]*(vec)[Y]; }
00873 #endif /* SHORT_VECTORS */
00874 
00875 /** @brief Multiply a 2-tuple (Z=0) by the 3x3 part of a mat_t. */
00876 #ifdef SHORT_VECTORS
00877 #define VEC2X3MAT(o,i,m) \
00878         { register int _v2x3m; \
00879         for(_v2x3m = 0; _v2x3m < 3; _v2x3m++) \
00880                 (o)[_v2x3m] = (i)[X]*(m)[_v2x3m] + (i)[Y]*(m)[2*_v2x3m]; \
00881         }
00882 #else
00883 #define VEC2X3MAT(o,i,m)        { \
00884         (o)[X] = (i)[X]*(m)[0] + (i)[Y]*(m)[4]; \
00885         (o)[Y] = (i)[X]*(m)[1] + (i)[Y]*(m)[5]; \
00886         (o)[Z] = (i)[X]*(m)[2] + (i)[Y]*(m)[6]; }
00887 #endif /* SHORT_VECTORS */
00888 
00889 /** @brief Apply a 4x4 matrix to a 3-tuple which is an absolute Point in space */
00890 #ifdef SHORT_VECTORS
00891 #define MAT4X3PNT(o,m,i) \
00892         { register double _f; \
00893         register int _i_m4x3p, _j_m4x3p; \
00894         _f = 0.0; \
00895         for(_j_m4x3p = 0; _j_m4x3p < 3; _j_m4x3p++)  \
00896                 _f += (m)[_j_m4x3p+12] * (i)[_j_m4x3p]; \
00897         _f = 1.0/(_f + (m)[15]); \
00898         for(_i_m4x3p = 0; _i_m4x3p < 3; _i_m4x3p++) \
00899                 (o)[_i_m4x3p] = 0.0; \
00900         for(_i_m4x3p = 0; _i_m4x3p < 3; _i_m4x3p++)  { \
00901                 for(_j_m4x3p = 0; _j_m4x3p < 3; _j_m4x3p++) \
00902                         (o)[_i_m4x3p] += (m)[_j_m4x3p+4*_i_m4x3p] * (i)[_j_m4x3p]; \
00903         } \
00904         for(_i_m4x3p = 0; _i_m4x3p < 3; _i_m4x3p++)  { \
00905                 (o)[_i_m4x3p] = ((o)[_i_m4x3p] + (m)[4*_i_m4x3p+3]) * _f; \
00906         } }
00907 #else
00908 #define MAT4X3PNT(o,m,i) \
00909         { register double _f; \
00910         _f = 1.0/((m)[12]*(i)[X] + (m)[13]*(i)[Y] + (m)[14]*(i)[Z] + (m)[15]);\
00911         (o)[X]=((m)[0]*(i)[X] + (m)[1]*(i)[Y] + (m)[ 2]*(i)[Z] + (m)[3]) * _f;\
00912         (o)[Y]=((m)[4]*(i)[X] + (m)[5]*(i)[Y] + (m)[ 6]*(i)[Z] + (m)[7]) * _f;\
00913         (o)[Z]=((m)[8]*(i)[X] + (m)[9]*(i)[Y] + (m)[10]*(i)[Z] + (m)[11])* _f;}
00914 #endif /* SHORT_VECTORS */
00915 
00916 /** @brief Multiply an Absolute 3-Point by a full 4x4 matrix. */
00917 #define PNT3X4MAT(o,i,m) \
00918         { register double _f; \
00919         _f = 1.0/((i)[X]*(m)[3] + (i)[Y]*(m)[7] + (i)[Z]*(m)[11] + (m)[15]);\
00920         (o)[X]=((i)[X]*(m)[0] + (i)[Y]*(m)[4] + (i)[Z]*(m)[8] + (m)[12]) * _f;\
00921         (o)[Y]=((i)[X]*(m)[1] + (i)[Y]*(m)[5] + (i)[Z]*(m)[9] + (m)[13]) * _f;\
00922         (o)[Z]=((i)[X]*(m)[2] + (i)[Y]*(m)[6] + (i)[Z]*(m)[10] + (m)[14])* _f;}
00923 
00924 /** @brief Multiply an Absolute hvect_t 4-Point by a full 4x4 matrix. */
00925 #ifdef SHORT_VECTORS
00926 #define MAT4X4PNT(o,m,i) \
00927         { register int _i_m4x4p, _j_m4x4p; \
00928         for(_i_m4x4p = 0; _i_m4x4p < 4; _i_m4x4p++) \
00929                 (o)[_i_m4x4p] = 0.0; \
00930         for(_i_m4x4p = 0; _i_m4x4p < 4; _i_m4x4p++) \
00931                 for(_j_m4x4p = 0; _j_m4x4p < 4; _j_m4x4p++) \
00932                         (o)[_i_m4x4p] += (m)[_j_m4x4p+4*_i_m4x4p] * (i)[_j_m4x4p]; \
00933         }
00934 #else
00935 #define MAT4X4PNT(o,m,i)        { \
00936         (o)[X]=(m)[ 0]*(i)[X] + (m)[ 1]*(i)[Y] + (m)[ 2]*(i)[Z] + (m)[ 3]*(i)[H];\
00937         (o)[Y]=(m)[ 4]*(i)[X] + (m)[ 5]*(i)[Y] + (m)[ 6]*(i)[Z] + (m)[ 7]*(i)[H];\
00938         (o)[Z]=(m)[ 8]*(i)[X] + (m)[ 9]*(i)[Y] + (m)[10]*(i)[Z] + (m)[11]*(i)[H];\
00939         (o)[H]=(m)[12]*(i)[X] + (m)[13]*(i)[Y] + (m)[14]*(i)[Z] + (m)[15]*(i)[H]; }
00940 #endif /* SHORT_VECTORS */
00941 
00942 /** @brief Apply a 4x4 matrix to a 3-tuple which is a relative Vector in space
00943  * This macro can scale the length of the vector if [15] != 1.0 
00944  */
00945 #ifdef SHORT_VECTORS
00946 #define MAT4X3VEC(o,m,i) \
00947         { register double _f; \
00948         register int _i_m4x3v, _j_m4x3v; \
00949         _f = 1.0/((m)[15]); \
00950         for(_i_m4x3v = 0; _i_m4x3v < 3; _i_m4x3v++) \
00951                 (o)[_i_m4x3v] = 0.0; \
00952         for(_i_m4x3v = 0; _i_m4x3v < 3; _i_m4x3v++) { \
00953                 for(_j_m4x3v = 0; _j_m4x3v < 3; _j_m4x3v++) \
00954                         (o)[_i_m4x3v] += (m)[_j_m4x3v+4*_i_m4x3v] * (i)[_j_m4x3v]; \
00955         } \
00956         for(_i_m4x3v = 0; _i_m4x3v < 3; _i_m4x3v++) { \
00957                 (o)[_i_m4x3v] *= _f; \
00958         } }
00959 #else
00960 #define MAT4X3VEC(o,m,i) \
00961         { register double _f;   _f = 1.0/((m)[15]);\
00962         (o)[X] = ((m)[0]*(i)[X] + (m)[1]*(i)[Y] + (m)[ 2]*(i)[Z]) * _f; \
00963         (o)[Y] = ((m)[4]*(i)[X] + (m)[5]*(i)[Y] + (m)[ 6]*(i)[Z]) * _f; \
00964         (o)[Z] = ((m)[8]*(i)[X] + (m)[9]*(i)[Y] + (m)[10]*(i)[Z]) * _f; }
00965 #endif /* SHORT_VECTORS */
00966 
00967 #define MAT4XSCALOR(o,m,i) \
00968         {(o) = (i) / (m)[15];}
00969 
00970 /** @brief Multiply a Relative 3-Vector by most of a 4x4 matrix */
00971 #define VEC3X4MAT(o,i,m) \
00972         { register double _f;   _f = 1.0/((m)[15]); \
00973         (o)[X] = ((i)[X]*(m)[0] + (i)[Y]*(m)[4] + (i)[Z]*(m)[8]) * _f; \
00974         (o)[Y] = ((i)[X]*(m)[1] + (i)[Y]*(m)[5] + (i)[Z]*(m)[9]) * _f; \
00975         (o)[Z] = ((i)[X]*(m)[2] + (i)[Y]*(m)[6] + (i)[Z]*(m)[10]) * _f; }
00976 
00977 /** @brief Multiply a Relative 2-Vector by most of a 4x4 matrix */
00978 #define VEC2X4MAT(o,i,m) \
00979         { register double _f;   _f = 1.0/((m)[15]); \
00980         (o)[X] = ((i)[X]*(m)[0] + (i)[Y]*(m)[4]) * _f; \
00981         (o)[Y] = ((i)[X]*(m)[1] + (i)[Y]*(m)[5]) * _f; \
00982         (o)[Z] = ((i)[X]*(m)[2] + (i)[Y]*(m)[6]) * _f; }
00983 
00984 /** @brief Test a vector for non-unit length */
00985 #define BN_VEC_NON_UNIT_LEN(_vec)       \
00986         (fabs(MAGSQ(_vec)) < 0.0001 || fabs(fabs(MAGSQ(_vec))-1) > 0.0001)
00987 
00988 /** @brief Compare two vectors for EXACT equality.  Use carefully. */
00989 #define VEQUAL(a,b)     ((a)[X]==(b)[X] && (a)[Y]==(b)[Y] && (a)[Z]==(b)[Z])
00990 
00991 /** @brief
00992  *  Compare two vectors for approximate equality,
00993  *  within the specified absolute tolerance.
00994  */
00995 #define VAPPROXEQUAL(a,b,tol)   ( \
00996         NEAR_ZERO( (a)[X]-(b)[X], tol ) && \
00997         NEAR_ZERO( (a)[Y]-(b)[Y], tol ) && \
00998         NEAR_ZERO( (a)[Z]-(b)[Z], tol ) )
00999 
01000 /** @brief Test for all elements of `v' being smaller than `tol' */
01001 #define VNEAR_ZERO(v, tol)      ( \
01002         NEAR_ZERO(v[X],tol) && NEAR_ZERO(v[Y],tol) && NEAR_ZERO(v[Z],tol)  )
01003 
01004 /** @brief Macros to update min and max X,Y,Z values to contain a point */
01005 #define V_MIN(r,s)      if( (s) < (r) ) r = (s)
01006 #define V_MAX(r,s)      if( (s) > (r) ) r = (s)
01007 #define VMIN(r,s)       { V_MIN((r)[X],(s)[X]); V_MIN((r)[Y],(s)[Y]); V_MIN((r)[Z],(s)[Z]); }
01008 #define VMAX(r,s)       { V_MAX((r)[X],(s)[X]); V_MAX((r)[Y],(s)[Y]); V_MAX((r)[Z],(s)[Z]); }
01009 #define VMINMAX( min, max, pt ) { VMIN( (min), (pt) ); VMAX( (max), (pt) ); }
01010 
01011 /** @brief Divide out homogeneous parameter from hvect_t, creating vect_t */
01012 #ifdef SHORT_VECTORS
01013 #define HDIVIDE(a,b)  \
01014         { register int _hdivide; \
01015         for(_hdivide = 0; _hdivide < 3; _hdivide++) \
01016                 (a)[_hdivide] = (b)[_hdivide] / (b)[H]; \
01017         }
01018 #else
01019 #define HDIVIDE(a,b)  { \
01020         (a)[X] = (b)[X] / (b)[H];\
01021         (a)[Y] = (b)[Y] / (b)[H];\
01022         (a)[Z] = (b)[Z] / (b)[H]; }
01023 #endif /* SHORT_VECTORS */
01024 
01025 /** @brief
01026  *  Some 2-D versions of the 3-D macros given above.
01027  *
01028  *  A better naming convention is V2MOVE() rather than VMOVE_2D().
01029  *  XXX These xxx_2D names are slated to go away, use the others.
01030  */
01031 #define VADD2_2D(a,b,c) V2ADD2(a,b,c)
01032 #define VSUB2_2D(a,b,c) V2SUB2(a,b,c)
01033 #define MAGSQ_2D(a)     MAG2SQ(a)
01034 #define VDOT_2D(a,b)    V2DOT(a,b)
01035 #define VMOVE_2D(a,b)   V2MOVE(a,b)
01036 #define VSCALE_2D(a,b,c)        V2SCALE(a,b,c)
01037 #define VJOIN1_2D(a,b,c,d)      V2JOIN1(a,b,c,d)
01038 
01039 /** @brief
01040  *  Quaternion math definitions.
01041  *
01042  *  Note that the W component will be put in the last [3] place
01043  *  rather than the first [0] place,
01044  *  so that the X, Y, Z elements will be compatible with vectors.
01045  *  Only QUAT_FROM_VROT macros depend on component locations, however.
01046  *
01047  *  @author Phillip Dykstra, 26 Sep 1985.
01048  *  @author Lee A. Butler, 14 March 1996.
01049  */
01050 
01051 /** @brief Create Quaternion from Vector and Rotation about vector.
01052  *
01053  * To produce a quaternion representing a rotation by PI radians about X-axis:
01054  *
01055  *      VSET(axis, 1, 0, 0);
01056  *      QUAT_FROM_VROT( quat, M_PI, axis);
01057  *              or
01058  *      QUAT_FROM_ROT( quat, M_PI, 1.0, 0.0, 0.0, 0.0 );
01059  *
01060  *  Alternatively, in degrees:
01061  *      QUAT_FROM_ROT_DEG( quat, 180.0, 1.0, 0.0, 0.0, 0.0 );
01062  *
01063  */
01064 #define QUAT_FROM_ROT(q, r, x, y, z){ \
01065         register fastf_t _rot = (r) * 0.5; \
01066         QSET(q, x, y, z, cos(_rot)); \
01067         VUNITIZE(q); \
01068         _rot = sin(_rot); /* _rot is really just a temp variable now */ \
01069         VSCALE(q, q, _rot ); }
01070 
01071 #define QUAT_FROM_VROT(q, r, v) { \
01072         register fastf_t _rot = (r) * 0.5; \
01073         VMOVE(q, v); \
01074         VUNITIZE(q); \
01075         (q)[W] = cos(_rot); \
01076         _rot = sin(_rot); /* _rot is really just a temp variable now */ \
01077         VSCALE(q, q, _rot ); }
01078 
01079 #define QUAT_FROM_VROT_DEG(q, r, v) \
01080         QUAT_FROM_VROT(q, ((r)*(M_PI/180.0)), v)
01081 
01082 #define QUAT_FROM_ROT_DEG(q, r, x, y, z) \
01083         QUAT_FROM_ROT(q, ((r)*(M_PI/180.0)), x, y, z)
01084 
01085 
01086 
01087 /** @brief Set quaternion at `a' to have coordinates `b', `c', `d', `e' */
01088 #define QSET(a,b,c,d,e) { \
01089                         (a)[X] = (b);\
01090                         (a)[Y] = (c);\
01091                         (a)[Z] = (d);\
01092                         (a)[W] = (e); }
01093 
01094 /** @brief Transfer quaternion at `b' to quaternion at `a' */
01095 #define QMOVE(a,b)      { \
01096                         (a)[X] = (b)[X];\
01097                         (a)[Y] = (b)[Y];\
01098                         (a)[Z] = (b)[Z];\
01099                         (a)[W] = (b)[W]; }
01100 
01101 /** @brief Add quaternions at `b' and `c', store result at `a' */
01102 #define QADD2(a,b,c)    { \
01103                         (a)[X] = (b)[X] + (c)[X];\
01104                         (a)[Y] = (b)[Y] + (c)[Y];\
01105                         (a)[Z] = (b)[Z] + (c)[Z];\
01106                         (a)[W] = (b)[W] + (c)[W]; }
01107 
01108 /** @brief Subtract quaternion at `c' from quaternion at `b', store result at `a' */
01109 #define QSUB2(a,b,c)    { \
01110                         (a)[X] = (b)[X] - (c)[X];\
01111                         (a)[Y] = (b)[Y] - (c)[Y];\
01112                         (a)[Z] = (b)[Z] - (c)[Z];\
01113                         (a)[W] = (b)[W] - (c)[W]; }
01114 
01115 /** @brief Scale quaternion at `b' by scalar `c', store result at `a' */
01116 #define QSCALE(a,b,c)   { \
01117                         (a)[X] = (b)[X] * (c);\
01118                         (a)[Y] = (b)[Y] * (c);\
01119                         (a)[Z] = (b)[Z] * (c);\
01120                         (a)[W] = (b)[W] * (c); }
01121 
01122 /** @brief Normalize quaternion 'a' to be a unit quaternion */
01123 #define QUNITIZE(a)     {register double _f; _f = QMAGNITUDE(a); \
01124                         if( _f < VDIVIDE_TOL ) _f = 0.0; else _f = 1.0/_f; \
01125                         (a)[X] *= _f; (a)[Y] *= _f; (a)[Z] *= _f; (a)[W] *= _f; }
01126 
01127 /** @brief Return scalar magnitude squared of quaternion at `a' */
01128 #define QMAGSQ(a)       ( (a)[X]*(a)[X] + (a)[Y]*(a)[Y] \
01129                         + (a)[Z]*(a)[Z] + (a)[W]*(a)[W] )
01130 
01131 /** @brief Return scalar magnitude of quaternion at `a' */
01132 #define QMAGNITUDE(a)   sqrt( QMAGSQ( a ) )
01133 
01134 /** @brief Compute dot product of quaternions at `a' and `b' */
01135 #define QDOT(a,b)       ( (a)[X]*(b)[X] + (a)[Y]*(b)[Y] \
01136                         + (a)[Z]*(b)[Z] + (a)[W]*(b)[W] )
01137 
01138 /** @brief
01139  *  Compute quaternion product a = b * c
01140  *      a[W] = b[W]*c[W] - VDOT(b,c);
01141         VCROSS( temp, b, c );
01142  *      VJOIN2( a, temp, b[W], c, c[W], b );
01143  */
01144 #define QMUL(a,b,c)     { \
01145     (a)[W] = (b)[W]*(c)[W] - (b)[X]*(c)[X] - (b)[Y]*(c)[Y] - (b)[Z]*(c)[Z]; \
01146     (a)[X] = (b)[W]*(c)[X] + (b)[X]*(c)[W] + (b)[Y]*(c)[Z] - (b)[Z]*(c)[Y]; \
01147     (a)[Y] = (b)[W]*(c)[Y] + (b)[Y]*(c)[W] + (b)[Z]*(c)[X] - (b)[X]*(c)[Z]; \
01148     (a)[Z] = (b)[W]*(c)[Z] + (b)[Z]*(c)[W] + (b)[X]*(c)[Y] - (b)[Y]*(c)[X]; }
01149 
01150 /** @brief Conjugate quaternion */
01151 #define QCONJUGATE(a,b) { \
01152         (a)[X] = -(b)[X]; \
01153         (a)[Y] = -(b)[Y]; \
01154         (a)[Z] = -(b)[Z]; \
01155         (a)[W] =  (b)[W]; }
01156 
01157 /** @brief Multiplicative inverse quaternion */
01158 #define QINVERSE(a,b)   { register double _f = QMAGSQ(b); \
01159         if( _f < VDIVIDE_TOL ) _f = 0.0; else _f = 1.0/_f; \
01160         (a)[X] = -(b)[X] * _f; \
01161         (a)[Y] = -(b)[Y] * _f; \
01162         (a)[Z] = -(b)[Z] * _f; \
01163         (a)[W] =  (b)[W] * _f; }
01164 
01165 /** @brief
01166  *  Blend into quaternion `a'
01167  *      scalar `b' times quaternion at `c' plus
01168  *      scalar `d' times quaternion at `e'
01169  */
01170 #ifdef SHORT_VECTORS
01171 #define QBLEND2(a,b,c,d,e)      VBLEND2N(a,b,c,d,e,4)
01172 #else
01173 #define QBLEND2(a,b,c,d,e)      { \
01174         (a)[X] = (b) * (c)[X] + (d) * (e)[X];\
01175         (a)[Y] = (b) * (c)[Y] + (d) * (e)[Y];\
01176         (a)[Z] = (b) * (c)[Z] + (d) * (e)[Z];\
01177         (a)[W] = (b) * (c)[W] + (d) * (e)[W]; }
01178 #endif /* SHORT_VECTORS */
01179 
01180 /** @brief
01181  *  Macros for dealing with 3-D "extents" represented as axis-aligned
01182  *  right parallelpipeds (RPPs).
01183  *  This is stored as two points:  a min point, and a max point.
01184  *  RPP 1 is defined by lo1, hi1, RPP 2 by lo2, hi2.
01185  */
01186 
01187 /** @brief Compare two extents represented as RPPs. If they are disjoint, return true */
01188 #define V3RPP_DISJOINT(_l1, _h1, _l2, _h2) \
01189       ( (_l1)[X] > (_h2)[X] || (_l1)[Y] > (_h2)[Y] || (_l1)[Z] > (_h2)[Z] || \
01190         (_l2)[X] > (_h1)[X] || (_l2)[Y] > (_h1)[Y] || (_l2)[Z] > (_h1)[Z] )
01191 
01192 /** @brief Compare two extents represented as RPPs. If they overlap, return true */
01193 #define V3RPP_OVERLAP(_l1, _h1, _l2, _h2) \
01194     (! ((_l1)[X] > (_h2)[X] || (_l1)[Y] > (_h2)[Y] || (_l1)[Z] > (_h2)[Z] || \
01195         (_l2)[X] > (_h1)[X] || (_l2)[Y] > (_h1)[Y] || (_l2)[Z] > (_h1)[Z]) )
01196 
01197 /** @brief If two extents overlap within distance tolerance, return true. */
01198 #define V3RPP_OVERLAP_TOL(_l1, _h1, _l2, _h2, _t) \
01199     (! ((_l1)[X] > (_h2)[X] + (_t)->dist || \
01200         (_l1)[Y] > (_h2)[Y] + (_t)->dist || \
01201         (_l1)[Z] > (_h2)[Z] + (_t)->dist || \
01202         (_l2)[X] > (_h1)[X] + (_t)->dist || \
01203         (_l2)[Y] > (_h1)[Y] + (_t)->dist || \
01204         (_l2)[Z] > (_h1)[Z] + (_t)->dist ) )
01205 
01206 /** @brief Is the point within or on the boundary of the RPP? */
01207 #define V3PT_IN_RPP(_pt, _lo, _hi)      ( \
01208         (_pt)[X] >= (_lo)[X] && (_pt)[X] <= (_hi)[X] && \
01209         (_pt)[Y] >= (_lo)[Y] && (_pt)[Y] <= (_hi)[Y] && \
01210         (_pt)[Z] >= (_lo)[Z] && (_pt)[Z] <= (_hi)[Z]  )
01211 
01212 /** @brief Within the distance tolerance, is the point within the RPP? */
01213 #define V3PT_IN_RPP_TOL(_pt, _lo, _hi, _t)      ( \
01214         (_pt)[X] >= (_lo)[X]-(_t)->dist && (_pt)[X] <= (_hi)[X]+(_t)->dist && \
01215         (_pt)[Y] >= (_lo)[Y]-(_t)->dist && (_pt)[Y] <= (_hi)[Y]+(_t)->dist && \
01216         (_pt)[Z] >= (_lo)[Z]-(_t)->dist && (_pt)[Z] <= (_hi)[Z]+(_t)->dist  )
01217 
01218 /** @brief
01219  * Determine if one bounding box is within another.
01220  * Also returns true if the boxes are the same.
01221  */
01222 #define V3RPP1_IN_RPP2( _lo1 , _hi1 , _lo2 , _hi2 )     ( \
01223         (_lo1)[X] >= (_lo2)[X] && (_hi1)[X] <= (_hi2)[X] && \
01224         (_lo1)[Y] >= (_lo2)[Y] && (_hi1)[Y] <= (_hi2)[Y] && \
01225         (_lo1)[Z] >= (_lo2)[Z] && (_hi1)[Z] <= (_hi2)[Z] )
01226 
01227 __END_DECLS
01228 
01229 #endif /* VMATH_H */
01230 /*@}*/
01231 /*
01232  * Local Variables:
01233  * mode: C
01234  * tab-width: 8
01235  * c-basic-offset: 4
01236  * indent-tabs-mode: t
01237  * End:
01238  * ex: shiftwidth=4 tabstop=8
01239  */
01240 

Generated on Mon Sep 18 01:24:47 2006 for BRL-CAD by  doxygen 1.4.6