Browse Source

*** empty log message ***

David Rose 25 years ago
parent
commit
707fed7025
100 changed files with 8709 additions and 0 deletions
  1. 77 0
      panda/src/linmath/Sources.pp
  2. 49 0
      panda/src/linmath/cast_to_double.I
  3. 32 0
      panda/src/linmath/cast_to_double.h
  4. 49 0
      panda/src/linmath/cast_to_float.I
  5. 32 0
      panda/src/linmath/cast_to_float.h
  6. 106 0
      panda/src/linmath/cmath.I
  7. 40 0
      panda/src/linmath/cmath.h
  8. 17 0
      panda/src/linmath/compose_matrix.cxx
  9. 34 0
      panda/src/linmath/compose_matrix.h
  10. 104 0
      panda/src/linmath/compose_matrix_src.I
  11. 57 0
      panda/src/linmath/config_linmath.cxx
  12. 14 0
      panda/src/linmath/config_linmath.h
  13. 96 0
      panda/src/linmath/coordinateSystem.cxx
  14. 46 0
      panda/src/linmath/coordinateSystem.h
  15. 19 0
      panda/src/linmath/deg_2_rad.h
  16. 45 0
      panda/src/linmath/ioPtaDatagramLinMath.I
  17. 11 0
      panda/src/linmath/ioPtaDatagramLinMath.cxx
  18. 62 0
      panda/src/linmath/ioPtaDatagramLinMath.h
  19. 25 0
      panda/src/linmath/lmat_ops.h
  20. 13 0
      panda/src/linmath/lmatrix.cxx
  21. 28 0
      panda/src/linmath/lmatrix.h
  22. 15 0
      panda/src/linmath/lmatrix3.cxx
  23. 28 0
      panda/src/linmath/lmatrix3.h
  24. 892 0
      panda/src/linmath/lmatrix3_src.I
  25. 15 0
      panda/src/linmath/lmatrix4.cxx
  26. 30 0
      panda/src/linmath/lmatrix4.h
  27. 1107 0
      panda/src/linmath/lmatrix4_src.I
  28. 13 0
      panda/src/linmath/lorientation.cxx
  29. 19 0
      panda/src/linmath/lorientation.h
  30. 93 0
      panda/src/linmath/lorientation_src.I
  31. 13 0
      panda/src/linmath/lpoint2.cxx
  32. 21 0
      panda/src/linmath/lpoint2.h
  33. 177 0
      panda/src/linmath/lpoint2_src.I
  34. 13 0
      panda/src/linmath/lpoint3.cxx
  35. 22 0
      panda/src/linmath/lpoint3.h
  36. 224 0
      panda/src/linmath/lpoint3_src.I
  37. 13 0
      panda/src/linmath/lpoint4.cxx
  38. 20 0
      panda/src/linmath/lpoint4.h
  39. 197 0
      panda/src/linmath/lpoint4_src.I
  40. 13 0
      panda/src/linmath/lquaternion.cxx
  41. 25 0
      panda/src/linmath/lquaternion.h
  42. 293 0
      panda/src/linmath/lquaternion_src.I
  43. 13 0
      panda/src/linmath/lrotation.cxx
  44. 21 0
      panda/src/linmath/lrotation.h
  45. 105 0
      panda/src/linmath/lrotation_src.I
  46. 4 0
      panda/src/linmath/luse.I
  47. 68 0
      panda/src/linmath/luse.N
  48. 6 0
      panda/src/linmath/luse.cxx
  49. 87 0
      panda/src/linmath/luse.h
  50. 21 0
      panda/src/linmath/lvec2_ops.h
  51. 22 0
      panda/src/linmath/lvec3_ops.h
  52. 22 0
      panda/src/linmath/lvec4_ops.h
  53. 13 0
      panda/src/linmath/lvecBase2.cxx
  54. 26 0
      panda/src/linmath/lvecBase2.h
  55. 521 0
      panda/src/linmath/lvecBase2_src.I
  56. 13 0
      panda/src/linmath/lvecBase3.cxx
  57. 26 0
      panda/src/linmath/lvecBase3.h
  58. 590 0
      panda/src/linmath/lvecBase3_src.I
  59. 13 0
      panda/src/linmath/lvecBase4.cxx
  60. 27 0
      panda/src/linmath/lvecBase4.h
  61. 618 0
      panda/src/linmath/lvecBase4_src.I
  62. 13 0
      panda/src/linmath/lvector2.cxx
  63. 20 0
      panda/src/linmath/lvector2.h
  64. 209 0
      panda/src/linmath/lvector2_src.I
  65. 13 0
      panda/src/linmath/lvector3.cxx
  66. 22 0
      panda/src/linmath/lvector3.h
  67. 345 0
      panda/src/linmath/lvector3_src.I
  68. 13 0
      panda/src/linmath/lvector4.cxx
  69. 20 0
      panda/src/linmath/lvector4.h
  70. 230 0
      panda/src/linmath/lvector4_src.I
  71. 10 0
      panda/src/linmath/mathNumbers.cxx
  72. 17 0
      panda/src/linmath/mathNumbers.h
  73. 58 0
      panda/src/linmath/nearly_zero.h
  74. 11 0
      panda/src/linmath/pta_Colorf.cxx
  75. 37 0
      panda/src/linmath/pta_Colorf.h
  76. 11 0
      panda/src/linmath/pta_Normalf.cxx
  77. 37 0
      panda/src/linmath/pta_Normalf.h
  78. 11 0
      panda/src/linmath/pta_TexCoordf.cxx
  79. 37 0
      panda/src/linmath/pta_TexCoordf.h
  80. 11 0
      panda/src/linmath/pta_Vertexf.cxx
  81. 37 0
      panda/src/linmath/pta_Vertexf.h
  82. 147 0
      panda/src/linmath/test_math.cxx
  83. 11 0
      panda/src/linmath/vector_Colorf.cxx
  84. 32 0
      panda/src/linmath/vector_Colorf.h
  85. 11 0
      panda/src/linmath/vector_LPoint2f.cxx
  86. 32 0
      panda/src/linmath/vector_LPoint2f.h
  87. 11 0
      panda/src/linmath/vector_LVecBase3f.cxx
  88. 32 0
      panda/src/linmath/vector_LVecBase3f.h
  89. 11 0
      panda/src/linmath/vector_Normalf.cxx
  90. 32 0
      panda/src/linmath/vector_Normalf.h
  91. 20 0
      panda/src/linmath/vector_TexCoordf.h
  92. 11 0
      panda/src/linmath/vector_Vertexf.cxx
  93. 32 0
      panda/src/linmath/vector_Vertexf.h
  94. 47 0
      panda/src/mathutil/Sources.pp
  95. 30 0
      panda/src/mathutil/boundingHexahedron.I
  96. 336 0
      panda/src/mathutil/boundingHexahedron.cxx
  97. 109 0
      panda/src/mathutil/boundingHexahedron.h
  98. 33 0
      panda/src/mathutil/boundingLine.I
  99. 114 0
      panda/src/mathutil/boundingLine.cxx
  100. 81 0
      panda/src/mathutil/boundingLine.h

+ 77 - 0
panda/src/linmath/Sources.pp

@@ -0,0 +1,77 @@
+#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
+                   dtoolutil:c dtoolbase:c dtool:m
+
+#begin lib_target
+  #define TARGET linmath
+  #define LOCAL_LIBS \
+    putil
+
+  #define SOURCES \
+    cmath.I cmath.h compose_matrix.cxx compose_matrix.h  \
+    compose_matrix_src.I compose_matrix_src.h config_linmath.cxx \
+    config_linmath.h coordinateSystem.cxx coordinateSystem.h \
+    deg_2_rad.h ioPtaDatagramLinMath.I ioPtaDatagramLinMath.cxx \
+    ioPtaDatagramLinMath.h lcast_to.h lcast_to_src.h lcast_to_src.I \
+    lmatrix.cxx lmatrix.h lmatrix3.cxx lmatrix3.h lmatrix3_src.I \
+    lmatrix3_src.h lmatrix4.cxx lmatrix4.h lmatrix4_src.I \
+    lmatrix4_src.h lorientation.cxx lorientation.h lorientation_src.I \
+    lorientation_src.h lpoint2.cxx lpoint2.h lpoint2_src.I \
+    lpoint2_src.h lpoint3.cxx lpoint3.h lpoint3_src.I lpoint3_src.h \
+    lpoint4.cxx lpoint4.h lpoint4_src.I lpoint4_src.h lquaternion.cxx \
+    lquaternion.h lquaternion_src.I lquaternion_src.h lrotation.cxx \
+    lrotation.h lrotation_src.I lrotation_src.h luse.I luse.N luse.cxx \
+    luse.h lvec2_ops.h lvec2_ops_src.I lvec2_ops_src.h lvec3_ops.h \
+    lvec3_ops_src.I lvec3_ops_src.h lvec4_ops.h lvec4_ops_src.I \
+    lvec4_ops_src.h lvecBase2.cxx lvecBase2.h lvecBase2_src.I \
+    lvecBase2_src.h lvecBase3.cxx lvecBase3.h lvecBase3_src.I \
+    lvecBase3_src.h lvecBase4.cxx lvecBase4.h lvecBase4_src.I \
+    lvecBase4_src.h lvector2.cxx lvector2.h lvector2_src.I \
+    lvector2_src.h lvector3.cxx lvector3.h lvector3_src.I \
+    lvector3_src.h lvector4.cxx lvector4.h lvector4_src.I \
+    lvector4_src.h mathNumbers.cxx mathNumbers.h nearly_zero.h \
+    pta_Colorf.cxx pta_Colorf.h pta_Normalf.cxx pta_Normalf.h \
+    pta_TexCoordf.cxx pta_TexCoordf.h pta_Vertexf.cxx pta_Vertexf.h \
+    vector_Colorf.cxx vector_Colorf.h vector_LPoint2f.cxx \
+    vector_LPoint2f.h vector_LVecBase3f.cxx vector_LVecBase3f.h \
+    vector_Normalf.cxx vector_Normalf.h vector_Vertexf.cxx \
+    vector_Vertexf.h
+
+  #define INSTALL_HEADERS \
+    cmath.I cmath.h compose_matrix.h compose_matrix_src.I \
+    compose_matrix_src.h config_linmath.h coordinateSystem.h \
+    dbl2fltnames.h dblnames.h deg_2_rad.h \
+    flt2dblnames.h fltnames.h ioPtaDatagramLinMath.I \
+    ioPtaDatagramLinMath.h lcast_to.h lcast_to_src.I lcast_to_src.h \
+    lmat_ops.h lmat_ops_src.I lmat_ops_src.h lmatrix.h lmatrix3.h \
+    lmatrix3_src.I lmatrix3_src.h lmatrix4.h lmatrix4_src.I \
+    lmatrix4_src.h lorientation.h lorientation_src.I \
+    lorientation_src.h lpoint2.h lpoint2_src.I lpoint2_src.h lpoint3.h \
+    lpoint3_src.I lpoint3_src.h lpoint4.h lpoint4_src.I lpoint4_src.h \
+    lquaternion.h lquaternion_src.I lquaternion_src.h lrotation.h \
+    lrotation_src.I lrotation_src.h luse.I luse.h lvec2_ops.h \
+    lvec2_ops_src.I lvec2_ops_src.h lvec3_ops.h lvec3_ops_src.I \
+    lvec3_ops_src.h lvec4_ops.h lvec4_ops_src.I lvec4_ops_src.h \
+    lvecBase2.h lvecBase2_src.I lvecBase2_src.h lvecBase3.h \
+    lvecBase3_src.I lvecBase3_src.h lvecBase4.h lvecBase4_src.I \
+    lvecBase4_src.h lvector2.h lvector2_src.I lvector2_src.h \
+    lvector3.h lvector3_src.I lvector3_src.h lvector4.h lvector4_src.I \
+    lvector4_src.h mathNumbers.h nearly_zero.h pta_Colorf.h \
+    pta_Normalf.h pta_TexCoordf.h pta_Vertexf.h vector_Colorf.h \
+    vector_LPoint2f.h vector_LVecBase3f.h vector_Normalf.h \
+    vector_TexCoordf.h vector_Vertexf.h
+
+  #define IGATESCAN all
+
+#end lib_target
+
+#begin test_bin_target
+  #define TARGET test_math
+  #define LOCAL_LIBS \
+    linmath
+  #define OTHER_LIBS $[OTHER_LIBS] pystub
+
+  #define SOURCES \
+    test_math.cxx
+
+#end test_bin_target
+

+ 49 - 0
panda/src/linmath/cast_to_double.I

@@ -0,0 +1,49 @@
+// Filename: cast_to_double.I
+// Created by:  drose (24May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+INLINE LVecBase2d cast_to_double(const LVecBase2f &source) {
+  return LCAST(double, source);
+}
+
+INLINE LVecBase3d cast_to_double(const LVecBase3f &source) {
+  return LCAST(double, source);
+}
+
+INLINE LVecBase4d cast_to_double(const LVecBase4f &source) {
+  return LCAST(double, source);
+}
+
+INLINE LVector2d cast_to_double(const LVector2f &source) {
+  return LCAST(double, source);
+}
+
+INLINE LVector3d cast_to_double(const LVector3f &source) {
+  return LCAST(double, source);
+}
+
+INLINE LVector4d cast_to_double(const LVector4f &source) {
+  return LCAST(double, source);
+}
+
+INLINE LPoint2d cast_to_double(const LPoint2f &source) {
+  return LCAST(double, source);
+}
+
+INLINE LPoint3d cast_to_double(const LPoint3f &source) {
+  return LCAST(double, source);
+}
+
+INLINE LPoint4d cast_to_double(const LPoint4f &source) {
+  return LCAST(double, source);
+}
+
+INLINE LMatrix3d cast_to_double(const LMatrix3f &source) {
+  return LCAST(double, source);
+}
+
+INLINE LMatrix4d cast_to_double(const LMatrix4f &source) {
+  return LCAST(double, source);
+}
+

+ 32 - 0
panda/src/linmath/cast_to_double.h

@@ -0,0 +1,32 @@
+// Filename: cast_to_double.h
+// Created by:  drose (24May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef CAST_TO_DOUBLE_H
+#define CAST_TO_DOUBLE_H
+
+#include "luse.h"
+
+// The functions in this file are primarily for the benefit of a
+// higher-level language that can't take advantage of the LCAST macro.
+// These are a number of functions that convert our various math
+// objects between floats and doubles.
+
+INLINE LVecBase2d cast_to_double(const LVecBase2f &source);
+INLINE LVecBase3d cast_to_double(const LVecBase3f &source);
+INLINE LVecBase4d cast_to_double(const LVecBase4f &source);
+INLINE LVector2d cast_to_double(const LVector2f &source);
+INLINE LVector3d cast_to_double(const LVector3f &source);
+INLINE LVector4d cast_to_double(const LVector4f &source);
+INLINE LPoint2d cast_to_double(const LPoint2f &source);
+INLINE LPoint3d cast_to_double(const LPoint3f &source);
+INLINE LPoint4d cast_to_double(const LPoint4f &source);
+INLINE LMatrix3d cast_to_double(const LMatrix3f &source);
+INLINE LMatrix4d cast_to_double(const LMatrix4f &source);
+
+#include "cast_to_double.I"
+
+#endif
+
+

+ 49 - 0
panda/src/linmath/cast_to_float.I

@@ -0,0 +1,49 @@
+// Filename: cast_to_float.I
+// Created by:  drose (24May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+INLINE LVecBase2f cast_to_float(const LVecBase2d &source) {
+  return LCAST(float, source);
+}
+
+INLINE LVecBase3f cast_to_float(const LVecBase3d &source) {
+  return LCAST(float, source);
+}
+
+INLINE LVecBase4f cast_to_float(const LVecBase4d &source) {
+  return LCAST(float, source);
+}
+
+INLINE LVector2f cast_to_float(const LVector2d &source) {
+  return LCAST(float, source);
+}
+
+INLINE LVector3f cast_to_float(const LVector3d &source) {
+  return LCAST(float, source);
+}
+
+INLINE LVector4f cast_to_float(const LVector4d &source) {
+  return LCAST(float, source);
+}
+
+INLINE LPoint2f cast_to_float(const LPoint2d &source) {
+  return LCAST(float, source);
+}
+
+INLINE LPoint3f cast_to_float(const LPoint3d &source) {
+  return LCAST(float, source);
+}
+
+INLINE LPoint4f cast_to_float(const LPoint4d &source) {
+  return LCAST(float, source);
+}
+
+INLINE LMatrix3f cast_to_float(const LMatrix3d &source) {
+  return LCAST(float, source);
+}
+
+INLINE LMatrix4f cast_to_float(const LMatrix4d &source) {
+  return LCAST(float, source);
+}
+

+ 32 - 0
panda/src/linmath/cast_to_float.h

@@ -0,0 +1,32 @@
+// Filename: cast_to_float.h
+// Created by:  drose (24May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef CAST_TO_FLOAT_H
+#define CAST_TO_FLOAT_H
+
+#include "luse.h"
+
+// The functions in this file are primarily for the benefit of a
+// higher-level language that can't take advantage of the LCAST macro.
+// These are a number of functions that convert our various math
+// objects between floats and doubles.
+
+INLINE LVecBase2f cast_to_float(const LVecBase2d &source);
+INLINE LVecBase3f cast_to_float(const LVecBase3d &source);
+INLINE LVecBase4f cast_to_float(const LVecBase4d &source);
+INLINE LVector2f cast_to_float(const LVector2d &source);
+INLINE LVector3f cast_to_float(const LVector3d &source);
+INLINE LVector4f cast_to_float(const LVector4d &source);
+INLINE LPoint2f cast_to_float(const LPoint2d &source);
+INLINE LPoint3f cast_to_float(const LPoint3d &source);
+INLINE LPoint4f cast_to_float(const LPoint4d &source);
+INLINE LMatrix3f cast_to_float(const LMatrix3d &source);
+INLINE LMatrix4f cast_to_float(const LMatrix4d &source);
+
+#include "cast_to_float.I"
+
+#endif
+
+

+ 106 - 0
panda/src/linmath/cmath.I

@@ -0,0 +1,106 @@
+// Filename: cmath.I
+// Created by:  drose (19May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+//Windows has isnan in a different place and with a different name
+//than everyone else.  Sheesh
+#ifdef _WIN32
+#include <float.h>
+#endif
+
+INLINE float csqrt(float v) {
+  return sqrtf(v);
+}
+
+INLINE float csin(float v) {
+  return sinf(v);
+}
+
+INLINE float ccos(float v) {
+  return cosf(v);
+}
+
+INLINE void
+sincosf(float v, float *pSinResult, float *pCosResult) {
+
+// MS VC defines _M_IX86 for x86.  gcc should define _X86_
+#if defined(_M_IX86) || defined(_X86_)
+//#define fsincos_opcode __asm _emit 0xd9 __asm _emit 0xfb
+    __asm {
+        mov eax, pSinResult
+        mov edx, pCosResult
+        fld v
+        fsincos
+        fstp DWORD ptr [edx]
+        fstp DWORD ptr [eax]
+    }
+#else //!_X86_
+    *pSinResult = sinf(v);
+    *pCosResult = cosf(v);
+#endif //!_X86_
+}
+
+INLINE void
+sincos(double v, double *pSinResult, double *pCosResult) {
+#if defined(_M_IX86) || defined(_X86_)
+//#define fsincos_opcode __asm _emit 0xd9 __asm _emit 0xfb
+    __asm {
+        mov eax, pSinResult
+        mov edx, pCosResult
+        fld v
+        fsincos
+        fstp QWORD ptr [edx]
+        fstp QWORD ptr [eax]
+    }
+#else //!_X86_
+    *pSinResult = sin(v);
+    *pCosResult = cos(v);
+#endif //!_X86_
+}
+
+INLINE void csincos(float v,float *pSinResult, float *pCosResult) {
+  sincosf(v,pSinResult,pCosResult);
+}
+
+INLINE void csincos(double v,double *pSinResult, double *pCosResult) {
+  sincos(v,pSinResult,pCosResult);
+}
+
+INLINE float cabs(float v) {
+  return fabs(v);
+}
+
+INLINE float catan2(float y, float x) {
+  return atan2f(y, x);
+}
+
+INLINE double csqrt(double v) {
+  return sqrt(v);
+}
+
+INLINE double csin(double v) {
+  return sin(v);
+}
+
+INLINE double ccos(double v) {
+  return cos(v);
+}
+
+INLINE double cabs(double v) {
+  return fabs(v);
+}
+
+INLINE double catan2(double y, double x) {
+  return atan2(y, x);
+}
+
+INLINE bool cnan(double v) {
+#ifndef _WIN32
+  return (isnan(v) != 0);
+#else
+  return (_isnan(v) != 0);
+#endif
+}
+
+

+ 40 - 0
panda/src/linmath/cmath.h

@@ -0,0 +1,40 @@
+// Filename: cmath.h
+// Created by:  drose (19May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef CMATH_H
+#define CMATH_H
+
+#include <pandabase.h>
+
+#include <math.h>
+
+// This file declares a number of C++-style overloading wrappers
+// around the standard math library functions, so we can use
+// overloading to differentiate on type instead of having to know
+// explicitly whether we need to call, for instance, sqrtf() or
+// sqrt().
+
+INLINE float csqrt(float v);
+INLINE float csin(float v);
+INLINE float ccos(float v);
+INLINE void  csincos(float v, float *pSinResult, float *pCosResult);  // does both at once (faster on x86)
+INLINE float cabs(float v);
+INLINE float catan2(float y, float x);
+
+INLINE double csqrt(double v);
+INLINE double csin(double v);
+INLINE double ccos(double v);
+INLINE double cabs(double v);
+INLINE double catan2(double y, double x);
+INLINE void   csincos(double v, double *pSinResult, double *pCosResult);  // does both at once (faster on x86)
+
+// Returns true if the number is nan, false if it's a genuine number
+// or infinity.
+INLINE bool cnan(double v);
+
+#include "cmath.I"
+
+#endif
+

+ 17 - 0
panda/src/linmath/compose_matrix.cxx

@@ -0,0 +1,17 @@
+// Filename: compose_matrix.cxx
+// Created by:  drose (27Jan99)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "deg_2_rad.h"
+#include "config_linmath.h"
+#include "compose_matrix.h"
+
+#include "fltnames.h"
+#include "compose_matrix_src.cxx"
+
+#include "dblnames.h"
+#include "compose_matrix_src.cxx"
+
+
+

+ 34 - 0
panda/src/linmath/compose_matrix.h

@@ -0,0 +1,34 @@
+// Filename: compose_matrix.h
+// Created by:  drose (27Jan99)
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef COMPOSE_MATRIX_H
+#define COMPOSE_MATRIX_H
+
+////////////////////////////////////////////////////////////////////
+//
+// compose_matrix(), decompose_matrix()
+//
+// These two functions build and/or extract an affine matrix into
+// its constituent parts: scale, hpr, and translate.
+//
+// There are also two additional flavors for 3x3 matrices.  These are
+// treated as the upper 3x3 part of a general 4x4 matrix, and so can
+// only represent rotations and scales.
+//
+////////////////////////////////////////////////////////////////////
+
+#include <pandabase.h>
+#include <math.h>
+#include "lmatrix.h"
+#include "luse.h"
+
+#include "fltnames.h"
+#include "compose_matrix_src.h"
+
+#include "dblnames.h"
+#include "compose_matrix_src.h"
+
+#endif
+

+ 104 - 0
panda/src/linmath/compose_matrix_src.I

@@ -0,0 +1,104 @@
+////////////////////////////////////////////////////////////////////
+// Filename: compose_matrix_src.h
+// Created by:  drose (21Feb99)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: compose_matrix
+//  Description: Computes the 4x4 matrix according to scale, rotation,
+//               and translation.
+////////////////////////////////////////////////////////////////////
+INLINE void
+compose_matrix(FLOATNAME(LMatrix4) &mat,
+	       const FLOATNAME(LVecBase3) &scale,
+	       const FLOATNAME(LVecBase3) &hpr,
+	       const FLOATNAME(LVecBase3) &translate,
+	       CoordinateSystem cs) {
+  FLOATNAME(LMatrix3) upper3;
+  compose_matrix(upper3, scale, hpr, cs);
+  mat = FLOATNAME(LMatrix4)(upper3, translate);
+}
+
+INLINE void
+compose_matrix(FLOATNAME(LMatrix4) &mat,
+	       const FLOATTYPE components[9],
+	       CoordinateSystem cs) {
+  FLOATNAME(LVector3) scale(components[0],
+			    components[1],
+			    components[2]);
+  FLOATNAME(LVector3) hpr(components[3],
+			  components[4],
+			  components[5]);
+  FLOATNAME(LVector3) translate(components[6],
+				components[7],
+				components[8]);
+  compose_matrix(mat, scale, hpr, translate, cs);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: decompose_matrix
+//  Description: Extracts out the components of an affine matrix.
+//               Returns true if the scale, hpr, translate
+//               completely describe the matrix, or false if there is
+//               also a shear component or if the matrix is not
+//               affine.
+////////////////////////////////////////////////////////////////////
+INLINE bool
+decompose_matrix(const FLOATNAME(LMatrix4) &mat,
+		 FLOATNAME(LVecBase3) &scale,
+		 FLOATNAME(LVecBase3) &hpr,
+		 FLOATNAME(LVecBase3) &translate,
+		 CoordinateSystem cs) {
+  // Get the translation first.
+  translate = mat.get_row3(3);
+  return decompose_matrix(mat.get_upper_3(), scale, hpr, cs);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: decompose_matrix
+//  Description: Extracts out the components of an affine matrix.
+//               Returns true if the scale, hpr, translate
+//               completely describe the matrix, or false if there is
+//               also a shear component or if the matrix is not
+//               affine.
+//
+//               This flavor of the function accepts an expected roll
+//               amount.  This amount will be used as the roll
+//               component, rather than attempting to determine roll
+//               by examining the matrix; this helps alleviate roll
+//               instability due to roundoff errors or gimbal lock.
+////////////////////////////////////////////////////////////////////
+INLINE bool
+decompose_matrix(const FLOATNAME(LMatrix4) &mat,
+		 FLOATNAME(LVecBase3) &scale,
+		 FLOATNAME(LVecBase3) &hpr,
+		 FLOATNAME(LVecBase3) &translate,
+		 FLOATTYPE roll,
+		 CoordinateSystem cs) {
+  // Get the translation first.
+  translate = mat.get_row3(3);
+  return decompose_matrix(mat.get_upper_3(), scale, hpr, roll, cs);
+}
+
+INLINE bool
+decompose_matrix(const FLOATNAME(LMatrix4) &mat,
+		 FLOATTYPE components[9],
+		 CoordinateSystem cs) {
+  FLOATNAME(LVector3) scale, hpr, translate;
+  if (!decompose_matrix(mat, scale, hpr, translate, cs)) {
+    return false;
+  }
+  components[0] = scale[0];
+  components[1] = scale[1];
+  components[2] = scale[2];
+  components[3] = hpr[0];
+  components[4] = hpr[1];
+  components[5] = hpr[2];
+  components[6] = translate[0];
+  components[7] = translate[1];
+  components[8] = translate[2];
+  return true;
+}

+ 57 - 0
panda/src/linmath/config_linmath.cxx

@@ -0,0 +1,57 @@
+// Filename: config_linmath.cxx
+// Created by:  drose (23Feb00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "config_linmath.h"
+#include "luse.h"
+#include "coordinateSystem.h"
+
+#include <dconfig.h>
+
+Configure(config_linmath);
+NotifyCategoryDef(linmath, "");
+
+ConfigureFn(config_linmath) {
+  LVecBase2f::init_type();
+  LVecBase3f::init_type();
+  LVecBase4f::init_type();
+  LVector2f::init_type();
+  LVector3f::init_type();
+  LVector4f::init_type();
+  LPoint2f::init_type();
+  LPoint3f::init_type();
+  LPoint4f::init_type();
+  LMatrix3f::init_type();
+  LMatrix4f::init_type();
+
+  LVecBase2d::init_type();
+  LVecBase3d::init_type();
+  LVecBase4d::init_type();
+  LVector2d::init_type();
+  LVector3d::init_type();
+  LVector4d::init_type();
+  LPoint2d::init_type();
+  LPoint3d::init_type();
+  LPoint4d::init_type();
+  LMatrix3d::init_type();
+  LMatrix4d::init_type();
+
+  LQuaternionf::init_type();
+  LRotationf::init_type();
+  LOrientationf::init_type();
+
+  LQuaterniond::init_type();
+  LRotationd::init_type();
+  LOrientationd::init_type();
+
+  string csstr = config_linmath.GetString("coordinate-system", "default");
+  CoordinateSystem cs = parse_coordinate_system_string(csstr);
+
+  if (cs == CS_invalid) {
+    linmath_cat.error()
+      << "Unexpected coordinate-system string: " << csstr << "\n";
+    cs = CS_default;
+  }
+  default_coordinate_system = (cs == CS_default) ? CS_zup_right : cs;
+}

+ 14 - 0
panda/src/linmath/config_linmath.h

@@ -0,0 +1,14 @@
+// Filename: config_linmath.h
+// Created by:  drose (23Feb00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef CONFIG_LINMATH_H
+#define CONFIG_LINMATH_H
+
+#include <pandabase.h>
+#include <notifyCategoryProxy.h>
+
+NotifyCategoryDecl(linmath, EXPCL_PANDA, EXPTP_PANDA);
+
+#endif

+ 96 - 0
panda/src/linmath/coordinateSystem.cxx

@@ -0,0 +1,96 @@
+// Filename: coordinateSystem.cxx
+// Created by:  drose (24Sep99)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "coordinateSystem.h"
+#include "config_linmath.h"
+
+#include <dconfig.h>
+#include <notify.h>
+
+#include <ctype.h>
+#include <string>
+
+CoordinateSystem default_coordinate_system;
+
+
+CoordinateSystem
+parse_coordinate_system_string(const string &str) {
+  // First, make sure the string is lowercase before we compare it, so
+  // we'll be case-insensitive.
+  string lstr = str;
+  for (string::iterator si = lstr.begin();
+       si != lstr.end();
+       ++si) {
+    (*si) = tolower(*si);
+  }
+
+  if (lstr == "default") {
+    return CS_default;
+
+  } else if (lstr == "z-up" || lstr == "z-up-right") {
+    return CS_zup_right;
+
+  } else if (lstr == "y-up" || lstr == "y-up-right") {
+    return CS_yup_right;
+
+  } else if (lstr == "z-up-left") {
+    return CS_zup_left;
+
+  } else if (lstr == "y-up-left") {
+    return CS_yup_left;
+  }
+
+  return CS_invalid;
+}
+
+bool
+is_right_handed(CoordinateSystem cs) {
+  if (cs == CS_default) {
+    cs = default_coordinate_system;
+  }
+  switch (cs) {
+  case CS_zup_right:
+  case CS_yup_right:
+    return true;
+
+  case CS_zup_left:
+  case CS_yup_left:
+    return false;
+
+  default:
+    linmath_cat.error()
+      << "Invalid coordinate system value: " << (int)cs << "\n";
+    nassertr(false, false);
+    return false;
+  }
+}
+
+ostream &
+operator << (ostream &out, CoordinateSystem cs) {
+  switch (cs) {
+  case CS_default:
+    return out << "default";
+
+  case CS_zup_right:
+    return out << "zup_right";
+
+  case CS_yup_right:
+    return out << "yup_right";
+
+  case CS_zup_left:
+    return out << "zup_left";
+    
+  case CS_yup_left:
+    return out << "yup_left";
+
+  case CS_invalid:
+    return out << "invalid";
+  }
+
+  linmath_cat.error()
+    << "Invalid coordinate_system value: " << (int)cs << "\n";
+  nassertr(false, out);
+  return out;
+}

+ 46 - 0
panda/src/linmath/coordinateSystem.h

@@ -0,0 +1,46 @@
+// Filename: coordinateSystem.h
+// Created by:  drose (24Sep99)
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef COORDINATESYSTEM_H
+#define COORDINATESYSTEM_H
+
+#include <pandabase.h>
+
+#include <typedef.h>
+
+#include <string>
+
+BEGIN_PUBLISH
+
+enum CoordinateSystem {
+  // The CS_default entry does not refer to a particular coordinate
+  // system, but rather to the value stored in
+  // default_coordinate_system, which in turn is loaded from the
+  // Configrc variable "coordinate-system".
+  CS_default,
+
+  CS_zup_right,
+  CS_yup_right,
+  CS_zup_left,
+  CS_yup_left,
+ 
+  // CS_invalid is not a coordinate system at all.  It can be used in
+  // user-input processing code to indicate a contradictory coordinate
+  // system request.
+  CS_invalid,
+};
+
+END_PUBLISH
+
+extern CoordinateSystem EXPCL_PANDA default_coordinate_system;
+
+CoordinateSystem EXPCL_PANDA parse_coordinate_system_string(const string &str);
+bool EXPCL_PANDA is_right_handed(CoordinateSystem cs = CS_default);
+
+ostream EXPCL_PANDA &operator << (ostream &out, CoordinateSystem cs);
+
+
+#endif
+

+ 19 - 0
panda/src/linmath/deg_2_rad.h

@@ -0,0 +1,19 @@
+// Filename: deg_2_rad.h
+// Created by:  drose (29Sep99)
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef DEG_2_RAD_H
+#define DEG_2_RAD_H
+
+#include <pandabase.h>
+
+#include "mathNumbers.h"
+
+BEGIN_PUBLISH
+INLINE double deg_2_rad( double f ) { return f * MathNumbers::pi / 180.0; }
+INLINE double rad_2_deg( double f ) { return f * 180.0 / MathNumbers::pi; }
+END_PUBLISH
+
+#endif
+

+ 45 - 0
panda/src/linmath/ioPtaDatagramLinMath.I

@@ -0,0 +1,45 @@
+// Filename: ioPtaDatagramLinMath.I
+// Created by:  jason (26Jun00)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: IoPtaDatagamLinMath::write_datagram
+//       Access: Public, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+template<class LinMathElement>
+void IoPtaDatagramLinMath<LinMathElement>::
+write_datagram(Datagram &dest, CPTA(LinMathElement) array)
+{
+  dest.add_uint32(array.size());
+  for(int i = 0; i < (int)array.size(); i++)
+  {
+    array[i].write_datagram(dest);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: IoPtaDatagamLinMath::read_datagram
+//       Access: Public, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+template<class LinMathElement>
+PTA(LinMathElement) IoPtaDatagramLinMath<LinMathElement>::
+read_datagram(DatagramIterator &source)
+{
+  PTA(LinMathElement) array;
+  LinMathElement temp;
+
+  int size = source.get_uint32();
+  for(int i = 0; i < size; i++)
+  {
+    temp.read_datagram(source);
+    array.push_back(temp);
+  }
+
+  return array;
+}
+
+

+ 11 - 0
panda/src/linmath/ioPtaDatagramLinMath.cxx

@@ -0,0 +1,11 @@
+// Filename: ioPtaDatagramLinMath.cxx
+// Created by:  drose (29Jun00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "ioPtaDatagramLinMath.h"
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma implementation
+#endif

+ 62 - 0
panda/src/linmath/ioPtaDatagramLinMath.h

@@ -0,0 +1,62 @@
+// Filename: ioPtaDatagramLinMath.h
+// Created by:  jason (26Jun00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef _IO_PTA_DATAGRAM_LINMATH
+#define _IO_PTA_DATAGRAM_LINMATH
+
+#include <pandabase.h>
+
+#include "luse.h"
+#include "pta_Vertexf.h"
+#include "pta_Colorf.h"
+#include "pta_Normalf.h"
+#include "pta_TexCoordf.h"
+
+#include <pointerToArray.h>
+
+class Datagram;
+class DatagramIterator;
+
+///////////////////////////////////////////////////////////////////
+// 	 Class : IoPtaDatagramLinMath
+// Description : This class is used to read and write a PTA_something
+//               (where something is some kind of LinMath object like
+//               LMatrix4f or LVector3f) from a Datagram, in support
+//               of Bam.  It's not intended to be constructed; it's
+//               just a convenient place to scope these static methods
+//               which should be called directly.
+////////////////////////////////////////////////////////////////////
+template<class LinMathElement>
+class IoPtaDatagramLinMath {
+public:
+  static void write_datagram(Datagram &dest, CPTA(LinMathElement) array);
+  static PTA(LinMathElement) read_datagram(DatagramIterator &source);
+};
+
+#include "ioPtaDatagramLinMath.I"
+
+// Now export all of the likely template classes for Windows' benefit.
+// This must be done in this file, and not in the individual pta_*
+// files, because it's important that this export command be the first
+// appearance of a particular template instantiation.
+
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, IoPtaDatagramLinMath<Colorf>)
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, IoPtaDatagramLinMath<Normalf>)
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, IoPtaDatagramLinMath<TexCoordf>)
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, IoPtaDatagramLinMath<Vertexf>)
+
+
+typedef IoPtaDatagramLinMath<Colorf> IPD_Colorf;
+typedef IoPtaDatagramLinMath<Normalf> IPD_Normalf;
+typedef IoPtaDatagramLinMath<TexCoordf> IPD_TexCoordf;
+typedef IoPtaDatagramLinMath<Vertexf> IPD_Vertexf;
+
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#endif

+ 25 - 0
panda/src/linmath/lmat_ops.h

@@ -0,0 +1,25 @@
+// Filename: lmat_ops.h
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef LMAT_OPS_H
+#define LMAT_OPS_H
+
+#include "lvecBase3.h"
+#include "lpoint3.h"
+#include "lvector3.h"
+#include "lvecBase4.h"
+#include "lpoint4.h"
+#include "lvector4.h"
+#include "lmatrix3.h"
+#include "lmatrix4.h"
+
+#include "fltnames.h"
+#include "lmat_ops_src.h"
+
+#include "dblnames.h"
+#include "lmat_ops_src.h"
+
+
+#endif

+ 13 - 0
panda/src/linmath/lmatrix.cxx

@@ -0,0 +1,13 @@
+// Filename: lmatrix.cxx
+// Created by:  drose (22Feb99)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include <pandabase.h>
+#include "lmatrix.h"
+
+// This tells GCC to explicitly instantiate the templates defined in
+// lmatrix.h and leave them here.
+#ifdef __GNUC__
+#pragma implementation
+#endif

+ 28 - 0
panda/src/linmath/lmatrix.h

@@ -0,0 +1,28 @@
+// Filename: lmatrix.h
+// Created by:  drose (15Jan99)
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef LMATRIX_H
+#define LMATRIX_H
+
+#include <pandabase.h>
+#include "config_linmath.h"
+
+#include "lmatrix3.h"
+#include "lmatrix4.h"
+
+/*
+typedef LMatrix3<float> LMatrix3f;
+typedef LMatrix4<float> LMatrix4f;
+
+typedef LMatrix3<double> LMatrix3d;
+typedef LMatrix4<double> LMatrix4d;
+*/
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#endif

+ 15 - 0
panda/src/linmath/lmatrix3.cxx

@@ -0,0 +1,15 @@
+// Filename: lmatrix3.cxx
+// Created by:  drose (29Jan99)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "config_linmath.h"
+#include "lmatrix3.h"
+
+#include "fltnames.h"
+#include "lmatrix3_src.cxx"
+
+#include "dblnames.h"
+#include "lmatrix3_src.cxx"
+
+

+ 28 - 0
panda/src/linmath/lmatrix3.h

@@ -0,0 +1,28 @@
+// Filename: lmatrix3.h
+// Created by:  drose (29Jan99)
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef LMATRIX3_H
+#define LMATRIX3_H
+
+#include <pandabase.h>
+#include <math.h>
+#include <typeHandle.h>
+#include <datagram.h>
+#include <datagramIterator.h>
+#include <notify.h>
+#include <indent.h>
+#include "deg_2_rad.h"
+#include "nearly_zero.h"
+#include "coordinateSystem.h"
+#include "lvecBase3.h"
+#include "lvecBase2.h"
+
+#include "fltnames.h"
+#include "lmatrix3_src.h"
+
+#include "dblnames.h"
+#include "lmatrix3_src.h"
+
+#endif

+ 892 - 0
panda/src/linmath/lmatrix3_src.I

@@ -0,0 +1,892 @@
+// Filename: lmatrix3_src.I
+// Created by:  drose (29Jan99)
+// 
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::ident_mat
+//       Access: Public, Static
+//  Description: Returns an identity matrix.
+//
+//               This function definition must appear first, since
+//               some inline functions below take advantage of it.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LMatrix3) &FLOATNAME(LMatrix3)::
+ident_mat() {
+  return _ident_mat;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::Default Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3):: 
+FLOATNAME(LMatrix3)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3):: 
+FLOATNAME(LMatrix3)(const FLOATNAME(LMatrix3) &copy) {
+  (*this) = copy;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) &FLOATNAME(LMatrix3):: 
+operator = (const FLOATNAME(LMatrix3) &copy) {
+  set(copy(0, 0), copy(0, 1), copy(0, 2), 
+      copy(1, 0), copy(1, 1), copy(1, 2), 
+      copy(2, 0), copy(2, 1), copy(2, 2));
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::Fill Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) &FLOATNAME(LMatrix3)::
+operator = (FLOATTYPE fill_value) {
+  fill(fill_value);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3):: 
+FLOATNAME(LMatrix3)(FLOATTYPE e00, FLOATTYPE e01, FLOATTYPE e02,
+	 FLOATTYPE e10, FLOATTYPE e11, FLOATTYPE e12,
+	 FLOATTYPE e20, FLOATTYPE e21, FLOATTYPE e22) {
+  set(e00, e01, e02,
+      e10, e11, e12,
+      e20, e21, e22);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::set
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix3)::
+set(FLOATTYPE e00, FLOATTYPE e01, FLOATTYPE e02,
+    FLOATTYPE e10, FLOATTYPE e11, FLOATTYPE e12,
+    FLOATTYPE e20, FLOATTYPE e21, FLOATTYPE e22) {
+  (*this)(0, 0) = e00;
+  (*this)(0, 1) = e01;
+  (*this)(0, 2) = e02;
+  (*this)(1, 0) = e10;
+  (*this)(1, 1) = e11;
+  (*this)(1, 2) = e12;
+  (*this)(2, 0) = e20;
+  (*this)(2, 1) = e21;
+  (*this)(2, 2) = e22;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::set_row
+//       Access: Public
+//  Description: Replaces the indicated row of the matrix from a
+//               three-component vector.
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix3)::
+set_row(int row, const FLOATNAME(LVecBase3) &v) {
+  (*this)(row, 0) = v[0];
+  (*this)(row, 1) = v[1];
+  (*this)(row, 2) = v[2];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::set_column
+//       Access: Public
+//  Description: Replaces the indicated column of the matrix from a
+//               three-component vector.
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix3)::
+set_col(int col, const FLOATNAME(LVecBase3) &v) {
+  (*this)(0, col) = v[0];
+  (*this)(1, col) = v[1];
+  (*this)(2, col) = v[2];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::set_row
+//       Access: Public
+//  Description: Replaces the indicated row of the matrix from a
+//               two-component vector, ignoring the last column.
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix3)::
+set_row(int row, const FLOATNAME(LVecBase2) &v) {
+  (*this)(row, 0) = v[0];
+  (*this)(row, 1) = v[1];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::set_column
+//       Access: Public
+//  Description: Replaces the indicated column of the matrix from a
+//               two-component vector, ignoring the last row.
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix3)::
+set_col(int col, const FLOATNAME(LVecBase2) &v) {
+  (*this)(0, col) = v[0];
+  (*this)(1, col) = v[1];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::get_row
+//       Access: Public
+//  Description: Returns the indicated row of the matrix as a
+//               three-component vector.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LMatrix3)::
+get_row(int row) const {
+  return FLOATNAME(LVecBase3)((*this)(row, 0), (*this)(row, 1), (*this)(row, 2));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::get_col
+//       Access: Public
+//  Description: Returns the indicated column of the matrix as a
+//               three-component vector.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LMatrix3)::
+get_col(int col) const {
+  return FLOATNAME(LVecBase3)((*this)(0, col), (*this)(1, col), (*this)(2, col));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::get_row2
+//       Access: Public
+//  Description: Returns the indicated row of the matrix as a
+//               two-component vector, ignoring the last column.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2) FLOATNAME(LMatrix3)::
+get_row2(int row) const {
+  return FLOATNAME(LVecBase2)((*this)(row, 0), (*this)(row, 1));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::get_col2
+//       Access: Public
+//  Description: Returns the indicated column of the matrix as a
+//               two-component vector, ignoring the last row.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2) FLOATNAME(LMatrix3)::
+get_col2(int col) const {
+  return FLOATNAME(LVecBase2)((*this)(0, col), (*this)(1, col));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::Indexing operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE &FLOATNAME(LMatrix3)::
+operator () (int row, int col) {
+  nassertr(row >= 0 && row < 3, _data[0]);
+  nassertr(col >= 0 && col < 3, _data[0]);
+  return _data[row * 3 + col];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::Indexing operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LMatrix3)::
+operator () (int row, int col) const {
+  nassertr(row >= 0 && row < 3, 0.0);
+  nassertr(col >= 0 && col < 3, 0.0);
+  return _data[row * 3 + col];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::is_nan
+//       Access: Public
+//  Description: Returns true if any component of the matrix is
+//               not-a-number, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LMatrix3)::
+is_nan() const {
+  return 
+    cnan(_data[0]) || cnan(_data[1]) || cnan(_data[2]) ||
+    cnan(_data[3]) || cnan(_data[4]) || cnan(_data[5]) ||
+    cnan(_data[6]) || cnan(_data[7]) || cnan(_data[8]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::get_cell
+//       Access: Public
+//  Description: Returns a particular element of the matrix.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LMatrix3)::
+get_cell(int row, int col) const {
+  nassertr(row >= 0 && row < 3, 0.0);
+  nassertr(col >= 0 && col < 3, 0.0);
+  return _data[row * 3 + col];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::set_cell
+//       Access: Public
+//  Description: Changes a particular element of the matrix.
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix3)::
+set_cell(int row, int col, FLOATTYPE value) {
+  nassertv(row >= 0 && row < 3);
+  nassertv(col >= 0 && col < 3);
+  _data[row * 3 + col] = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::get_data
+//       Access: Public
+//  Description: Returns the address of the first of the nine data
+//               elements in the matrix.  The remaining elements
+//               occupy the next eight positions in row-major order.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATTYPE *FLOATNAME(LMatrix3)::
+get_data() const {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::get_num_components
+//       Access: Public
+//  Description: Returns the number of elements in the matrix, nine.
+////////////////////////////////////////////////////////////////////
+INLINE int FLOATNAME(LMatrix3)::
+get_num_components() const {
+  return 9;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::begin
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3)::iterator FLOATNAME(LMatrix3)::
+begin() {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::end
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3)::iterator FLOATNAME(LMatrix3)::
+end() {
+  return begin() + get_num_components();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::begin
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3)::const_iterator FLOATNAME(LMatrix3)::
+begin() const {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::end
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3)::const_iterator FLOATNAME(LMatrix3)::
+end() const {
+  return begin() + get_num_components();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::Inequality Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LMatrix3)::
+operator != (const FLOATNAME(LMatrix3) &other) const {
+  return !operator == (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::compare_to
+//       Access: Public
+//  Description: This flavor of compare_to uses a default threshold
+//               value based on the numeric type.
+////////////////////////////////////////////////////////////////////
+INLINE int FLOATNAME(LMatrix3)::
+compare_to(const FLOATNAME(LMatrix3) &other) const {
+  return compare_to(other, NEARLY_ZERO(FLOATTYPE));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::xform
+//       Access: Public
+//  Description: 3-component vector or point times matrix.  This is a
+//               fully general operation.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LMatrix3)::
+xform(const FLOATNAME(LVecBase3) &v) const {
+  return FLOATNAME(LVecBase3)(v.dot(get_col(0)),
+			    v.dot(get_col(1)),
+			    v.dot(get_col(2)));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::xform_point
+//       Access: Public
+//  Description: The matrix transforms a 2-component point (including
+//               translation component) and returns the result.  This
+//               assumes the matrix is an affine transform.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2) FLOATNAME(LMatrix3)::
+xform_point(const FLOATNAME(LVecBase2) &v) const {
+  return FLOATNAME(LVecBase2)(v.dot(get_col2(0)) + (*this)(2, 0),
+			    v.dot(get_col2(1)) + (*this)(2, 1));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::xform_vec
+//       Access: Public
+//  Description: The matrix transforms a 2-component vector (without
+//               translation component) and returns the result.  This
+//               assumes the matrix is an affine transform.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2) FLOATNAME(LMatrix3)::
+xform_vec(const FLOATNAME(LVecBase2) &v) const {
+  return FLOATNAME(LVecBase2)(v.dot(get_col2(0)),
+			    v.dot(get_col2(1)));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::mult_cel
+//       Access: Private
+//  Description: Returns one cell of the result of a matrix-matrix
+//               multiplication operation.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LMatrix3)::
+mult_cel(const FLOATNAME(LMatrix3) &other, int row, int col) const {
+  return get_row(row).dot(other.get_col(col));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::matrix *= matrix
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) &FLOATNAME(LMatrix3)::
+operator *= (const FLOATNAME(LMatrix3) &other) {
+  (*this) = (*this) * other;
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::matrix *= scalar
+//       Access: Public
+//  Description: Performs a memberwise scale.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) &FLOATNAME(LMatrix3)::
+operator *= (FLOATTYPE scalar) {
+  (*this)(0, 0) *= scalar;
+  (*this)(0, 1) *= scalar;
+  (*this)(0, 2) *= scalar;
+
+  (*this)(1, 0) *= scalar;
+  (*this)(1, 1) *= scalar;
+  (*this)(1, 2) *= scalar;
+
+  (*this)(2, 0) *= scalar;
+  (*this)(2, 1) *= scalar;
+  (*this)(2, 2) *= scalar;
+
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::matrix /= scalar
+//       Access: Public
+//  Description: Performs a memberwise scale.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) &FLOATNAME(LMatrix3)::
+operator /= (FLOATTYPE scalar) {
+  (*this)(0, 0) /= scalar;
+  (*this)(0, 1) /= scalar;
+  (*this)(0, 2) /= scalar;
+
+  (*this)(1, 0) /= scalar;
+  (*this)(1, 1) /= scalar;
+  (*this)(1, 2) /= scalar;
+
+  (*this)(2, 0) /= scalar;
+  (*this)(2, 1) /= scalar;
+  (*this)(2, 2) /= scalar;
+
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::transpose_from
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix3)::
+transpose_from(const FLOATNAME(LMatrix3) &other) {
+  (*this)(0, 0) = other(0, 0);
+  (*this)(0, 1) = other(1, 0);
+  (*this)(0, 2) = other(2, 0);
+
+  (*this)(1, 0) = other(0, 1);
+  (*this)(1, 1) = other(1, 1);
+  (*this)(1, 2) = other(2, 1);
+
+  (*this)(2, 0) = other(0, 2);
+  (*this)(2, 1) = other(1, 2);
+  (*this)(2, 2) = other(2, 2);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::transpose_in_place
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix3)::
+transpose_in_place() {
+  FLOATNAME(LMatrix3) temp = (*this);
+  transpose_from(temp);
+}
+
+// Matrix inversion code from Numerical Recipes in C.
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::det2
+//       Access: Private, Static
+//  Description: Returns the determinant of a 2x2 matrix.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LMatrix3)::
+det2(FLOATTYPE e00, FLOATTYPE e01, FLOATTYPE e10, FLOATTYPE e11) const {
+  return (e00 * e11 - e10 * e01);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::determinant
+//       Access: Public
+//  Description: Returns the determinant of the matrix.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LMatrix3)::
+determinant() const {
+  return 
+    (*this)(0,0) * det2((*this)(1,1),(*this)(1,2),(*this)(2,1),(*this)(2,2))
+    -(*this)(0,1) * det2((*this)(1,0),(*this)(1,2),(*this)(2,0),(*this)(2,2))
+    +(*this)(0,2) * det2((*this)(1,0),(*this)(1,1),(*this)(2,0),(*this)(2,1));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::invert_from
+//       Access: Public
+//  Description: Computes the inverse of the other matrix, and stores
+//               the result in this matrix.  This is a fully general
+//               operation and makes no assumptions about the type of
+//               transform represented by the matrix.
+//
+//               The other matrix must be a different object than this
+//               matrix.  However, if you need to invert a matrix in
+//               place, see invert_in_place.
+//
+//               The return value is true if the matrix was
+//               successfully inverted, false if the was a
+//               singularity.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LMatrix3)::
+invert_from(const FLOATNAME(LMatrix3) &other) {
+  FLOATTYPE d = other.determinant();
+
+  if (IS_NEARLY_ZERO(d)) {
+    linmath_cat.warning()
+      << "Tried to invert singular LMatrix3.\n";
+    (*this) = ident_mat();
+    return false;
+  }
+
+  d = 1.0 / d;
+  (*this)(0,0) =  d * det2(other(1,1), other(1,2), other(2,1), other(2,2));
+  (*this)(1,0) = -d * det2(other(1,0), other(1,2), other(2,0), other(2,2));
+  (*this)(2,0) =  d * det2(other(1,0), other(1,1), other(2,0), other(2,1));
+
+  (*this)(0,1) = -d * det2(other(0,1), other(0,2), other(2,1), other(2,2));
+  (*this)(1,1) =  d * det2(other(0,0), other(0,2), other(2,0), other(2,2));
+  (*this)(2,1) = -d * det2(other(0,0), other(0,1), other(2,0), other(2,1));
+
+  (*this)(0,2) =  d * det2(other(0,1), other(0,2), other(1,1), other(1,2));
+  (*this)(1,2) = -d * det2(other(0,0), other(0,2), other(1,0), other(1,2));
+  (*this)(2,2) =  d * det2(other(0,0), other(0,1), other(1,0), other(1,1));
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::invert_in_place
+//       Access: Public
+//  Description: Inverts the current matrix.  Returns true if the
+//               inverse is successful, false if the matrix was
+//               singular.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LMatrix3)::
+invert_in_place() {
+  FLOATNAME(LMatrix3) temp = (*this);
+  return invert_from(temp);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::translate_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that applies the indicated
+//               translation.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
+translate_mat(const FLOATNAME(LVecBase2) &trans) {
+  return FLOATNAME(LMatrix3)(1.0, 0.0, 0.0,
+			   0.0, 1.0, 0.0,
+			   trans[0], trans[1], 1.0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::translate_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that applies the indicated
+//               translation.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
+translate_mat(FLOATTYPE tx, FLOATTYPE ty) {
+  return FLOATNAME(LMatrix3)(1.0, 0.0, 0.0,
+			   0.0, 1.0, 0.0,
+			   tx, ty, 1.0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::rotate_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that rotates by the given angle in
+//               degrees counterclockwise.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
+rotate_mat(FLOATTYPE angle) {
+  double angle_rad=deg_2_rad(angle);
+  double s,c;
+  csincos(angle_rad,&s,&c);
+  return FLOATNAME(LMatrix3)(  c,    s,  0.0,
+			      -s,    c,  0.0,
+			     0.0,  0.0,  1.0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::scale_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that applies the indicated
+//               scale in each of the two axes.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
+scale_mat(const FLOATNAME(LVecBase2) &scale) {
+  return FLOATNAME(LMatrix3)(scale[0], 0.0, 0.0,
+			     0.0, scale[1], 0.0,
+			     0.0, 0.0, 1.0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::scale_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that applies the indicated
+//               scale in each of the two axes.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
+scale_mat(FLOATTYPE sx, FLOATTYPE sy) {
+  return FLOATNAME(LMatrix3)(sx, 0.0, 0.0,
+			     0.0, sy, 0.0,
+			     0.0, 0.0, 1.0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::rotate_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that rotates by the given angle in
+//               degrees counterclockwise about the indicated vector.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
+rotate_mat(FLOATTYPE angle, FLOATNAME(LVecBase3) axis,
+	   CoordinateSystem cs) {
+  if (cs == CS_default) {
+    cs = default_coordinate_system;
+  }
+  FLOATNAME(LMatrix3) mat;
+
+  if (!is_right_handed(cs)) {
+    // In a left-handed coordinate system, counterclockwise is the
+    // other direction.
+    angle = -angle;
+  }
+
+  // Normalize the axis.
+  FLOATTYPE length = axis.dot(axis);
+  nassertr(length != 0.0, ident_mat());
+  FLOATTYPE recip_length=1.0f/length;
+  axis *= recip_length;
+
+  double angle_rad=deg_2_rad(angle);
+  double s,c;
+  csincos(angle_rad,&s,&c);
+  double t = 1.0 - c;
+
+  mat(0, 0) = t * axis[0] * axis[0] + c;
+  mat(0, 1) = t * axis[0] * axis[1] + s * axis[2];
+  mat(0, 2) = t * axis[0] * axis[2] - s * axis[1];
+
+  mat(1, 0) = t * axis[1] * axis[0] - s * axis[2];
+  mat(1, 1) = t * axis[1] * axis[1] + c;
+  mat(1, 2) = t * axis[1] * axis[2] + s * axis[0];
+
+  mat(2, 0) = t * axis[2] * axis[0] + s * axis[1];
+  mat(2, 1) = t * axis[2] * axis[1] - s * axis[0];
+  mat(2, 2) = t * axis[2] * axis[2] + c;
+
+  return mat;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::scale_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that applies the indicated
+//               scale in each of the three axes.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
+scale_mat(const FLOATNAME(LVecBase3) &scale) {
+  return FLOATNAME(LMatrix3)(scale[0], 0.0, 0.0,
+			     0.0, scale[1], 0.0,
+			     0.0, 0.0, scale[2]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::scale_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that applies the indicated
+//               scale in each of the three axes.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
+scale_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz) {
+  return FLOATNAME(LMatrix3)(sx, 0.0, 0.0,
+			     0.0, sy, 0.0,
+			     0.0, 0.0, sz);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::almost_equal
+//       Access: Public
+//  Description: Returns true if two matrices are memberwise equal
+//               within a default tolerance based on the numeric type.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LMatrix3)::
+almost_equal(const FLOATNAME(LMatrix3) &other) const {
+  return almost_equal(other, NEARLY_ZERO(FLOATTYPE));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::output
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix3)::
+output(ostream &out) const {
+  out << "[ " 
+      << MAYBE_ZERO((*this)(0, 0)) << " "
+      << MAYBE_ZERO((*this)(0, 1)) << " " 
+      << MAYBE_ZERO((*this)(0, 2))
+      << " ] [ "
+      << MAYBE_ZERO((*this)(1, 0)) << " "
+      << MAYBE_ZERO((*this)(1, 1)) << " " 
+      << MAYBE_ZERO((*this)(1, 2))
+      << " ] [ "
+      << MAYBE_ZERO((*this)(2, 0)) << " "
+      << MAYBE_ZERO((*this)(2, 1)) << " " 
+      << MAYBE_ZERO((*this)(2, 2))
+      << " ]";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::transpose
+//  Description: Transposes the given matrix and returns it.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3)
+transpose(const FLOATNAME(LMatrix3) &a) {
+  FLOATNAME(LMatrix3) result;
+  result.transpose_from(a);
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::invert
+//  Description: Inverts the given matrix and returns it.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3)
+invert(const FLOATNAME(LMatrix3) &a) {
+  FLOATNAME(LMatrix3) result;
+  bool nonsingular = result.invert_from(a);
+  nassertr(nonsingular, FLOATNAME(LMatrix3)::ident_mat());
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::write
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix3)::
+write(ostream &out, int indent_level) const {
+  indent(out, indent_level) 
+    << MAYBE_ZERO((*this)(0, 0)) << " "
+    << MAYBE_ZERO((*this)(0, 1)) << " " 
+    << MAYBE_ZERO((*this)(0, 2))
+    << "\n";
+  indent(out, indent_level)
+    << MAYBE_ZERO((*this)(1, 0)) << " "
+    << MAYBE_ZERO((*this)(1, 1)) << " " 
+    << MAYBE_ZERO((*this)(1, 2))
+    << "\n";
+  indent(out, indent_level)
+    << MAYBE_ZERO((*this)(2, 0)) << " "
+    << MAYBE_ZERO((*this)(2, 1)) << " " 
+    << MAYBE_ZERO((*this)(2, 2))
+    << "\n";
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::matrix * matrix
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
+operator * (const FLOATNAME(LMatrix3) &other) const {
+  FLOATNAME(LMatrix3) t;
+
+  t(0, 0) = mult_cel(other, 0, 0);
+  t(0, 1) = mult_cel(other, 0, 1);
+  t(0, 2) = mult_cel(other, 0, 2);
+
+  t(1, 0) = mult_cel(other, 1, 0);
+  t(1, 1) = mult_cel(other, 1, 1);
+  t(1, 2) = mult_cel(other, 1, 2);
+
+  t(2, 0) = mult_cel(other, 2, 0);
+  t(2, 1) = mult_cel(other, 2, 1);
+  t(2, 2) = mult_cel(other, 2, 2);
+
+  return t;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::matrix * scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
+operator * (FLOATTYPE scalar) const {
+  FLOATNAME(LMatrix3) t;
+
+  t(0, 0) = (*this)(0, 0) * scalar;
+  t(0, 1) = (*this)(0, 1) * scalar;
+  t(0, 2) = (*this)(0, 2) * scalar;
+
+  t(1, 0) = (*this)(1, 0) * scalar;
+  t(1, 1) = (*this)(1, 1) * scalar;
+  t(1, 2) = (*this)(1, 2) * scalar;
+
+  t(2, 0) = (*this)(2, 0) * scalar;
+  t(2, 1) = (*this)(2, 1) * scalar;
+  t(2, 2) = (*this)(2, 2) * scalar;
+
+  return t;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::matrix / scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::
+operator / (FLOATTYPE scalar) const {
+  FLOATNAME(LMatrix3) t;
+
+  t(0, 0) = (*this)(0, 0) / scalar;
+  t(0, 1) = (*this)(0, 1) / scalar;
+  t(0, 2) = (*this)(0, 2) / scalar;
+
+  t(1, 0) = (*this)(1, 0) / scalar;
+  t(1, 1) = (*this)(1, 1) / scalar;
+  t(1, 2) = (*this)(1, 2) / scalar;
+
+  t(2, 0) = (*this)(2, 0) / scalar;
+  t(2, 1) = (*this)(2, 1) / scalar;
+  t(2, 2) = (*this)(2, 2) / scalar;
+
+  return t;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::matrix += matrix
+//       Access: Public
+//  Description: Performs a memberwise addition between two matrices.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) &FLOATNAME(LMatrix3)::
+operator += (const FLOATNAME(LMatrix3) &other) {
+  (*this)(0, 0) += other(0, 0);
+  (*this)(0, 1) += other(0, 1);
+  (*this)(0, 2) += other(0, 2);
+
+  (*this)(1, 0) += other(1, 0);
+  (*this)(1, 1) += other(1, 1);
+  (*this)(1, 2) += other(1, 2);
+
+  (*this)(2, 0) += other(2, 0);
+  (*this)(2, 1) += other(2, 1);
+  (*this)(2, 2) += other(2, 2);
+
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix3::matrix -= matrix
+//       Access: Public
+//  Description: Performs a memberwise subtraction between two matrices.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) &FLOATNAME(LMatrix3)::
+operator -= (const FLOATNAME(LMatrix3) &other) {
+  (*this)(0, 0) -= other(0, 0);
+  (*this)(0, 1) -= other(0, 1);
+  (*this)(0, 2) -= other(0, 2);
+
+  (*this)(1, 0) -= other(1, 0);
+  (*this)(1, 1) -= other(1, 1);
+  (*this)(1, 2) -= other(1, 2);
+
+  (*this)(2, 0) -= other(2, 0);
+  (*this)(2, 1) -= other(2, 1);
+  (*this)(2, 2) -= other(2, 2);
+
+  return *this;
+}

+ 15 - 0
panda/src/linmath/lmatrix4.cxx

@@ -0,0 +1,15 @@
+// Filename: lmatrix3.cxx
+// Created by:  drose (29Jan99)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "config_linmath.h"
+#include "lmatrix4.h"
+
+#include "fltnames.h"
+#include "lmatrix4_src.cxx"
+
+#include "dblnames.h"
+#include "lmatrix4_src.cxx"
+
+

+ 30 - 0
panda/src/linmath/lmatrix4.h

@@ -0,0 +1,30 @@
+// Filename: lmatrix4.h
+// Created by:  drose (29Jan99)
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef LMATRIX4_H
+#define LMATRIX4_H
+
+#include <pandabase.h>
+#include <math.h>
+#include <typeHandle.h>
+#include <datagram.h>
+#include <datagramIterator.h>
+#include <indent.h>
+
+#include "deg_2_rad.h"
+#include "nearly_zero.h"
+
+#include "coordinateSystem.h"
+#include "lvecBase4.h"
+#include "lvecBase3.h"
+#include "lmatrix3.h"
+
+#include "fltnames.h"
+#include "lmatrix4_src.h"
+
+#include "dblnames.h"
+#include "lmatrix4_src.h"
+
+#endif

+ 1107 - 0
panda/src/linmath/lmatrix4_src.I

@@ -0,0 +1,1107 @@
+// Filename: lmatrix4_src.I
+// Created by:  drose (15Jan99)
+// 
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::ident_mat
+//       Access: Public, Static
+//  Description: Returns an identity matrix.
+//
+//               This function definition must appear first, since
+//               some inline functions below take advantage of it.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LMatrix4) &FLOATNAME(LMatrix4)::
+ident_mat() {
+  return _ident_mat;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::Default Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4)::
+FLOATNAME(LMatrix4)() { 
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4):: 
+FLOATNAME(LMatrix4)(const FLOATNAME(LMatrix4) &copy) {
+  (*this) = copy;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) &FLOATNAME(LMatrix4):: 
+operator = (const FLOATNAME(LMatrix4) &copy) {
+  set(copy(0, 0), copy(0, 1), copy(0, 2), copy(0, 3),
+      copy(1, 0), copy(1, 1), copy(1, 2), copy(1, 3),
+      copy(2, 0), copy(2, 1), copy(2, 2), copy(2, 3),
+      copy(3, 0), copy(3, 1), copy(3, 2), copy(3, 3));
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::Fill Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) &FLOATNAME(LMatrix4)::
+operator = (FLOATTYPE fill_value) {
+  fill(fill_value);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4)::
+FLOATNAME(LMatrix4)(FLOATTYPE e00, FLOATTYPE e01, FLOATTYPE e02, FLOATTYPE e03,
+		    FLOATTYPE e10, FLOATTYPE e11, FLOATTYPE e12, FLOATTYPE e13,
+		    FLOATTYPE e20, FLOATTYPE e21, FLOATTYPE e22, FLOATTYPE e23,
+		    FLOATTYPE e30, FLOATTYPE e31, FLOATTYPE e32, FLOATTYPE e33) {
+  set(e00, e01, e02, e03,
+      e10, e11, e12, e13,
+      e20, e21, e22, e23,
+      e30, e31, e32, e33);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::Constructor, upper 3x3
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4)::
+FLOATNAME(LMatrix4)(const FLOATNAME(LMatrix3) &upper3) {
+  set(upper3(0, 0), upper3(0, 1), upper3(0, 2), 0.0,
+      upper3(1, 0), upper3(1, 1), upper3(1, 2), 0.0,
+      upper3(2, 0), upper3(2, 1), upper3(2, 2), 0.0,
+      0.0, 0.0, 0.0, 1.0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::Constructor, upper 3x3 plus translation
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4)::
+FLOATNAME(LMatrix4)(const FLOATNAME(LMatrix3) &upper3,
+	 const FLOATNAME(LVecBase3) &trans) {
+  set(upper3(0, 0), upper3(0, 1), upper3(0, 2), 0.0,
+      upper3(1, 0), upper3(1, 1), upper3(1, 2), 0.0,
+      upper3(2, 0), upper3(2, 1), upper3(2, 2), 0.0,
+      trans[0], trans[1], trans[2], 1.0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::fill
+//       Access: Public
+//  Description: Sets each element of the matrix to the indicated
+//               fill_value.  This is of questionable value, but is
+//               sometimes useful when initializing to zero.
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix4)::
+fill(FLOATTYPE fill_value) {
+  set(fill_value, fill_value, fill_value, fill_value,
+      fill_value, fill_value, fill_value, fill_value,
+      fill_value, fill_value, fill_value, fill_value,
+      fill_value, fill_value, fill_value, fill_value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::set
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix4)::
+set(FLOATTYPE e00, FLOATTYPE e01, FLOATTYPE e02, FLOATTYPE e03,
+    FLOATTYPE e10, FLOATTYPE e11, FLOATTYPE e12, FLOATTYPE e13,
+    FLOATTYPE e20, FLOATTYPE e21, FLOATTYPE e22, FLOATTYPE e23,
+    FLOATTYPE e30, FLOATTYPE e31, FLOATTYPE e32, FLOATTYPE e33) {
+  (*this)(0, 0) = e00;
+  (*this)(0, 1) = e01;
+  (*this)(0, 2) = e02;
+  (*this)(0, 3) = e03;
+
+  (*this)(1, 0) = e10;
+  (*this)(1, 1) = e11;
+  (*this)(1, 2) = e12;
+  (*this)(1, 3) = e13;
+
+  (*this)(2, 0) = e20;
+  (*this)(2, 1) = e21;
+  (*this)(2, 2) = e22;
+  (*this)(2, 3) = e23;
+
+  (*this)(3, 0) = e30;
+  (*this)(3, 1) = e31;
+  (*this)(3, 2) = e32;
+  (*this)(3, 3) = e33;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::set_upper_3
+//       Access: Public
+//  Description: Sets the upper 3x3 submatrix.
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix4)::
+set_upper_3(const FLOATNAME(LMatrix3) &upper3) {
+  (*this)(0, 0) = upper3(0, 0);
+  (*this)(0, 1) = upper3(0, 1);
+  (*this)(0, 2) = upper3(0, 2);
+
+  (*this)(1, 0) = upper3(1, 0);
+  (*this)(1, 1) = upper3(1, 1);
+  (*this)(1, 2) = upper3(1, 2);
+
+  (*this)(2, 0) = upper3(2, 0);
+  (*this)(2, 1) = upper3(2, 1);
+  (*this)(2, 2) = upper3(2, 2);
+}
+    
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::get_upper_3
+//       Access: Public
+//  Description: Retrieves the upper 3x3 submatrix.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) FLOATNAME(LMatrix4)::
+get_upper_3() const {
+  return FLOATNAME(LMatrix3)
+    ((*this)(0, 0), (*this)(0, 1), (*this)(0, 2),
+     (*this)(1, 0), (*this)(1, 1), (*this)(1, 2),
+     (*this)(2, 0), (*this)(2, 1), (*this)(2, 2));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::set_row
+//       Access: Public
+//  Description: Replaces the indicated row of the matrix.
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix4)::
+set_row(int row, const FLOATNAME(LVecBase4) &v) {
+  (*this)(row, 0) = v[0];
+  (*this)(row, 1) = v[1];
+  (*this)(row, 2) = v[2];
+  (*this)(row, 3) = v[3];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::set_col
+//       Access: Public
+//  Description: Replaces the indicated column of the matrix.
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix4)::
+set_col(int col, const FLOATNAME(LVecBase4) &v) {
+  (*this)(0, col) = v[0];
+  (*this)(1, col) = v[1];
+  (*this)(2, col) = v[2];
+  (*this)(3, col) = v[3];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::set_row
+//       Access: Public
+//  Description: Replaces the indicated row of the matrix with the
+//               indicated 3-component vector, ignoring the last
+//               column.
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix4)::
+set_row(int row, const FLOATNAME(LVecBase3) &v) {
+  (*this)(row, 0) = v[0];
+  (*this)(row, 1) = v[1];
+  (*this)(row, 2) = v[2];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::set_col
+//       Access: Public
+//  Description: Replaces the indicated column of the matrix with the
+//               indicated 3-component vector, ignoring the last
+//               row.
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix4)::
+set_col(int col, const FLOATNAME(LVecBase3) &v) {
+  (*this)(0, col) = v[0];
+  (*this)(1, col) = v[1];
+  (*this)(2, col) = v[2];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::get_row
+//       Access: Public
+//  Description: Retrieves the indicated row of the matrix as a
+//               4-component vector.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4) FLOATNAME(LMatrix4)::
+get_row(int row) const {
+  return FLOATNAME(LVecBase4)((*this)(row, 0),
+			      (*this)(row, 1),
+			      (*this)(row, 2),
+			      (*this)(row, 3));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::get_col
+//       Access: Public
+//  Description: Retrieves the indicated column of the matrix as a
+//               4-component vector.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4) FLOATNAME(LMatrix4)::
+get_col(int col) const {
+  return FLOATNAME(LVecBase4)((*this)(0, col),
+			      (*this)(1, col),
+			      (*this)(2, col),
+			      (*this)(3, col));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::get_row3
+//       Access: Public
+//  Description: Retrieves the row column of the matrix as a
+//               3-component vector, ignoring the last column.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LMatrix4)::
+get_row3(int row) const {
+  return FLOATNAME(LVecBase3)((*this)(row, 0),
+			      (*this)(row, 1),
+			      (*this)(row, 2));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::get_col3
+//       Access: Public
+//  Description: Retrieves the indicated column of the matrix as a
+//               3-component vector, ignoring the last row.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LMatrix4)::
+get_col3(int col) const {
+  return FLOATNAME(LVecBase3)((*this)(0, col),
+			      (*this)(1, col),
+			      (*this)(2, col));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::Indexing operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE &FLOATNAME(LMatrix4)::
+operator () (int row, int col) {
+  //  nassertr(row >= 0 && row < 4, _data[0]);
+  //  nassertr(col >= 0 && col < 4, _data[0]);
+  return _data[row * 4 + col];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::Indexing operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LMatrix4)::
+operator () (int row, int col) const {
+  //  nassertr(row >= 0 && row < 4, 0.0);
+  //  nassertr(col >= 0 && col < 4, 0.0);
+  return _data[row * 4 + col];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::is_nan
+//       Access: Public
+//  Description: Returns true if any component of the matrix is
+//               not-a-number, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LMatrix4)::
+is_nan() const {
+  return 
+    cnan(_data[0]) || cnan(_data[1]) || cnan(_data[2]) || cnan(_data[3]) ||
+    cnan(_data[4]) || cnan(_data[5]) || cnan(_data[6]) || cnan(_data[7]) || 
+    cnan(_data[8]) || cnan(_data[9]) || cnan(_data[10]) || cnan(_data[11]) || 
+    cnan(_data[12]) || cnan(_data[13]) || cnan(_data[14]) || cnan(_data[15]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::get_cell
+//       Access: Public
+//  Description: Returns a particular element of the matrix.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LMatrix4)::
+get_cell(int row, int col) const {
+  nassertr(row >= 0 && row < 4, 0.0);
+  nassertr(col >= 0 && col < 4, 0.0);
+  return _data[row * 4 + col];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::set_cell
+//       Access: Public
+//  Description: Changes a particular element of the matrix.
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix4)::
+set_cell(int row, int col, FLOATTYPE value) {
+  nassertv(row >= 0 && row < 4);
+  nassertv(col >= 0 && col < 4);
+  _data[row * 4 + col] = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::get_data
+//       Access: Public
+//  Description: Returns the address of the first of the nine data
+//               elements in the matrix.  The remaining elements
+//               occupy the next eight positions in row-major order.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATTYPE *FLOATNAME(LMatrix4)::
+get_data() const {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::get_num_components
+//       Access: Public
+//  Description: Returns the number of elements in the matrix, 16.
+////////////////////////////////////////////////////////////////////
+INLINE int FLOATNAME(LMatrix4)::
+get_num_components() const {
+  return 16;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::begin
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4)::iterator FLOATNAME(LMatrix4)::
+begin() {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::end
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4)::iterator FLOATNAME(LMatrix4)::
+end() {
+  return begin() + 16;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::begin
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4)::const_iterator FLOATNAME(LMatrix4)::
+begin() const {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::end
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4)::const_iterator FLOATNAME(LMatrix4)::
+end() const {
+  return begin() + 16;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::Inequality Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LMatrix4)::
+operator != (const FLOATNAME(LMatrix4) &other) const {
+  return !operator == (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::compare_to
+//       Access: Public
+//  Description: This flavor of compare_to uses a default threshold
+//               value based on the numeric type.
+////////////////////////////////////////////////////////////////////
+INLINE int FLOATNAME(LMatrix4)::
+compare_to(const FLOATNAME(LMatrix4) &other) const {
+  return compare_to(other, NEARLY_ZERO(FLOATTYPE));
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::xform
+//       Access: Public
+//  Description: 4-component vector or point times matrix.  This is a
+//               fully general operation.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4) FLOATNAME(LMatrix4)::
+xform(const FLOATNAME(LVecBase4) &v) const {
+  return FLOATNAME(LVecBase4)(v.dot(get_col(0)),
+			      v.dot(get_col(1)),
+			      v.dot(get_col(2)),
+			      v.dot(get_col(3)));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::xform_point
+//       Access: Public
+//  Description: The matrix transforms a 3-component point (including
+//               translation component) and returns the result.  This
+//               assumes the matrix is an affine transform.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LMatrix4)::
+xform_point(const FLOATNAME(LVecBase3) &v) const {
+  return FLOATNAME(LVecBase3)(v.dot(get_col3(0)) + (*this)(3, 0),
+			      v.dot(get_col3(1)) + (*this)(3, 1),
+			      v.dot(get_col3(2)) + (*this)(3, 2));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::xform_vec
+//       Access: Public
+//  Description: The matrix transforms a 3-component vector (without
+//               translation component) and returns the result.  This
+//               assumes the matrix is an affine transform.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LMatrix4)::
+xform_vec(const FLOATNAME(LVecBase3) &v) const {
+  return FLOATNAME(LVecBase3)(v.dot(get_col3(0)),
+			      v.dot(get_col3(1)),
+			      v.dot(get_col3(2)));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::mult_cel
+//       Access: Private
+//  Description: Returns one cell of the result of a matrix-matrix
+//               multiplication operation.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LMatrix4)::
+mult_cel(const FLOATNAME(LMatrix4) &other, int row, int col) const {
+  return get_row(row).dot(other.get_col(col));
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::matrix * matrix
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::
+operator * (const FLOATNAME(LMatrix4) &other) const {
+  FLOATNAME(LMatrix4) t;
+
+  t(0, 0) = mult_cel(other, 0, 0);
+  t(0, 1) = mult_cel(other, 0, 1);
+  t(0, 2) = mult_cel(other, 0, 2);
+  t(0, 3) = mult_cel(other, 0, 3);
+
+  t(1, 0) = mult_cel(other, 1, 0);
+  t(1, 1) = mult_cel(other, 1, 1);
+  t(1, 2) = mult_cel(other, 1, 2);
+  t(1, 3) = mult_cel(other, 1, 3);
+
+  t(2, 0) = mult_cel(other, 2, 0);
+  t(2, 1) = mult_cel(other, 2, 1);
+  t(2, 2) = mult_cel(other, 2, 2);
+  t(2, 3) = mult_cel(other, 2, 3);
+
+  t(3, 0) = mult_cel(other, 3, 0);
+  t(3, 1) = mult_cel(other, 3, 1);
+  t(3, 2) = mult_cel(other, 3, 2);
+  t(3, 3) = mult_cel(other, 3, 3);
+
+  return t;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::matrix * scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::
+operator * (FLOATTYPE scalar) const {
+  FLOATNAME(LMatrix4) t;
+
+  t(0, 0) = (*this)(0, 0) * scalar;
+  t(0, 1) = (*this)(0, 1) * scalar;
+  t(0, 2) = (*this)(0, 2) * scalar;
+  t(0, 3) = (*this)(0, 3) * scalar;
+
+  t(1, 0) = (*this)(1, 0) * scalar;
+  t(1, 1) = (*this)(1, 1) * scalar;
+  t(1, 2) = (*this)(1, 2) * scalar;
+  t(1, 3) = (*this)(1, 3) * scalar;
+
+  t(2, 0) = (*this)(2, 0) * scalar;
+  t(2, 1) = (*this)(2, 1) * scalar;
+  t(2, 2) = (*this)(2, 2) * scalar;
+  t(2, 3) = (*this)(2, 3) * scalar;
+
+  t(3, 0) = (*this)(3, 0) * scalar;
+  t(3, 1) = (*this)(3, 1) * scalar;
+  t(3, 2) = (*this)(3, 2) * scalar;
+  t(3, 3) = (*this)(3, 3) * scalar;
+
+  return t;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::matrix / scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::
+operator / (FLOATTYPE scalar) const {
+  FLOATNAME(LMatrix4) t;
+
+  t(0, 0) = (*this)(0, 0) / scalar;
+  t(0, 1) = (*this)(0, 1) / scalar;
+  t(0, 2) = (*this)(0, 2) / scalar;
+  t(0, 3) = (*this)(0, 3) / scalar;
+
+  t(1, 0) = (*this)(1, 0) / scalar;
+  t(1, 1) = (*this)(1, 1) / scalar;
+  t(1, 2) = (*this)(1, 2) / scalar;
+  t(1, 3) = (*this)(1, 3) / scalar;
+
+  t(2, 0) = (*this)(2, 0) / scalar;
+  t(2, 1) = (*this)(2, 1) / scalar;
+  t(2, 2) = (*this)(2, 2) / scalar;
+  t(2, 3) = (*this)(2, 3) / scalar;
+
+  t(3, 0) = (*this)(3, 0) / scalar;
+  t(3, 1) = (*this)(3, 1) / scalar;
+  t(3, 2) = (*this)(3, 2) / scalar;
+  t(3, 3) = (*this)(3, 3) / scalar;
+
+  return t;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::matrix += matrix
+//       Access: Public
+//  Description: Performs a memberwise addition between two matrices.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) &FLOATNAME(LMatrix4)::
+operator += (const FLOATNAME(LMatrix4) &other) {
+  (*this)(0, 0) += other(0, 0);
+  (*this)(0, 1) += other(0, 1);
+  (*this)(0, 2) += other(0, 2);
+  (*this)(0, 3) += other(0, 3);
+
+  (*this)(1, 0) += other(1, 0);
+  (*this)(1, 1) += other(1, 1);
+  (*this)(1, 2) += other(1, 2);
+  (*this)(1, 3) += other(1, 3);
+
+  (*this)(2, 0) += other(2, 0);
+  (*this)(2, 1) += other(2, 1);
+  (*this)(2, 2) += other(2, 2);
+  (*this)(2, 3) += other(2, 3);
+
+  (*this)(3, 0) += other(3, 0);
+  (*this)(3, 1) += other(3, 1);
+  (*this)(3, 2) += other(3, 2);
+  (*this)(3, 3) += other(3, 3);
+
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::matrix -= matrix
+//       Access: Public
+//  Description: Performs a memberwise addition between two matrices.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) &FLOATNAME(LMatrix4)::
+operator -= (const FLOATNAME(LMatrix4) &other) {
+  (*this)(0, 0) -= other(0, 0);
+  (*this)(0, 1) -= other(0, 1);
+  (*this)(0, 2) -= other(0, 2);
+  (*this)(0, 3) -= other(0, 3);
+
+  (*this)(1, 0) -= other(1, 0);
+  (*this)(1, 1) -= other(1, 1);
+  (*this)(1, 2) -= other(1, 2);
+  (*this)(1, 3) -= other(1, 3);
+
+  (*this)(2, 0) -= other(2, 0);
+  (*this)(2, 1) -= other(2, 1);
+  (*this)(2, 2) -= other(2, 2);
+  (*this)(2, 3) -= other(2, 3);
+
+  (*this)(3, 0) -= other(3, 0);
+  (*this)(3, 1) -= other(3, 1);
+  (*this)(3, 2) -= other(3, 2);
+  (*this)(3, 3) -= other(3, 3);
+
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::matrix *= matrix
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) &FLOATNAME(LMatrix4)::
+operator *= (const FLOATNAME(LMatrix4) &other) {
+  (*this) = (*this) * other;
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::matrix *= scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) &FLOATNAME(LMatrix4)::
+operator *= (FLOATTYPE scalar) {
+  (*this)(0, 0) *= scalar;
+  (*this)(0, 1) *= scalar;
+  (*this)(0, 2) *= scalar;
+  (*this)(0, 3) *= scalar;
+
+  (*this)(1, 0) *= scalar;
+  (*this)(1, 1) *= scalar;
+  (*this)(1, 2) *= scalar;
+  (*this)(1, 3) *= scalar;
+
+  (*this)(2, 0) *= scalar;
+  (*this)(2, 1) *= scalar;
+  (*this)(2, 2) *= scalar;
+  (*this)(2, 3) *= scalar;
+
+  (*this)(3, 0) *= scalar;
+  (*this)(3, 1) *= scalar;
+  (*this)(3, 2) *= scalar;
+  (*this)(3, 3) *= scalar;
+
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::matrix /= scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) &FLOATNAME(LMatrix4)::
+operator /= (FLOATTYPE scalar) {
+  (*this)(0, 0) /= scalar;
+  (*this)(0, 1) /= scalar;
+  (*this)(0, 2) /= scalar;
+  (*this)(0, 3) /= scalar;
+
+  (*this)(1, 0) /= scalar;
+  (*this)(1, 1) /= scalar;
+  (*this)(1, 2) /= scalar;
+  (*this)(1, 3) /= scalar;
+
+  (*this)(2, 0) /= scalar;
+  (*this)(2, 1) /= scalar;
+  (*this)(2, 2) /= scalar;
+  (*this)(2, 3) /= scalar;
+
+  (*this)(3, 0) /= scalar;
+  (*this)(3, 1) /= scalar;
+  (*this)(3, 2) /= scalar;
+  (*this)(3, 3) /= scalar;
+
+  return *this;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::transpose_from
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix4)::
+transpose_from(const FLOATNAME(LMatrix4) &other) {
+  (*this)(0, 0) = other(0, 0);
+  (*this)(0, 1) = other(1, 0);
+  (*this)(0, 2) = other(2, 0);
+  (*this)(0, 3) = other(3, 0);
+
+  (*this)(1, 0) = other(0, 1);
+  (*this)(1, 1) = other(1, 1);
+  (*this)(1, 2) = other(2, 1);
+  (*this)(1, 3) = other(3, 1);
+
+  (*this)(2, 0) = other(0, 2);
+  (*this)(2, 1) = other(1, 2);
+  (*this)(2, 2) = other(2, 2);
+  (*this)(2, 3) = other(3, 2);
+
+  (*this)(3, 0) = other(0, 3);
+  (*this)(3, 1) = other(1, 3);
+  (*this)(3, 2) = other(2, 3);
+  (*this)(3, 3) = other(3, 3);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::transpose_in_place
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix4)::
+transpose_in_place() {
+  FLOATNAME(LMatrix4) temp = (*this);
+  transpose_from(temp);
+}
+
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::invert_from
+//       Access: Public
+//  Description: Computes the inverse of the other matrix, and stores
+//               the result in this matrix.  This is a fully general
+//               operation and makes no assumptions about the type of
+//               transform represented by the matrix.
+//
+//               The other matrix must be a different object than this
+//               matrix.  However, if you need to invert a matrix in
+//               place, see invert_in_place.
+//
+//               The return value is true if the matrix was
+//               successfully inverted, false if the was a
+//               singularity.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LMatrix4)::
+invert_from(const FLOATNAME(LMatrix4) &other) {
+  if (IS_NEARLY_EQUAL(other(3, 0), 0.0) &&
+      IS_NEARLY_EQUAL(other(3, 1), 0.0) &&
+      IS_NEARLY_EQUAL(other(3, 2), 0.0) &&
+      IS_NEARLY_EQUAL(other(3, 3), 1.0)) {
+    return invert_affine_from(other);
+  }
+
+  (*this) = other;
+   
+  int index[4];
+
+  if (!decompose_mat(index)) {
+    linmath_cat.warning()
+      << "Tried to invert singular LMatrix4.\n";
+    return false;
+  }
+  
+  FLOATNAME(LMatrix4) inv = FLOATNAME(LMatrix4)::ident_mat();
+  int row;
+  
+  for (row = 0; row < 4; row++) {
+    back_sub_mat(index, inv, row);
+  }
+  
+  transpose_from(inv);
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::invert_affine_from
+//       Access: Public
+//  Description: Performs an invert of the indicated matrix, storing
+//               the result in this matrix.  The calculation is only
+//               correct of the other matrix represents an affine
+//               transform.
+//
+//               The other matrix must be a different object than this
+//               matrix.  However, if you need to invert a matrix in
+//               place, see invert_in_place.
+//
+//               The return value is true if the matrix was
+//               successfully inverted, false if the was a
+//               singularity.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LMatrix4)::
+invert_affine_from(const FLOATNAME(LMatrix4) &other) {
+  FLOATNAME(LMatrix3) rot;
+  rot.invert_from(other.get_upper_3());
+
+  set_upper_3(rot);
+  set_col(3, FLOATNAME(LVecBase4)(0.0, 0.0, 0.0, 1.0));
+
+  // compute -C*inv(A)
+  for (int i = 0; i < 3; i++) {
+    (*this)(3, i) = 0.0;
+    for (int j = 0; j < 3; j++) {
+      (*this)(3, i) -= other(3, j) * (*this)(j, i);
+    }
+  }
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::invert_in_place
+//       Access: Public
+//  Description: Inverts the current matrix.  Returns true if the
+//               inverse is successful, false if the matrix was
+//               singular.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LMatrix4)::
+invert_in_place() {
+  FLOATNAME(LMatrix4) temp = (*this);
+  return invert_from(temp);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::translate_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that applies the indicated
+//               translation.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::
+translate_mat(const FLOATNAME(LVecBase3) &trans) {
+  return FLOATNAME(LMatrix4)(1.0, 0.0, 0.0, 0.0,
+			   0.0, 1.0, 0.0, 0.0,
+			   0.0, 0.0, 1.0, 0.0,
+			   trans[0], trans[1], trans[2], 1.0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::translate_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that applies the indicated
+//               translation.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::
+translate_mat(FLOATTYPE tx, FLOATTYPE ty, FLOATTYPE tz) {
+  return FLOATNAME(LMatrix4)(1.0, 0.0, 0.0, 0.0,
+			   0.0, 1.0, 0.0, 0.0,
+			   0.0, 0.0, 1.0, 0.0,
+			   tx, ty, tz, 1.0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::rotate_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that rotates by the given angle in
+//               degrees counterclockwise about the indicated vector.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::
+rotate_mat(FLOATTYPE angle, FLOATNAME(LVecBase3) axis,
+	   CoordinateSystem cs) {
+  if (cs == CS_default) {
+    cs = default_coordinate_system;
+  }
+  FLOATNAME(LMatrix4) mat;
+
+  if (!is_right_handed(cs)) {
+    // In a left-handed coordinate system, counterclockwise is the
+    // other direction.
+    angle = -angle;
+  }
+
+  // Normalize the axis.
+  FLOATTYPE length2 = axis.dot(axis);
+  // Cannot rotate about a zero-length axis.
+  nassertr(length2 != 0.0, ident_mat());
+  FLOATTYPE recip_sqrt_length2=1.0f/csqrt(length2);
+  axis *= recip_sqrt_length2;
+
+  double angle_rad=deg_2_rad(angle);
+  double s,c;
+  csincos(angle_rad,&s,&c);
+  double t = 1.0 - c;
+
+  mat(0, 0) = t * axis[0] * axis[0] + c;
+  mat(0, 1) = t * axis[0] * axis[1] + s * axis[2];
+  mat(0, 2) = t * axis[0] * axis[2] - s * axis[1];
+  mat(0, 3) = 0.0;
+
+  mat(1, 0) = t * axis[1] * axis[0] - s * axis[2];
+  mat(1, 1) = t * axis[1] * axis[1] + c;
+  mat(1, 2) = t * axis[1] * axis[2] + s * axis[0];
+  mat(1, 3) = 0.0;
+
+  mat(2, 0) = t * axis[2] * axis[0] + s * axis[1];
+  mat(2, 1) = t * axis[2] * axis[1] - s * axis[0];
+  mat(2, 2) = t * axis[2] * axis[2] + c;
+  mat(2, 3) = 0.0;
+
+  mat(3, 0) = 0.0;
+  mat(3, 1) = 0.0;
+  mat(3, 2) = 0.0;
+  mat(3, 3) = 1.0;
+
+  return mat;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::scale_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that applies the indicated
+//               scale in each of the three axes.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::
+scale_mat(const FLOATNAME(LVecBase3) &scale) {
+  return FLOATNAME(LMatrix4)(scale[0], 0.0, 0.0, 0.0,
+			   0.0, scale[1], 0.0, 0.0,
+			   0.0, 0.0, scale[2], 0.0,
+			   0.0, 0.0, 0.0, 1.0);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::scale_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that applies the indicated
+//               scale in each of the three axes.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::
+scale_mat(FLOATTYPE sx, FLOATTYPE sy, FLOATTYPE sz) {
+  return FLOATNAME(LMatrix4)(sx, 0.0, 0.0, 0.0,
+			   0.0, sy, 0.0, 0.0,
+			   0.0, 0.0, sz, 0.0,
+			   0.0, 0.0, 0.0, 1.0);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::scale_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that applies the indicated
+//               uniform scale.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::
+scale_mat(FLOATTYPE scale) {
+  return FLOATNAME(LMatrix4)(scale, 0.0, 0.0, 0.0,
+			   0.0, scale, 0.0, 0.0,
+			   0.0, 0.0, scale, 0.0,
+			   0.0, 0.0, 0.0, 1.0);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::y_to_z_up_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that transforms from the Y-up
+//               coordinate system to the Z-up coordinate system.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LMatrix4) &FLOATNAME(LMatrix4)::
+y_to_z_up_mat() {
+  return _y_to_z_up_mat;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix::z_to_y_up_mat
+//       Access: Public, Static
+//  Description: Returns a matrix that transforms from the Y-up
+//               coordinate system to the Z-up coordinate system.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LMatrix4) &FLOATNAME(LMatrix4)::
+z_to_y_up_mat() {
+  return _z_to_y_up_mat;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::almost_equal
+//       Access: Public
+//  Description: Returns true if two matrices are memberwise equal
+//               within a default tolerance based on the numeric type.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LMatrix4)::
+almost_equal(const FLOATNAME(LMatrix4) &other) const {
+  return almost_equal(other, NEARLY_ZERO(FLOATTYPE));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::output
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix4)::
+output(ostream &out) const {
+  out << "[ " 
+      << MAYBE_ZERO((*this)(0, 0)) << " "
+      << MAYBE_ZERO((*this)(0, 1)) << " " 
+      << MAYBE_ZERO((*this)(0, 2)) << " "
+      << MAYBE_ZERO((*this)(0, 3))
+      << " ] [ "
+      << MAYBE_ZERO((*this)(1, 0)) << " "
+      << MAYBE_ZERO((*this)(1, 1)) << " " 
+      << MAYBE_ZERO((*this)(1, 2)) << " "
+      << MAYBE_ZERO((*this)(1, 3))
+      << " ] [ "
+      << MAYBE_ZERO((*this)(2, 0)) << " "
+      << MAYBE_ZERO((*this)(2, 1)) << " " 
+      << MAYBE_ZERO((*this)(2, 2)) << " "
+      << MAYBE_ZERO((*this)(2, 3))
+      << " ] [ "
+      << MAYBE_ZERO((*this)(3, 0)) << " "
+      << MAYBE_ZERO((*this)(3, 1)) << " " 
+      << MAYBE_ZERO((*this)(3, 2)) << " "
+      << MAYBE_ZERO((*this)(3, 3))
+      << " ]";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::write
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LMatrix4)::
+write(ostream &out, int indent_level) const {
+  indent(out, indent_level)
+    << MAYBE_ZERO((*this)(0, 0)) << " "
+    << MAYBE_ZERO((*this)(0, 1)) << " " 
+    << MAYBE_ZERO((*this)(0, 2)) << " "
+    << MAYBE_ZERO((*this)(0, 3))
+    << "\n";
+  indent(out, indent_level)
+    << MAYBE_ZERO((*this)(1, 0)) << " "
+    << MAYBE_ZERO((*this)(1, 1)) << " " 
+    << MAYBE_ZERO((*this)(1, 2)) << " "
+    << MAYBE_ZERO((*this)(1, 3))
+    << "\n";
+  indent(out, indent_level)
+    << MAYBE_ZERO((*this)(2, 0)) << " "
+    << MAYBE_ZERO((*this)(2, 1)) << " " 
+    << MAYBE_ZERO((*this)(2, 2)) << " "
+    << MAYBE_ZERO((*this)(2, 3))
+    << "\n";
+  indent(out, indent_level)
+    << MAYBE_ZERO((*this)(3, 0)) << " "
+    << MAYBE_ZERO((*this)(3, 1)) << " " 
+    << MAYBE_ZERO((*this)(3, 2)) << " "
+    << MAYBE_ZERO((*this)(3, 3))
+    << "\n";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::transpose
+//  Description: Transposes the given matrix and returns it.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4)
+transpose(const FLOATNAME(LMatrix4) &a) {
+  FLOATNAME(LMatrix4) result;
+  result.transpose_from(a);
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LMatrix4::invert
+//  Description: Inverts the given matrix and returns it.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4)
+invert(const FLOATNAME(LMatrix4) &a) {
+  FLOATNAME(LMatrix4) result;
+  bool nonsingular = result.invert_from(a);
+  nassertr(nonsingular, FLOATNAME(LMatrix4)::ident_mat());
+  return result;
+}

+ 13 - 0
panda/src/linmath/lorientation.cxx

@@ -0,0 +1,13 @@
+// Filename: lorientation.h
+// Created by:  frang, charles (23Jun00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "lorientation.h"
+
+#include "fltnames.h"
+#include "lorientation_src.cxx"
+
+#include "dblnames.h"
+#include "lorientation_src.cxx"
+

+ 19 - 0
panda/src/linmath/lorientation.h

@@ -0,0 +1,19 @@
+// Filename: lorientation.h
+// Created by:  frang, charles (23Jun00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef __LORIENTATION_H__
+#define __LORIENTATION_H__
+
+#include <pandabase.h>
+#include <notify.h>
+#include "lquaternion.h"
+
+#include "fltnames.h"
+#include "lorientation_src.h"
+
+#include "dblnames.h"
+#include "lorientation_src.h"
+
+#endif /* __LORIENTATION_H__ */

+ 93 - 0
panda/src/linmath/lorientation_src.I

@@ -0,0 +1,93 @@
+// Filename: lorientation_src.h
+// Created by:  frang, charles (23Jun00)
+// 
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: LOrientation::Default Constructor
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LOrientation)::
+FLOATNAME(LOrientation)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LOrientation::Copy Constructor
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LOrientation)::
+FLOATNAME(LOrientation)(const FLOATNAME(LQuaternion)& c) :
+  FLOATNAME(LQuaternion)(c) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LOrientation::Constructor
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LOrientation)::
+FLOATNAME(LOrientation)(FLOATTYPE r, FLOATTYPE i, FLOATTYPE j, FLOATTYPE k) :
+  FLOATNAME(LQuaternion)(r, i, j, k) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LOrientation::Constructor
+//       Access: public
+//  Description: vector + twist
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LOrientation)::
+FLOATNAME(LOrientation)(const FLOATNAME(LVector3) &point_at, float twist) {
+  float radians = twist * ((float) MathNumbers::pi / 180.0f);
+  float theta_over_2 = radians / 2.0f;
+  float sin_to2 = sinf(theta_over_2);
+
+  set_r(cosf(theta_over_2));
+  set_i(point_at[0] * sin_to2);
+  set_j(point_at[1] * sin_to2);
+  set_k(point_at[2] * sin_to2);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LOrientation::Constructor
+//       Access: public
+//  Description: matrix3
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LOrientation)::
+FLOATNAME(LOrientation)(const FLOATNAME(LMatrix3) &m) {
+  set_from_matrix(m);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LOrientation::Constructor
+//       Access: public
+//  Description: matrix4
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LOrientation)::
+FLOATNAME(LOrientation)(const FLOATNAME(LMatrix4) &m) {
+  set_from_matrix(m);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LOrientation::operator *
+//       Access: public
+//  Description: Orientation * rotation = Orientation
+//               Applies an rotation to an orientation.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LOrientation) FLOATNAME(LOrientation)::
+operator *(const FLOATNAME(LQuaternion)& other) const {
+  return multiply(other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LOrientation::operator *
+//       Access: public
+//  Description: Orientation * Orientation
+//               This is a meaningless operation, and will always
+//               simply return the rhs.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LOrientation) FLOATNAME(LOrientation)::
+operator *(const FLOATNAME(LOrientation)& other) const {
+  return other;
+}

+ 13 - 0
panda/src/linmath/lpoint2.cxx

@@ -0,0 +1,13 @@
+// Filename: lpoint2.cxx
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "lpoint2.h"
+
+#include "fltnames.h"
+#include "lpoint2_src.cxx"
+
+#include "dblnames.h"
+#include "lpoint2_src.cxx"
+

+ 21 - 0
panda/src/linmath/lpoint2.h

@@ -0,0 +1,21 @@
+// Filename: lpoint2.h
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef LPOINT2_H
+#define LPOINT2_H
+
+#include <pandabase.h>
+
+#include "lvecBase2.h"
+#include "lvector2.h"
+
+#include "fltnames.h"
+#include "lpoint2_src.h"
+
+#include "dblnames.h"
+#include "lpoint2_src.h"
+
+
+#endif

+ 177 - 0
panda/src/linmath/lpoint2_src.I

@@ -0,0 +1,177 @@
+// Filename: lpoint2_src.I
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::Default Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint2)::
+FLOATNAME(LPoint2)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint2)::
+FLOATNAME(LPoint2)(const FLOATNAME(LVecBase2) &copy) : FLOATNAME(LVecBase2)(copy) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint2) &FLOATNAME(LPoint2)::
+operator = (const FLOATNAME(LVecBase2) &copy) {
+  FLOATNAME(LVecBase2)::operator = (copy);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::Copy Fill Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint2) &FLOATNAME(LPoint2)::
+operator = (FLOATTYPE fill_value) {
+  FLOATNAME(LVecBase2)::operator = (fill_value);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint2)::
+FLOATNAME(LPoint2)(FLOATTYPE fill_value) :
+  FLOATNAME(LVecBase2)(fill_value) 
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint2)::
+FLOATNAME(LPoint2)(FLOATTYPE x, FLOATTYPE y) : 
+  FLOATNAME(LVecBase2)(x, y) 
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::zero Named Constructor
+//       Access: Public
+//  Description: Returns a zero-length point.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LPoint2) &FLOATNAME(LPoint2)::
+zero() {
+  return (const FLOATNAME(LPoint2) &)FLOATNAME(LVecBase2)::zero();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::unit_x Named Constructor
+//       Access: Public
+//  Description: Returns a unit X point.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LPoint2) &FLOATNAME(LPoint2)::
+unit_x() {
+  return (const FLOATNAME(LPoint2) &)FLOATNAME(LVecBase2)::unit_x();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::unit_y Named Constructor
+//       Access: Public
+//  Description: Returns a unit Y point.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LPoint2) &FLOATNAME(LPoint2)::
+unit_y() {
+  return (const FLOATNAME(LPoint2) &)FLOATNAME(LVecBase2)::unit_y();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::unary -
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint2) FLOATNAME(LPoint2)::
+operator - () const {
+  return FLOATNAME(LVecBase2)::operator - ();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::point + vecbase
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2) FLOATNAME(LPoint2)::
+operator + (const FLOATNAME(LVecBase2) &other) const {
+  return FLOATNAME(LVecBase2)::operator + (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::point + vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint2) FLOATNAME(LPoint2)::
+operator + (const FLOATNAME(LVector2) &other) const {
+  return FLOATNAME(LVecBase2)::operator + (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::point - vecbase
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2) FLOATNAME(LPoint2)::
+operator - (const FLOATNAME(LVecBase2) &other) const {
+  return FLOATNAME(LVecBase2)::operator - (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::point - point
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector2) FLOATNAME(LPoint2)::
+operator - (const FLOATNAME(LPoint2) &other) const {
+  return FLOATNAME(LVecBase2)::operator - (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::point - vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint2) FLOATNAME(LPoint2)::
+operator - (const FLOATNAME(LVector2) &other) const {
+  return FLOATNAME(LVecBase2)::operator - (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::operator * scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint2) FLOATNAME(LPoint2)::
+operator * (FLOATTYPE scalar) const {
+  return FLOATNAME(LPoint2)(FLOATNAME(LVecBase2)::operator * (scalar));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint2::operator / scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint2) FLOATNAME(LPoint2)::
+operator / (FLOATTYPE scalar) const {
+  return FLOATNAME(LPoint2)(FLOATNAME(LVecBase2)::operator / (scalar));
+}

+ 13 - 0
panda/src/linmath/lpoint3.cxx

@@ -0,0 +1,13 @@
+// Filename: lpoint2.cxx
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "lpoint3.h"
+
+#include "fltnames.h"
+#include "lpoint3_src.cxx"
+
+#include "dblnames.h"
+#include "lpoint3_src.cxx"
+

+ 22 - 0
panda/src/linmath/lpoint3.h

@@ -0,0 +1,22 @@
+// Filename: lpoint3.h
+// Created by:  drose (25Sep99)
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef LPOINT3_H
+#define LPOINT3_H
+
+#include <pandabase.h>
+
+#include "coordinateSystem.h"
+#include "lvecBase3.h"
+#include "lvector3.h"
+
+#include "fltnames.h"
+#include "lpoint3_src.h"
+
+#include "dblnames.h"
+#include "lpoint3_src.h"
+
+
+#endif

+ 224 - 0
panda/src/linmath/lpoint3_src.I

@@ -0,0 +1,224 @@
+// Filename: lpoint3_src.I
+// Created by:  drose (25Sep99)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::Default Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint3)::
+FLOATNAME(LPoint3)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint3)::
+FLOATNAME(LPoint3)(const FLOATNAME(LVecBase3) &copy) : FLOATNAME(LVecBase3)(copy) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint3) &FLOATNAME(LPoint3)::
+operator = (const FLOATNAME(LVecBase3) &copy) {
+  FLOATNAME(LVecBase3)::operator = (copy);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::Copy Fill Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint3) &FLOATNAME(LPoint3)::
+operator = (FLOATTYPE fill_value) {
+  FLOATNAME(LVecBase3)::operator = (fill_value);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint3)::
+FLOATNAME(LPoint3)(FLOATTYPE fill_value) :
+  FLOATNAME(LVecBase3)(fill_value) 
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint3)::
+FLOATNAME(LPoint3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z) : 
+  FLOATNAME(LVecBase3)(x, y, z) 
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::zero Named Constructor
+//       Access: Public
+//  Description: Returns a zero-length point.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LPoint3) &FLOATNAME(LPoint3)::
+zero() {
+  return (const FLOATNAME(LPoint3) &)FLOATNAME(LVecBase3)::zero();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::unit_x Named Constructor
+//       Access: Public
+//  Description: Returns a unit X point.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LPoint3) &FLOATNAME(LPoint3)::
+unit_x() {
+  return (const FLOATNAME(LPoint3) &)FLOATNAME(LVecBase3)::unit_x();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::unit_y Named Constructor
+//       Access: Public
+//  Description: Returns a unit Y point.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LPoint3) &FLOATNAME(LPoint3)::
+unit_y() {
+  return (const FLOATNAME(LPoint3) &)FLOATNAME(LVecBase3)::unit_y();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::unit_z Named Constructor
+//       Access: Public
+//  Description: Returns a unit Z point.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LPoint3) &FLOATNAME(LPoint3)::
+unit_z() {
+  return (const FLOATNAME(LPoint3) &)FLOATNAME(LVecBase3)::unit_z();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::unary -
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint3) FLOATNAME(LPoint3)::
+operator - () const {
+  return FLOATNAME(LVecBase3)::operator - ();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::point + vecbase
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LPoint3)::
+operator + (const FLOATNAME(LVecBase3) &other) const {
+  return FLOATNAME(LVecBase3)::operator + (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::point + vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint3) FLOATNAME(LPoint3)::
+operator + (const FLOATNAME(LVector3) &other) const {
+  return FLOATNAME(LVecBase3)::operator + (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::point - vecbase
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LPoint3)::
+operator - (const FLOATNAME(LVecBase3) &other) const {
+  return FLOATNAME(LVecBase3)::operator - (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::point - point
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) FLOATNAME(LPoint3)::
+operator - (const FLOATNAME(LPoint3) &other) const {
+  return FLOATNAME(LVecBase3)::operator - (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::point - vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint3) FLOATNAME(LPoint3)::
+operator - (const FLOATNAME(LVector3) &other) const {
+  return FLOATNAME(LVecBase3)::operator - (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::cross
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint3) FLOATNAME(LPoint3)::
+cross(const FLOATNAME(LVecBase3) &other) const {
+  return FLOATNAME(LVecBase3)::cross(other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::operator * scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint3) FLOATNAME(LPoint3)::
+operator * (FLOATTYPE scalar) const {
+  return FLOATNAME(LPoint3)(FLOATNAME(LVecBase3)::operator * (scalar));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::operator / scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint3) FLOATNAME(LPoint3)::
+operator / (FLOATTYPE scalar) const {
+  return FLOATNAME(LPoint3)(FLOATNAME(LVecBase3)::operator / (scalar));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::origin
+//       Access: Public, Static
+//  Description: Returns the origin of the indicated coordinate
+//               system.  This is always 0, 0, 0 with all of our
+//               existing coordinate systems; it's hard to imagine it
+//               ever being different.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint3) FLOATNAME(LPoint3)::
+origin(CoordinateSystem) {
+  return FLOATNAME(LPoint3)(0.0, 0.0, 0.0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::rfu
+//       Access: Public, Static
+//  Description: Returns a point described by right, forward, up
+//               displacements from the origin, wherever that maps to
+//               in the given coordinate system.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint3) FLOATNAME(LPoint3)::
+rfu(FLOATTYPE right_v, FLOATTYPE fwd_v, FLOATTYPE up_v,
+    CoordinateSystem cs) {
+  return origin(cs) + 
+    FLOATNAME(LVector3)::rfu(right_v, fwd_v, up_v, cs);
+}

+ 13 - 0
panda/src/linmath/lpoint4.cxx

@@ -0,0 +1,13 @@
+// Filename: lpoint2.cxx
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "lpoint4.h"
+
+#include "fltnames.h"
+#include "lpoint4_src.cxx"
+
+#include "dblnames.h"
+#include "lpoint4_src.cxx"
+

+ 20 - 0
panda/src/linmath/lpoint4.h

@@ -0,0 +1,20 @@
+// Filename: lpoint4.h
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef LPOINT4_H
+#define LPOINT4_H
+
+#include <pandabase.h>
+
+#include "lvecBase4.h"
+#include "lvector4.h"
+
+#include "fltnames.h"
+#include "lpoint4_src.h"
+
+#include "dblnames.h"
+#include "lpoint4_src.h"
+
+#endif

+ 197 - 0
panda/src/linmath/lpoint4_src.I

@@ -0,0 +1,197 @@
+// Filename: lpoint4_src.I
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::Default Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint4)::
+FLOATNAME(LPoint4)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint4)::
+FLOATNAME(LPoint4)(const FLOATNAME(LVecBase4) &copy) : FLOATNAME(LVecBase4)(copy) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint4) &FLOATNAME(LPoint4)::
+operator = (const FLOATNAME(LVecBase4) &copy) {
+  FLOATNAME(LVecBase4)::operator = (copy);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::Copy Fill Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint4) &FLOATNAME(LPoint4)::
+operator = (FLOATTYPE fill_value) {
+  FLOATNAME(LVecBase4)::operator = (fill_value);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint4)::
+FLOATNAME(LPoint4)(FLOATTYPE fill_value) :
+  FLOATNAME(LVecBase4)(fill_value) 
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint4)::
+FLOATNAME(LPoint4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w) : 
+  FLOATNAME(LVecBase4)(x, y, z, w) 
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::zero Named Constructor
+//       Access: Public
+//  Description: Returns a zero-length point.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LPoint4) &FLOATNAME(LPoint4)::
+zero() {
+  return (const FLOATNAME(LPoint4) &)FLOATNAME(LVecBase4)::zero();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::unit_x Named Constructor
+//       Access: Public
+//  Description: Returns a unit X point.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LPoint4) &FLOATNAME(LPoint4)::
+unit_x() {
+  return (const FLOATNAME(LPoint4) &)FLOATNAME(LVecBase4)::unit_x();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::unit_y Named Constructor
+//       Access: Public
+//  Description: Returns a unit Y point.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LPoint4) &FLOATNAME(LPoint4)::
+unit_y() {
+  return (const FLOATNAME(LPoint4) &)FLOATNAME(LVecBase4)::unit_y();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::unit_z Named Constructor
+//       Access: Public
+//  Description: Returns a unit Z point.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LPoint4) &FLOATNAME(LPoint4)::
+unit_z() {
+  return (const FLOATNAME(LPoint4) &)FLOATNAME(LVecBase4)::unit_z();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::unit_w Named Constructor
+//       Access: Public
+//  Description: Returns a unit W point.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LPoint4) &FLOATNAME(LPoint4)::
+unit_w() {
+  return (const FLOATNAME(LPoint4) &)FLOATNAME(LVecBase4)::unit_w();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::unary -
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint4) FLOATNAME(LPoint4)::
+operator - () const {
+  return FLOATNAME(LVecBase4)::operator - ();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::point + vecbase
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4) FLOATNAME(LPoint4)::
+operator + (const FLOATNAME(LVecBase4) &other) const {
+  return FLOATNAME(LVecBase4)::operator + (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::point + vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint4) FLOATNAME(LPoint4)::
+operator + (const FLOATNAME(LVector4) &other) const {
+  return FLOATNAME(LVecBase4)::operator + (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::point - vecbase
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4) FLOATNAME(LPoint4)::
+operator - (const FLOATNAME(LVecBase4) &other) const {
+  return FLOATNAME(LVecBase4)::operator - (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::point - point
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector4) FLOATNAME(LPoint4)::
+operator - (const FLOATNAME(LPoint4) &other) const {
+  return FLOATNAME(LVecBase4)::operator - (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::point - vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint4) FLOATNAME(LPoint4)::
+operator - (const FLOATNAME(LVector4) &other) const {
+  return FLOATNAME(LVecBase4)::operator - (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::operator * scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint4) FLOATNAME(LPoint4)::
+operator * (FLOATTYPE scalar) const {
+  return FLOATNAME(LPoint4)(FLOATNAME(LVecBase4)::operator * (scalar));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::operator / scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LPoint4) FLOATNAME(LPoint4)::
+operator / (FLOATTYPE scalar) const {
+  return FLOATNAME(LPoint4)(FLOATNAME(LVecBase4)::operator / (scalar));
+}

+ 13 - 0
panda/src/linmath/lquaternion.cxx

@@ -0,0 +1,13 @@
+// Filename: lquaternion.cxx
+// Created by:  frang (06Jun00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "lquaternion.h"
+
+#include "fltnames.h"
+#include "lquaternion_src.cxx"
+
+#include "dblnames.h"
+#include "lquaternion_src.cxx"
+

+ 25 - 0
panda/src/linmath/lquaternion.h

@@ -0,0 +1,25 @@
+// Filename: lquaternion.h
+// Created by:  frang (06Jun00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef LQUATERNION_H
+#define LQUATERNION_H
+
+#include "lmatrix.h"
+#include "lvector3.h"
+#include "lvector4.h"
+#include "nearly_zero.h"
+#include "cmath.h"
+#include "deg_2_rad.h"
+
+#include <notify.h>
+
+#include "fltnames.h"
+#include "lquaternion_src.h"
+
+#include "dblnames.h"
+#include "lquaternion_src.h"
+
+
+#endif /* __LQUATERNION_H__ */

+ 293 - 0
panda/src/linmath/lquaternion_src.I

@@ -0,0 +1,293 @@
+// Filename: lquaternion_src.I
+// Created by:  frang (06Jun00)
+// 
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::Default Constructor
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LQuaternion)::
+FLOATNAME(LQuaternion)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::Copy Constructor
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LQuaternion)::
+FLOATNAME(LQuaternion)(const FLOATNAME(LQuaternion) &c) : 
+  FLOATNAME(LVecBase4)(c) 
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::Constructor
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LQuaternion)::
+FLOATNAME(LQuaternion)(FLOATTYPE r, FLOATTYPE i, FLOATTYPE j, FLOATTYPE k) {
+  set(r, i, j, k);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::multiply
+//       Access: protected
+//  Description: actual multiply call (non virtual)
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LQuaternion) FLOATNAME(LQuaternion)::
+multiply(const FLOATNAME(LQuaternion)& rhs) const {
+  FLOATTYPE r = (_data[0] * rhs._data[0]) - (_data[1] * rhs._data[1]) - (_data[2] * rhs._data[2]) - (_data[3] * rhs._data[3]);
+  FLOATTYPE i = (_data[1] * rhs._data[0]) + (_data[0] * rhs._data[1]) - (_data[3] * rhs._data[2]) + (_data[2] * rhs._data[3]);
+  FLOATTYPE j = (_data[2] * rhs._data[0]) + (_data[3] * rhs._data[1]) + (_data[0] * rhs._data[2]) - (_data[1] * rhs._data[3]);
+  FLOATTYPE k = (_data[3] * rhs._data[0]) - (_data[2] * rhs._data[1]) + (_data[1] * rhs._data[2]) + (_data[0] * rhs._data[3]);
+
+  return FLOATNAME(LQuaternion)(r, i , j, k);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::Multiply Operator
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LQuaternion) FLOATNAME(LQuaternion)::
+operator *(const FLOATNAME(LQuaternion)& c) {
+  return multiply(c);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::Multiply Assignment Operator
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LQuaternion)& FLOATNAME(LQuaternion)::
+operator *=(const FLOATNAME(LQuaternion)& c) {
+  (*this) = operator*(c);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::Multiply Operator
+//       Access: public
+//  Description: Quat * Matrix = matrix
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) FLOATNAME(LQuaternion)::
+operator *(const FLOATNAME(LMatrix3) &m) {  
+  FLOATNAME(LMatrix3) result;
+  extract_to_matrix(result);
+  return result * m;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::Multiply Operator
+//       Access: public
+//  Description: Quat * Matrix = matrix
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) FLOATNAME(LQuaternion)::
+operator *(const FLOATNAME(LMatrix4) &m) {
+  FLOATNAME(LMatrix3) m_upper_3 = m.get_upper_3();
+  FLOATNAME(LMatrix3) this_quat;
+  extract_to_matrix(this_quat);
+
+  FLOATNAME(LMatrix4) result;
+  result.set_upper_3(this_quat * m_upper_3);
+  result.set_row(3, m.get_row(3));
+  result.set_col(3, m.get_col(3));
+
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::almost_equal
+//       Access: public
+//  Description: Returns true if two quaternions are memberwise equal
+//               within a specified tolerance.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LQuaternion)::
+almost_equal(const FLOATNAME(LQuaternion)& c, FLOATTYPE threshold) const {
+  return (IS_THRESHOLD_EQUAL(_data[0], c._data[0], threshold) &&
+	  IS_THRESHOLD_EQUAL(_data[1], c._data[1], threshold) &&
+	  IS_THRESHOLD_EQUAL(_data[2], c._data[2], threshold) &&
+	  IS_THRESHOLD_EQUAL(_data[3], c._data[3], threshold));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::almost_equal
+//       Access: public
+//  Description: Returns true if two quaternions are memberwise equal
+//               within a default tolerance based on the numeric type.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LQuaternion)::
+almost_equal(const FLOATNAME(LQuaternion)& c) const {
+  return almost_equal(c, NEARLY_ZERO(FLOATTYPE));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::output
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LQuaternion)::
+output(ostream& os) const {
+  os << MAYBE_ZERO(_data[0]) << " + "
+     << MAYBE_ZERO(_data[1]) << "i + "
+     << MAYBE_ZERO(_data[2]) << "j + "
+     << MAYBE_ZERO(_data[3]) << "k";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::get_r
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LQuaternion)::
+get_r() const {
+  return _data[0];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::get_i
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LQuaternion)::
+get_i() const {
+  return _data[1];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::get_j
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LQuaternion)::
+get_j() const {
+  return _data[2];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::get_k
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LQuaternion)::
+get_k() const {
+  return _data[3];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::set_r
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LQuaternion)::
+set_r(FLOATTYPE r) {
+  _data[0] = r;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::set_i
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LQuaternion)::
+set_i(FLOATTYPE i) {
+  _data[1] = i;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::set_j
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LQuaternion)::
+set_j(FLOATTYPE j) {
+  _data[2] = j;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::set_k
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LQuaternion)::
+set_k(FLOATTYPE k) {
+  _data[3] = k;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FLOATNAME(LQuaternion)::normalize
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LQuaternion)::
+normalize() {
+  FLOATTYPE l2 = (*this).dot(*this);
+  if (l2 == (FLOATTYPE)0.0) {
+    set(0.0, 0.0, 0.0, 0.0);
+    return false;
+
+  } else if (!IS_THRESHOLD_EQUAL(l2, 1.0, NEARLY_ZERO(FLOATTYPE) * NEARLY_ZERO(FLOATTYPE))) {
+    (*this) /= csqrt(l2);
+  }
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: set_from_matrix
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LQuaternion)::
+set_from_matrix(const FLOATNAME(LMatrix4) &m) {
+  set_from_matrix(m.get_upper_3());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: operator *(Matrix3, Quat)
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix3) operator *(const FLOATNAME(LMatrix3) &m,
+			     const FLOATNAME(LQuaternion) &q) {
+  FLOATNAME(LMatrix3) q_matrix;
+  q.extract_to_matrix(q_matrix);
+
+  return m * q_matrix;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: operator *(Matrix4, Quat)
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LMatrix4) operator *(const FLOATNAME(LMatrix4) &m,
+			     const FLOATNAME(LQuaternion) &q) {
+  FLOATNAME(LMatrix4) q_matrix;
+  q.extract_to_matrix(q_matrix);
+
+  // preserve the homogeneous coords and the translate
+  FLOATNAME(LVector4) m_row3 = m.get_row(3);
+  FLOATNAME(LVector4) m_col3 = m.get_col(3);
+
+  q_matrix = m * q_matrix;
+  q_matrix.set_row(3, m_row3);
+  q_matrix.set_col(3, m_col3);
+
+  return q_matrix;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LQuaternion::ident_quat
+//       Access: Public, Static
+//  Description: Returns an identity quaternion.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LQuaternion) &FLOATNAME(LQuaternion)::
+ident_quat() {
+  return _ident_quat;
+}

+ 13 - 0
panda/src/linmath/lrotation.cxx

@@ -0,0 +1,13 @@
+// Filename: lrotation_src.h
+// Created by:  frang, charles (23Jun00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "lrotation.h"
+
+#include "fltnames.h"
+#include "lrotation_src.cxx"
+
+#include "dblnames.h"
+#include "lrotation_src.cxx"
+

+ 21 - 0
panda/src/linmath/lrotation.h

@@ -0,0 +1,21 @@
+// Filename: lrotation.h
+// Created by:  frang, charles (07Jun00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef __LROTATION_H__
+#define __LROTATION_H__
+
+#include <pandabase.h>
+#include "lquaternion.h"
+#include "cmath.h"
+
+#include <notify.h>
+
+#include "fltnames.h"
+#include "lrotation_src.h"
+
+#include "dblnames.h"
+#include "lrotation_src.h"
+
+#endif /* __LROTATION_H__ */

+ 105 - 0
panda/src/linmath/lrotation_src.I

@@ -0,0 +1,105 @@
+// Filename: lrotation_src.I
+// Created by:  frang, charles (23Jun00)
+// 
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: LRotation::Default Constructor
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LRotation)::
+FLOATNAME(LRotation)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LRotation::Copy Constructor
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LRotation)::
+FLOATNAME(LRotation)(const FLOATNAME(LQuaternion)& c) : 
+  FLOATNAME(LQuaternion)(c) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LRotation::Constructor
+//       Access: public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LRotation)::
+FLOATNAME(LRotation)(FLOATTYPE r, FLOATTYPE i, FLOATTYPE j, FLOATTYPE k) : 
+  FLOATNAME(LQuaternion)(r, i, j, k) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LRotation::Constructor
+//       Access: public
+//  Description: lmatrix3
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LRotation)::
+FLOATNAME(LRotation)(const FLOATNAME(LMatrix3) &m) {
+  set_from_matrix(m);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LRotation::Constructor
+//       Access: public
+//  Description: lmatrix4
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LRotation)::
+FLOATNAME(LRotation)(const FLOATNAME(LMatrix4) &m) {
+  set_from_matrix(m);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LRotation::Constructor
+//       Access: public
+//  Description: axis + angle (in degrees)
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LRotation)::
+FLOATNAME(LRotation)(const FLOATNAME(LVector3) &axis, FLOATTYPE angle) {
+  FLOATTYPE radians = angle * ((FLOATTYPE) MathNumbers::pi / (FLOATTYPE)180.0);
+  FLOATTYPE theta_over_2 = radians / (FLOATTYPE)2.0;
+  FLOATTYPE sin_to2 = csin(theta_over_2);
+
+  set_r(ccos(theta_over_2));
+  set_i(axis[0] * sin_to2);
+  set_j(axis[1] * sin_to2);
+  set_k(axis[2] * sin_to2);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LRotation::Constructor
+//       Access: public
+//  Description: Sets the rotation from the given Euler angles.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LRotation)::
+FLOATNAME(LRotation)(FLOATTYPE h, FLOATTYPE p, FLOATTYPE r) {
+  set_hpr(FLOATNAME(LVecBase3)(h, p, r));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LRotation::operator *
+//       Access: public
+//  Description: Rotation * Rotation = Rotation
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LRotation) FLOATNAME(LRotation)::
+operator*(const FLOATNAME(LRotation)& other) const {
+  return multiply(other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LRotation::operator *
+//       Access: public
+//  Description: Rotation * Orientation = Orientation
+//               This is another meaningless operation, attempting
+//               to apply an orientation to a rotation.  It simply
+//               returns the rhs.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LQuaternion) FLOATNAME(LRotation)::
+operator*(const FLOATNAME(LQuaternion)& other) const {
+  return other;
+}
+
+

+ 4 - 0
panda/src/linmath/luse.I

@@ -0,0 +1,4 @@
+// Filename: luse.I
+// Created by:  drose (13Jan99)
+// 
+////////////////////////////////////////////////////////////////////

+ 68 - 0
panda/src/linmath/luse.N

@@ -0,0 +1,68 @@
+
+renametype LPoint2f LPoint2f
+renametype LPoint3f LPoint3f
+renametype LPoint4f LPoint4f
+renametype LPoint2d LPoint2d
+renametype LPoint3d LPoint3d
+renametype LPoint4d LPoint4d
+
+renametype LVecBase2f LVecBase2f
+renametype LVecBase3f LVecBase3f
+renametype LVecBase4f LVecBase4f
+renametype LVecBase2d LVecBase2d
+renametype LVecBase3d LVecBase3d
+renametype LVecBase4d LVecBase4d
+
+renametype LVector2f LVector2f
+renametype LVector3f LVector3f
+renametype LVector4f LVector4f
+renametype LVector2d LVector2d
+renametype LVector3d LVector3d
+renametype LVector4d LVector4d
+
+renametype LMatrix3f LMatrix3f
+renametype LMatrix4f LMatrix4f
+renametype LMatrix3d LMatrix3d
+renametype LMatrix4d LMatrix4d
+
+renametype LQuaternionf LQuaternionf
+renametype LRotationf LRotationf
+renametype LOrientationf LOrientationf
+
+renametype LQuaterniond LQuaterniond
+renametype LRotationd LRotationd
+renametype LOrientationd LOrientationd
+
+forcetype PTA_Vertexf
+renametype PTA_Vertexf PTA_Vertexf
+forcetype PTA_Normalf
+renametype PTA_Normalf PTA_Normalf
+forcetype PTA_TexCoordf
+renametype PTA_TexCoordf PTA_TexCoordf
+forcetype PTA_Colorf
+renametype PTA_Colorf PTA_Colorf
+
+# We don't want to accidentally include any of the _src files in the
+# generated output, since these files aren't intended to be included by
+# anything but their associated .h file.
+noinclude compose_matrix_src.h
+noinclude lcast_to.h
+noinclude lcast_to_src.h
+noinclude lmat_ops_src.h
+noinclude lmatrix3_src.h
+noinclude lmatrix4_src.h
+noinclude lorientation_src.h
+noinclude lpoint2_src.h
+noinclude lpoint3_src.h
+noinclude lpoint4_src.h
+noinclude lquaternion_src.h
+noinclude lrotation_src.h
+noinclude lvec2_ops_src.h
+noinclude lvec3_ops_src.h
+noinclude lvec4_ops_src.h
+noinclude lvecBase2_src.h
+noinclude lvecBase3_src.h
+noinclude lvecBase4_src.h
+noinclude lvector2_src.h
+noinclude lvector3_src.h
+noinclude lvector4_src.h

+ 6 - 0
panda/src/linmath/luse.cxx

@@ -0,0 +1,6 @@
+// Filename: luse.cxx
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "luse.h"

+ 87 - 0
panda/src/linmath/luse.h

@@ -0,0 +1,87 @@
+// Filename: luse.h
+// Created by:  drose (13Jan99)
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef LUSE_H
+#define LUSE_H
+
+////////////////////////////////////////////////////////////////////
+//
+// This file defines a number of vector-based classes that are
+// designed for specific uses.  These all inherit from
+// LVecBase[234][fd], which is the base of all linear algebra vectors.
+//
+// LPoint[234][fd]
+//
+//   This should be used to represent a specific point in space.  It
+//   inherits most properties from LVecBase.
+//
+// LVector[234][fd]
+//
+//   This should be used to represent a vector, or a distance between
+//   two points in space.
+//
+// The distinction between LPoint and LVector is worth emphasizing.
+// They differ in some subtle typing behavior (vector - vector =
+// vector, point + vector = point, point - point = vector) and also in
+// the way they are transformed when multiplied by a matrix (a point
+// gets the translation component of the matrix, while the vector does
+// not).  Also, vector has length() and normalize() functions defined
+// for it, while point does not.
+//
+// LPoint and LVector should be used whenever the concept of "point"
+// or "vector" applies.  If neither applies--for instance, if you are
+// storing a plane equation or some such nonsense--use the base class,
+// LVecBase.
+//
+// This file also typedefs the following:
+//
+// Vertex[fd]
+// Normal[fd]
+// TexCoord[fd]
+// Color[fd]
+// RGBColor[fd]
+//
+// These classes are typedefs of LPoint or LVector, as appropriate,
+// and are intended to store a specific kind of rendering attribute.
+// (Color is a four-component color; RGBColor is three-component.)
+//
+////////////////////////////////////////////////////////////////////
+
+#include <pandabase.h>
+
+#include "lvec2_ops.h"
+#include "lvec3_ops.h"
+#include "lvec4_ops.h"
+#include "lmat_ops.h"
+#include "lmatrix.h"
+#include "lquaternion.h"
+#include "lrotation.h"
+#include "lorientation.h"
+#include "lcast_to.h"
+
+// This macro defines the cast-to-another-numeric-type operator for
+// all of the things defined in this package.  It works by virtue of
+// there being an appropriate lcast_to() template function defined for
+// each class.
+
+#define LCAST(numeric_type, object) lcast_to((numeric_type *)0, object)
+
+
+// Now we define some handy typedefs for these classes.
+typedef LPoint3f Vertexf;
+typedef LVector3f Normalf;
+typedef LPoint2f TexCoordf;
+typedef LVecBase4f Colorf;
+typedef LVecBase3f RGBColorf;
+
+typedef LPoint3d Vertexd;
+typedef LVector3d Normald;
+typedef LPoint2d TexCoordd;
+typedef LVecBase4d Colord;
+typedef LVecBase3d RGBColord;
+
+
+#endif
+

+ 21 - 0
panda/src/linmath/lvec2_ops.h

@@ -0,0 +1,21 @@
+// Filename: lvec2_ops.h
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef LVEC2_OPS_H
+#define LVEC2_OPS_H
+
+#include <math.h>
+#include "nearly_zero.h"
+#include "lvecBase2.h"
+#include "lpoint2.h"
+#include "lvector2.h"
+
+#include "fltnames.h"
+#include "lvec2_ops_src.h"
+
+#include "dblnames.h"
+#include "lvec2_ops_src.h"
+
+#endif

+ 22 - 0
panda/src/linmath/lvec3_ops.h

@@ -0,0 +1,22 @@
+// Filename: lvec3_ops.h
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef LVEC3_OPS_H
+#define LVEC3_OPS_H
+
+#include <math.h>
+#include "nearly_zero.h"
+#include "lvecBase3.h"
+#include "lpoint3.h"
+#include "lvector3.h"
+
+#include "fltnames.h"
+#include "lvec3_ops_src.h"
+
+#include "dblnames.h"
+#include "lvec3_ops_src.h"
+
+
+#endif

+ 22 - 0
panda/src/linmath/lvec4_ops.h

@@ -0,0 +1,22 @@
+// Filename: lvec4_ops.h
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef LVEC4_OPS_H
+#define LVEC4_OPS_H
+
+#include <math.h>
+#include "nearly_zero.h"
+#include "lvecBase4.h"
+#include "lpoint4.h"
+#include "lvector4.h"
+
+#include "fltnames.h"
+#include "lvec4_ops_src.h"
+
+#include "dblnames.h"
+#include "lvec4_ops_src.h"
+
+
+#endif

+ 13 - 0
panda/src/linmath/lvecBase2.cxx

@@ -0,0 +1,13 @@
+// Filename: lvecBase2.cxx
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "lvecBase2.h"
+
+#include "fltnames.h"
+#include "lvecBase2_src.cxx"
+
+#include "dblnames.h"
+#include "lvecBase2_src.cxx"
+

+ 26 - 0
panda/src/linmath/lvecBase2.h

@@ -0,0 +1,26 @@
+// Filename: lvecBase2.h
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef LVECBASE2_H
+#define LVECBASE2_H
+
+#include <pandabase.h>
+#include <typeHandle.h>
+#include <notify.h>
+#include <datagram.h>
+#include <datagramIterator.h>
+#include "cmath.h"
+#include "nearly_zero.h"
+
+class Datagram;
+class DatagramIterator;
+
+#include "fltnames.h"
+#include "lvecBase2_src.h"
+
+#include "dblnames.h"
+#include "lvecBase2_src.h"
+
+#endif

+ 521 - 0
panda/src/linmath/lvecBase2_src.I

@@ -0,0 +1,521 @@
+// Filename: lvecBase2_src.I
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::Default Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2)::
+FLOATNAME(LVecBase2)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2)::
+FLOATNAME(LVecBase2)(const FLOATNAME(LVecBase2) &copy) {
+  (*this) = copy;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2) &FLOATNAME(LVecBase2)::
+operator = (const FLOATNAME(LVecBase2) &copy) {
+  set(copy[0], copy[1]);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::Fill Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2) &FLOATNAME(LVecBase2)::
+operator = (FLOATTYPE fill_value) {
+  fill(fill_value);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2)::
+FLOATNAME(LVecBase2)(FLOATTYPE fill_value) {
+  fill(fill_value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2)::
+FLOATNAME(LVecBase2)(FLOATTYPE x, FLOATTYPE y) {
+  set(x, y);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::zero Named Constructor
+//       Access: Public
+//  Description: Returns a zero-length vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVecBase2) &FLOATNAME(LVecBase2)::
+zero() {
+  return _zero;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::unit_x Named Constructor
+//       Access: Public
+//  Description: Returns a unit X vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVecBase2) &FLOATNAME(LVecBase2)::
+unit_x() {
+  return _unit_x;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::unit_y Named Constructor
+//       Access: Public
+//  Description: Returns a unit Y vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVecBase2) &FLOATNAME(LVecBase2)::
+unit_y() {
+  return _unit_y;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2)::
+~FLOATNAME(LVecBase2)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::Indexing Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase2)::
+operator [](int i) const {
+  //  nassertr(i >= 0 && i < 2, 0);
+  return _data[i];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::Indexing Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE &FLOATNAME(LVecBase2)::
+operator [](int i) {
+  //  nassertr(i >= 0 && i < 2, _data[0]);
+  return _data[i];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::is_nan
+//       Access: Public
+//  Description: Returns true if any component of the vector is
+//               not-a-number, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase2)::
+is_nan() const {
+  return cnan(_data[0]) || cnan(_data[1]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::get_cell
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase2)::
+get_cell(int i) const {
+  nassertr(i >= 0 && i < 2, 0);
+  return _data[i];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::get_x
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase2)::
+get_x() const {
+  return _data[0];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::get_y
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase2)::
+get_y() const {
+  return _data[1];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::set_cell
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase2)::
+set_cell(int i, FLOATTYPE value) {
+  nassertv(i >= 0 && i < 2);
+  _data[i] = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::set_x
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase2)::
+set_x(FLOATTYPE value) {
+  _data[0] = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::set_y
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase2)::
+set_y(FLOATTYPE value) {
+  _data[1] = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::get_data
+//       Access: Public
+//  Description: Returns the address of the first of the two data
+//               elements in the vector.  The next element
+//               occupies the next position consecutively in memory.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATTYPE *FLOATNAME(LVecBase2)::
+get_data() const {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::get_num_components
+//       Access: Public
+//  Description: Returns the number of elements in the vector, two.
+////////////////////////////////////////////////////////////////////
+INLINE int FLOATNAME(LVecBase2)::
+get_num_components() const {
+  return 2;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::begin
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2)::iterator FLOATNAME(LVecBase2)::
+begin() {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::end
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2)::iterator FLOATNAME(LVecBase2)::
+end() {
+  return begin() + get_num_components();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::begin
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2)::const_iterator FLOATNAME(LVecBase2)::
+begin() const {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::end
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2)::const_iterator FLOATNAME(LVecBase2)::
+end() const {
+  return begin() + get_num_components();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::fill
+//       Access: Public
+//  Description: Sets each element of the vector to the indicated
+//               fill_value.  This is particularly useful for
+//               initializing to zero.
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase2)::
+fill(FLOATTYPE fill_value) {
+  _data[0] = fill_value;
+  _data[1] = fill_value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::set
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase2)::
+set(FLOATTYPE x, FLOATTYPE y) {
+  _data[0] = x;
+  _data[1] = y;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::dot
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase2)::
+dot(const FLOATNAME(LVecBase2) &other) const {
+  return _data[0] * other[0] + _data[1] * other[1];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::operator <
+//       Access: Public
+//  Description: This performs a lexicographical comparison.  It's of
+//               questionable mathematical meaning, but sometimes has
+//               a practical purpose for sorting unique vectors,
+//               especially in an STL container.  Also see
+//               compare_to().
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase2)::
+operator < (const FLOATNAME(LVecBase2) &other) const {
+  return (compare_to(other) < 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::operator ==
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase2)::
+operator == (const FLOATNAME(LVecBase2) &other) const {
+  return (_data[0] == other[0] &&
+	  _data[1] == other[1]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::operator !=
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase2)::
+operator != (const FLOATNAME(LVecBase2) &other) const {
+  return !operator == (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::compare_to
+//       Access: Public
+//  Description: This flavor of compare_to uses a default threshold
+//               value based on the numeric type.
+////////////////////////////////////////////////////////////////////
+INLINE int FLOATNAME(LVecBase2)::
+compare_to(const FLOATNAME(LVecBase2) &other) const {
+  return compare_to(other, NEARLY_ZERO(FLOATTYPE));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::compare_to
+//       Access: Public
+//  Description: Sorts vectors lexicographically, componentwise.
+//               Returns a number less than 0 if this vector sorts
+//               before the other one, greater than zero if it sorts
+//               after, 0 if they are equivalent (within the indicated
+//               tolerance).
+////////////////////////////////////////////////////////////////////
+INLINE int FLOATNAME(LVecBase2)::
+compare_to(const FLOATNAME(LVecBase2) &other, FLOATTYPE threshold) const {
+  if (!IS_THRESHOLD_EQUAL(_data[0], other[0], threshold)) {
+    return (_data[0] < other[0]) ? -1 : 1;
+  }
+  if (!IS_THRESHOLD_EQUAL(_data[1], other[1], threshold)) {
+    return (_data[1] < other[1]) ? -1 : 1;
+  }
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::unary -
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::
+operator - () const {
+  return FLOATNAME(LVecBase2)(-_data[0], -_data[1]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::vector + vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::
+operator + (const FLOATNAME(LVecBase2) &other) const {
+  return FLOATNAME(LVecBase2)(_data[0] + other[0],
+			      _data[1] + other[1]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::vector - vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::
+operator - (const FLOATNAME(LVecBase2) &other) const {
+  return FLOATNAME(LVecBase2)(_data[0] - other[0],
+			      _data[1] - other[1]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::vector * scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::
+operator * (FLOATTYPE scalar) const {
+  return FLOATNAME(LVecBase2)(_data[0] * scalar,
+			      _data[1] * scalar);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::vector / scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::
+operator / (FLOATTYPE scalar) const {
+  return FLOATNAME(LVecBase2)(_data[0] / scalar,
+			      _data[1] / scalar);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::operator +=
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase2)::
+operator += (const FLOATNAME(LVecBase2) &other) {
+  _data[0] += other[0];
+  _data[1] += other[1];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::operator -=
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase2)::
+operator -= (const FLOATNAME(LVecBase2) &other) {
+  _data[0] -= other[0];
+  _data[1] -= other[1];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::operator *=
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase2)::
+operator *= (FLOATTYPE scalar) {
+  _data[0] *= scalar;
+  _data[1] *= scalar;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::operator /=
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase2)::
+operator /= (FLOATTYPE scalar) {
+  _data[0] /= scalar;
+  _data[1] /= scalar;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::almost_equal
+//       Access: Public
+//  Description: Returns true if two vectors are memberwise equal
+//               within a specified tolerance.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase2)::
+almost_equal(const FLOATNAME(LVecBase2) &other, FLOATTYPE threshold) const {
+  return (IS_THRESHOLD_EQUAL(_data[0], other[0], threshold) &&
+	  IS_THRESHOLD_EQUAL(_data[1], other[1], threshold));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::almost_equal
+//       Access: Public
+//  Description: Returns true if two vectors are memberwise equal
+//               within a default tolerance based on the numeric type.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase2)::
+almost_equal(const FLOATNAME(LVecBase2) &other) const {
+  return almost_equal(other, NEARLY_ZERO(FLOATTYPE));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::output
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase2)::
+output(ostream &out) const {
+  out << MAYBE_ZERO(_data[0]) << " " 
+      << MAYBE_ZERO(_data[1]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::write_datagram
+//       Access: Public
+//  Description: Function to write itself into a datagram
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase2)::
+write_datagram(Datagram &destination) const {
+  destination.add_float32(_data[0]);
+  destination.add_float32(_data[1]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::read_datagram
+//       Access: Public
+//  Description: Function to read itself from a datagramIterator
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase2)::
+read_datagram(DatagramIterator &source) {
+  _data[0] = source.get_float32();
+  _data[1] = source.get_float32();
+}
+

+ 13 - 0
panda/src/linmath/lvecBase3.cxx

@@ -0,0 +1,13 @@
+// Filename: lvecBase3.cxx
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "lvecBase3.h"
+
+#include "fltnames.h"
+#include "lvecBase3_src.cxx"
+
+#include "dblnames.h"
+#include "lvecBase3_src.cxx"
+

+ 26 - 0
panda/src/linmath/lvecBase3.h

@@ -0,0 +1,26 @@
+// Filename: lvecBase3.h
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef LVECBASE3_H
+#define LVECBASE3_H
+
+#include <pandabase.h>
+#include <typeHandle.h>
+#include <notify.h>
+#include <datagram.h>
+#include <datagramIterator.h>
+#include "cmath.h"
+#include "nearly_zero.h"
+
+class Datagram;
+class DatagramIterator;
+
+#include "fltnames.h"
+#include "lvecBase3_src.h"
+
+#include "dblnames.h"
+#include "lvecBase3_src.h"
+
+#endif

+ 590 - 0
panda/src/linmath/lvecBase3_src.I

@@ -0,0 +1,590 @@
+// Filename: lvecBase3_src.I
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::Default Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3)::
+FLOATNAME(LVecBase3)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3)::
+FLOATNAME(LVecBase3)(const FLOATNAME(LVecBase3) &copy) {
+  (*this) = copy;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) &FLOATNAME(LVecBase3)::
+operator = (const FLOATNAME(LVecBase3) &copy) {
+  set(copy[0], copy[1], copy[2]);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::Fill Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) &FLOATNAME(LVecBase3)::
+operator = (FLOATTYPE fill_value) {
+  fill(fill_value);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3)::
+FLOATNAME(LVecBase3)(FLOATTYPE fill_value) {
+  fill(fill_value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3)::
+FLOATNAME(LVecBase3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z) {
+  set(x, y, z);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::zero Named Constructor
+//       Access: Public
+//  Description: Returns a zero-length vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVecBase3) &FLOATNAME(LVecBase3)::
+zero() {
+  return _zero;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::unit_x Named Constructor
+//       Access: Public
+//  Description: Returns a unit X vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVecBase3) &FLOATNAME(LVecBase3)::
+unit_x() {
+  return _unit_x;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::unit_y Named Constructor
+//       Access: Public
+//  Description: Returns a unit Y vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVecBase3) &FLOATNAME(LVecBase3)::
+unit_y() {
+  return _unit_y;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::unit_z Named Constructor
+//       Access: Public
+//  Description: Returns a unit Z vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVecBase3) &FLOATNAME(LVecBase3)::
+unit_z() {
+  return _unit_z;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3)::
+~FLOATNAME(LVecBase3)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::Indexing Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase3)::
+operator [](int i) const {
+  //nassertr(i >= 0 && i < 3, 0);
+  return _data[i];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::Indexing Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE &FLOATNAME(LVecBase3)::
+operator [](int i) {
+  //nassertr(i >= 0 && i < 3, _data[0]);
+  return _data[i];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::is_nan
+//       Access: Public
+//  Description: Returns true if any component of the vector is
+//               not-a-number, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase3)::
+is_nan() const {
+  return cnan(_data[0]) || cnan(_data[1]) || cnan(_data[2]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::get_cell
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase3)::
+get_cell(int i) const {
+  nassertr(i >= 0 && i < 3, 0);
+  return _data[i];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::get_x
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase3)::
+get_x() const {
+  return _data[0];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::get_y
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase3)::
+get_y() const {
+  return _data[1];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::get_z
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase3)::
+get_z() const {
+  return _data[2];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::set_cell
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase3)::
+set_cell(int i, FLOATTYPE value) {
+  nassertv(i >= 0 && i < 3);
+  _data[i] = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::set_x
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase3)::
+set_x(FLOATTYPE value) {
+  _data[0] = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::set_y
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase3)::
+set_y(FLOATTYPE value) {
+  _data[1] = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::set_z
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase3)::
+set_z(FLOATTYPE value) {
+  _data[2] = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::get_data
+//       Access: Public
+//  Description: Returns the address of the first of the three data
+//               elements in the vector.  The remaining elements
+//               occupy the next positions consecutively in memory.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATTYPE *FLOATNAME(LVecBase3)::
+get_data() const {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::get_num_components
+//       Access: Public
+//  Description: Returns the number of elements in the vector, three.
+////////////////////////////////////////////////////////////////////
+INLINE int FLOATNAME(LVecBase3)::
+get_num_components() const {
+  return 3;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::begin
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3)::iterator FLOATNAME(LVecBase3)::
+begin() {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::end
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3)::iterator FLOATNAME(LVecBase3)::
+end() {
+  return begin() + get_num_components();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::begin
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3)::const_iterator FLOATNAME(LVecBase3)::
+begin() const {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::end
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3)::const_iterator FLOATNAME(LVecBase3)::
+end() const {
+  return begin() + get_num_components();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::fill
+//       Access: Public
+//  Description: Sets each element of the vector to the indicated
+//               fill_value.  This is particularly useful for
+//               initializing to zero.
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase3)::
+fill(FLOATTYPE fill_value) {
+  _data[0] = fill_value;
+  _data[1] = fill_value;
+  _data[2] = fill_value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::set
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase3)::
+set(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z) {
+  _data[0] = x;
+  _data[1] = y;
+  _data[2] = z;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::dot
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase3)::
+dot(const FLOATNAME(LVecBase3) &other) const {
+  return _data[0] * other[0] + _data[1] * other[1] + _data[2] * other[2];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::cross
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::
+cross(const FLOATNAME(LVecBase3) &other) const {
+  return FLOATNAME(LVecBase3)(_data[1] * other[2] - other[1] * _data[2],
+			      other[0] * _data[2] - _data[0] * other[2],
+			      _data[0] * other[1] - other[0] * _data[1]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::operator <
+//       Access: Public
+//  Description: This performs a lexicographical comparison.  It's of
+//               questionable mathematical meaning, but sometimes has
+//               a practical purpose for sorting unique vectors,
+//               especially in an STL container.  Also see
+//               compare_to().
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase3)::
+operator < (const FLOATNAME(LVecBase3) &other) const {
+  return (compare_to(other) < 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::operator ==
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase3)::
+operator == (const FLOATNAME(LVecBase3) &other) const {
+  return (_data[0] == other[0] &&
+	  _data[1] == other[1] &&
+	  _data[2] == other[2]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::operator !=
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase3)::
+operator != (const FLOATNAME(LVecBase3) &other) const {
+  return !operator == (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::compare_to
+//       Access: Public
+//  Description: This flavor of compare_to uses a default threshold
+//               value based on the numeric type.
+////////////////////////////////////////////////////////////////////
+INLINE int FLOATNAME(LVecBase3)::
+compare_to(const FLOATNAME(LVecBase3) &other) const {
+  return compare_to(other, NEARLY_ZERO(FLOATTYPE));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::compare_to
+//       Access: Public
+//  Description: Sorts vectors lexicographically, componentwise.
+//               Returns a number less than 0 if this vector sorts
+//               before the other one, greater than zero if it sorts
+//               after, 0 if they are equivalent (within the indicated
+//               tolerance).
+////////////////////////////////////////////////////////////////////
+INLINE int FLOATNAME(LVecBase3)::
+compare_to(const FLOATNAME(LVecBase3) &other, FLOATTYPE threshold) const {
+  if (!IS_THRESHOLD_EQUAL(_data[0], other[0], threshold)) {
+    return (_data[0] < other[0]) ? -1 : 1;
+  }
+  if (!IS_THRESHOLD_EQUAL(_data[1], other[1], threshold)) {
+    return (_data[1] < other[1]) ? -1 : 1;
+  }
+  if (!IS_THRESHOLD_EQUAL(_data[2], other[2], threshold)) {
+    return (_data[2] < other[2]) ? -1 : 1;
+  }
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::unary -
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::
+operator - () const {
+  return FLOATNAME(LVecBase3)(-_data[0], -_data[1], -_data[2]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::vector + vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::
+operator + (const FLOATNAME(LVecBase3) &other) const {
+  return FLOATNAME(LVecBase3)(_data[0] + other[0],
+			      _data[1] + other[1],
+			      _data[2] + other[2]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::vector - vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::
+operator - (const FLOATNAME(LVecBase3) &other) const {
+  return FLOATNAME(LVecBase3)(_data[0] - other[0],
+			      _data[1] - other[1],
+			      _data[2] - other[2]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::vector * scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::
+operator * (FLOATTYPE scalar) const {
+  return FLOATNAME(LVecBase3)(_data[0] * scalar,
+			      _data[1] * scalar,
+			      _data[2] * scalar);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::vector / scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::
+operator / (FLOATTYPE scalar) const {
+  return FLOATNAME(LVecBase3)(_data[0] / scalar,
+			      _data[1] / scalar,
+			      _data[2] / scalar);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::operator +=
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase3)::
+operator += (const FLOATNAME(LVecBase3) &other) {
+  _data[0] += other[0];
+  _data[1] += other[1];
+  _data[2] += other[2];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::operator -=
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase3)::
+operator -= (const FLOATNAME(LVecBase3) &other) {
+  _data[0] -= other[0];
+  _data[1] -= other[1];
+  _data[2] -= other[2];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::operator *=
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase3)::
+operator *= (FLOATTYPE scalar) {
+  _data[0] *= scalar;
+  _data[1] *= scalar;
+  _data[2] *= scalar;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::operator /=
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase3)::
+operator /= (FLOATTYPE scalar) {
+  _data[0] /= scalar;
+  _data[1] /= scalar;
+  _data[2] /= scalar;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::cross product (with assigment)
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase3)::
+cross_into(const FLOATNAME(LVecBase3) &other) {
+  (*this) = cross(other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::almost_equal
+//       Access: Public
+//  Description: Returns true if two vectors are memberwise equal
+//               within a specified tolerance.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase3)::
+almost_equal(const FLOATNAME(LVecBase3) &other, FLOATTYPE threshold) const {
+  return (IS_THRESHOLD_EQUAL(_data[0], other[0], threshold) &&
+	  IS_THRESHOLD_EQUAL(_data[1], other[1], threshold) &&
+	  IS_THRESHOLD_EQUAL(_data[2], other[2], threshold));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::almost_equal
+//       Access: Public
+//  Description: Returns true if two vectors are memberwise equal
+//               within a default tolerance based on the numeric type.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase3)::
+almost_equal(const FLOATNAME(LVecBase3) &other) const {
+  return almost_equal(other, NEARLY_ZERO(FLOATTYPE));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::output
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase3)::
+output(ostream &out) const {
+  out << MAYBE_ZERO(_data[0]) << " " 
+      << MAYBE_ZERO(_data[1]) << " " 
+      << MAYBE_ZERO(_data[2]);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::write_datagram
+//       Access: Public
+//  Description: Function to write itself into a datagram
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase3)::
+write_datagram(Datagram &destination) const {
+  destination.add_float32(_data[0]);
+  destination.add_float32(_data[1]);
+  destination.add_float32(_data[2]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::read_datagram
+//       Access: Public
+//  Description: Function to read itself from a datagramIterator
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase3)::
+read_datagram(DatagramIterator &source) {
+  _data[0] = source.get_float32();
+  _data[1] = source.get_float32();
+  _data[2] = source.get_float32();
+}

+ 13 - 0
panda/src/linmath/lvecBase4.cxx

@@ -0,0 +1,13 @@
+// Filename: lvecBase4.cxx
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "lvecBase4.h"
+
+#include "fltnames.h"
+#include "lvecBase4_src.cxx"
+
+#include "dblnames.h"
+#include "lvecBase4_src.cxx"
+

+ 27 - 0
panda/src/linmath/lvecBase4.h

@@ -0,0 +1,27 @@
+// Filename: lvecBase4.h
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef LVECBASE4_H
+#define LVECBASE4_H
+
+#include <pandabase.h>
+#include <typeHandle.h>
+#include <notify.h>
+#include <datagram.h>
+#include <datagramIterator.h>
+#include "cmath.h"
+#include "nearly_zero.h"
+
+class Datagram;
+class DatagramIterator;
+
+#include "fltnames.h"
+#include "lvecBase4_src.h"
+
+#include "dblnames.h"
+#include "lvecBase4_src.h"
+
+
+#endif

+ 618 - 0
panda/src/linmath/lvecBase4_src.I

@@ -0,0 +1,618 @@
+// Filename: lvecBase4_src.I
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::Default Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4)::
+FLOATNAME(LVecBase4)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4)::
+FLOATNAME(LVecBase4)(const FLOATNAME(LVecBase4) &copy) {
+  (*this) = copy;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4) &FLOATNAME(LVecBase4)::
+operator = (const FLOATNAME(LVecBase4) &copy) {
+  set(copy[0], copy[1], copy[2], copy[3]);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::Fill Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4) &FLOATNAME(LVecBase4)::
+operator = (FLOATTYPE fill_value) {
+  fill(fill_value);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4)::
+FLOATNAME(LVecBase4)(FLOATTYPE fill_value) {
+  fill(fill_value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4)::
+FLOATNAME(LVecBase4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w) {
+  set(x, y, z, w);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4)::
+~FLOATNAME(LVecBase4)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::zero Named Constructor
+//       Access: Public
+//  Description: Returns a zero-length vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVecBase4) &FLOATNAME(LVecBase4)::
+zero() {
+  return _zero;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::unit_x Named Constructor
+//       Access: Public
+//  Description: Returns a unit X vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVecBase4) &FLOATNAME(LVecBase4)::
+unit_x() {
+  return _unit_x;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::unit_y Named Constructor
+//       Access: Public
+//  Description: Returns a unit Y vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVecBase4) &FLOATNAME(LVecBase4)::
+unit_y() {
+  return _unit_y;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::unit_z Named Constructor
+//       Access: Public
+//  Description: Returns a unit Z vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVecBase4) &FLOATNAME(LVecBase4)::
+unit_z() {
+  return _unit_z;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::unit_w Named Constructor
+//       Access: Public
+//  Description: Returns a unit W vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVecBase4) &FLOATNAME(LVecBase4)::
+unit_w() {
+  return _unit_w;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::Indexing Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase4)::
+operator [](int i) const {
+  //  nassertr(i >= 0 && i < 4, 0);
+  return _data[i];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::Indexing Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE &FLOATNAME(LVecBase4)::
+operator [](int i) {
+  //  nassertr(i >= 0 && i < 4, _data[0]);
+  return _data[i];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::is_nan
+//       Access: Public
+//  Description: Returns true if any component of the vector is
+//               not-a-number, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase4)::
+is_nan() const {
+  return cnan(_data[0]) || cnan(_data[1]) || cnan(_data[2]) || cnan(_data[3]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::get_cell
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase4)::
+get_cell(int i) const {
+  nassertr(i >= 0 && i < 4, 0);
+  return _data[i];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::get_x
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase4)::
+get_x() const {
+  return _data[0];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::get_y
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase4)::
+get_y() const {
+  return _data[1];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::get_z
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase4)::
+get_z() const {
+  return _data[2];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::get_w
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase4)::
+get_w() const {
+  return _data[3];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::set_cell
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase4)::
+set_cell(int i, FLOATTYPE value) {
+  nassertv(i >= 0 && i < 4);
+  _data[i] = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::set_x
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase4)::
+set_x(FLOATTYPE value) {
+  _data[0] = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::set_y
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase4)::
+set_y(FLOATTYPE value) {
+  _data[1] = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::set_z
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase4)::
+set_z(FLOATTYPE value) {
+  _data[2] = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::set_w
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase4)::
+set_w(FLOATTYPE value) {
+  _data[3] = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::get_data
+//       Access: Public
+//  Description: Returns the address of the first of the four data
+//               elements in the vector.  The remaining elements
+//               occupy the next positions consecutively in memory.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATTYPE *FLOATNAME(LVecBase4)::
+get_data() const {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::get_num_components
+//       Access: Public
+//  Description: Returns the number of elements in the vector, four.
+////////////////////////////////////////////////////////////////////
+INLINE int FLOATNAME(LVecBase4)::
+get_num_components() const {
+  return 4;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::begin
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4)::iterator FLOATNAME(LVecBase4)::
+begin() {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::end
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4)::iterator FLOATNAME(LVecBase4)::
+end() {
+  return begin() + get_num_components();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::begin
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4)::const_iterator FLOATNAME(LVecBase4)::
+begin() const {
+  return _data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::end
+//       Access: Public
+//  Description: Returns an iterator that may be used to traverse the
+//               elements of the matrix, STL-style.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4)::const_iterator FLOATNAME(LVecBase4)::
+end() const {
+  return begin() + get_num_components();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::fill
+//       Access: Public
+//  Description: Sets each element of the vector to the indicated
+//               fill_value.  This is particularly useful for
+//               initializing to zero.
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase4)::
+fill(FLOATTYPE fill_value) {
+  _data[0] = fill_value;
+  _data[1] = fill_value;
+  _data[2] = fill_value;
+  _data[3] = fill_value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::set
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase4)::
+set(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w) {
+  _data[0] = x;
+  _data[1] = y;
+  _data[2] = z;
+  _data[3] = w;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::dot
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVecBase4)::
+dot(const FLOATNAME(LVecBase4) &other) const {
+  return 
+    _data[0] * other[0] + _data[1] * other[1] + 
+    _data[2] * other[2] + _data[3] * other[3];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::operator <
+//       Access: Public
+//  Description: This performs a lexicographical comparison.  It's of
+//               questionable mathematical meaning, but sometimes has
+//               a practical purpose for sorting unique vectors,
+//               especially in an STL container.  Also see
+//               compare_to().
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase4)::
+operator < (const FLOATNAME(LVecBase4) &other) const {
+  return (compare_to(other) < 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::operator ==
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase4)::
+operator == (const FLOATNAME(LVecBase4) &other) const {
+  return (_data[0] == other[0] &&
+	  _data[1] == other[1] &&
+	  _data[2] == other[2] &&
+	  _data[3] == other[3]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::operator !=
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase4)::
+operator != (const FLOATNAME(LVecBase4) &other) const {
+  return !operator == (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::compare_to
+//       Access: Public
+//  Description: This flavor of compare_to uses a default threshold
+//               value based on the numeric type.
+////////////////////////////////////////////////////////////////////
+INLINE int FLOATNAME(LVecBase4)::
+compare_to(const FLOATNAME(LVecBase4) &other) const {
+  return compare_to(other, NEARLY_ZERO(FLOATTYPE));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::compare_to
+//       Access: Public
+//  Description: Sorts vectors lexicographically, componentwise.
+//               Returns a number less than 0 if this vector sorts
+//               before the other one, greater than zero if it sorts
+//               after, 0 if they are equivalent (within the indicated
+//               tolerance).
+////////////////////////////////////////////////////////////////////
+INLINE int FLOATNAME(LVecBase4)::
+compare_to(const FLOATNAME(LVecBase4) &other, FLOATTYPE threshold) const {
+  if (!IS_THRESHOLD_EQUAL(_data[0], other[0], threshold)) {
+    return (_data[0] < other[0]) ? -1 : 1;
+  }
+  if (!IS_THRESHOLD_EQUAL(_data[1], other[1], threshold)) {
+    return (_data[1] < other[1]) ? -1 : 1;
+  }
+  if (!IS_THRESHOLD_EQUAL(_data[2], other[2], threshold)) {
+    return (_data[2] < other[2]) ? -1 : 1;
+  }
+  if (!IS_THRESHOLD_EQUAL(_data[3], other[3], threshold)) {
+    return (_data[3] < other[3]) ? -1 : 1;
+  }
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::unary -
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::
+operator - () const {
+  return FLOATNAME(LVecBase4)(-_data[0], -_data[1], -_data[2], -_data[3]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::vector + vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::
+operator + (const FLOATNAME(LVecBase4) &other) const {
+  return FLOATNAME(LVecBase4)(_data[0] + other[0],
+			      _data[1] + other[1],
+			      _data[2] + other[2],
+			      _data[3] + other[3]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::vector - vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::
+operator - (const FLOATNAME(LVecBase4) &other) const {
+  return FLOATNAME(LVecBase4)(_data[0] - other[0],
+			      _data[1] - other[1],
+			      _data[2] - other[2],
+			      _data[3] - other[3]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::vector * scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::
+operator * (FLOATTYPE scalar) const {
+  return FLOATNAME(LVecBase4)(_data[0] * scalar,
+			      _data[1] * scalar,
+			      _data[2] * scalar,
+			      _data[3] * scalar);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::vector / scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::
+operator / (FLOATTYPE scalar) const {
+  return FLOATNAME(LVecBase4)(_data[0] / scalar,
+			      _data[1] / scalar,
+			      _data[2] / scalar,
+			      _data[3] / scalar);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::operator +=
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase4)::
+operator += (const FLOATNAME(LVecBase4) &other) {
+  _data[0] += other[0];
+  _data[1] += other[1];
+  _data[2] += other[2];
+  _data[3] += other[3];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::operator -=
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase4)::
+operator -= (const FLOATNAME(LVecBase4) &other) {
+  _data[0] -= other[0];
+  _data[1] -= other[1];
+  _data[2] -= other[2];
+  _data[3] -= other[3];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::operator *=
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase4)::
+operator *= (FLOATTYPE scalar) {
+  _data[0] *= scalar;
+  _data[1] *= scalar;
+  _data[2] *= scalar;
+  _data[3] *= scalar;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::operator /=
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase4)::
+operator /= (FLOATTYPE scalar) {
+  _data[0] /= scalar;
+  _data[1] /= scalar;
+  _data[2] /= scalar;
+  _data[3] /= scalar;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::almost_equal
+//       Access: Public
+//  Description: Returns true if two vectors are memberwise equal
+//               within a specified tolerance.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase4)::
+almost_equal(const FLOATNAME(LVecBase4) &other, FLOATTYPE threshold) const {
+  return (IS_THRESHOLD_EQUAL(_data[0], other[0], threshold) &&
+	  IS_THRESHOLD_EQUAL(_data[1], other[1], threshold) &&
+	  IS_THRESHOLD_EQUAL(_data[2], other[2], threshold) &&
+	  IS_THRESHOLD_EQUAL(_data[3], other[3], threshold));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::almost_equal
+//       Access: Public
+//  Description: Returns true if two vectors are memberwise equal
+//               within a default tolerance based on the numeric type.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVecBase4)::
+almost_equal(const FLOATNAME(LVecBase4) &other) const {
+  return almost_equal(other, NEARLY_ZERO(FLOATTYPE));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::output
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase4)::
+output(ostream &out) const {
+  out << MAYBE_ZERO(_data[0]) << " " 
+      << MAYBE_ZERO(_data[1]) << " " 
+      << MAYBE_ZERO(_data[2]) << " " 
+      << MAYBE_ZERO(_data[3]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::write_datagram
+//       Access: Public
+//  Description: Function to write itself into a datagram
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase4)::
+write_datagram(Datagram &destination) const {
+  destination.add_float32(_data[0]);
+  destination.add_float32(_data[1]);
+  destination.add_float32(_data[2]);
+  destination.add_float32(_data[3]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::read_datagram
+//       Access: Public
+//  Description: Function to read itself from a datagramIterator
+////////////////////////////////////////////////////////////////////
+INLINE void FLOATNAME(LVecBase4)::
+read_datagram(DatagramIterator &source) {
+  _data[0] = source.get_float32();
+  _data[1] = source.get_float32();
+  _data[2] = source.get_float32();
+  _data[3] = source.get_float32();
+}

+ 13 - 0
panda/src/linmath/lvector2.cxx

@@ -0,0 +1,13 @@
+// Filename: lvector2.cxx
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "lvector2.h"
+
+#include "fltnames.h"
+#include "lvector2_src.cxx"
+
+#include "dblnames.h"
+#include "lvector2_src.cxx"
+

+ 20 - 0
panda/src/linmath/lvector2.h

@@ -0,0 +1,20 @@
+// Filename: lvector2.h
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef LVECTOR2_H
+#define LVECTOR2_H
+
+#include <pandabase.h>
+#include "cmath.h"
+#include "config_linmath.h"
+#include "lvecBase2.h"
+
+#include "fltnames.h"
+#include "lvector2_src.h"
+
+#include "dblnames.h"
+#include "lvector2_src.h"
+
+#endif

+ 209 - 0
panda/src/linmath/lvector2_src.I

@@ -0,0 +1,209 @@
+// Filename: lvector2_src.I
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::Default Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector2)::
+FLOATNAME(LVector2)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector2)::
+FLOATNAME(LVector2)(const FLOATNAME(LVecBase2) &copy) : FLOATNAME(LVecBase2)(copy) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector2) &FLOATNAME(LVector2)::
+operator = (const FLOATNAME(LVecBase2) &copy) {
+  FLOATNAME(LVecBase2)::operator = (copy);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::Copy Fill Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector2) &FLOATNAME(LVector2)::
+operator = (FLOATTYPE fill_value) {
+  FLOATNAME(LVecBase2)::operator = (fill_value);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector2)::
+FLOATNAME(LVector2)(FLOATTYPE fill_value) :
+  FLOATNAME(LVecBase2)(fill_value) 
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector2)::
+FLOATNAME(LVector2)(FLOATTYPE x, FLOATTYPE y) : 
+  FLOATNAME(LVecBase2)(x, y) 
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::zero Named Constructor
+//       Access: Public
+//  Description: Returns a zero-length vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVector2) &FLOATNAME(LVector2)::
+zero() {
+  return (const FLOATNAME(LVector2) &)FLOATNAME(LVecBase2)::zero();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::unit_x Named Constructor
+//       Access: Public
+//  Description: Returns a unit X vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVector2) &FLOATNAME(LVector2)::
+unit_x() {
+  return (const FLOATNAME(LVector2) &)FLOATNAME(LVecBase2)::unit_x();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::unit_y Named Constructor
+//       Access: Public
+//  Description: Returns a unit Y vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVector2) &FLOATNAME(LVector2)::
+unit_y() {
+  return (const FLOATNAME(LVector2) &)FLOATNAME(LVecBase2)::unit_y();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::unary -
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector2) FLOATNAME(LVector2)::
+operator - () const {
+  return FLOATNAME(LVecBase2)::operator - ();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::vector + vecbase
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2) FLOATNAME(LVector2)::
+operator + (const FLOATNAME(LVecBase2) &other) const {
+  return FLOATNAME(LVecBase2)::operator + (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::vector + vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector2) FLOATNAME(LVector2)::
+operator + (const FLOATNAME(LVector2) &other) const {
+  return FLOATNAME(LVecBase2)::operator + (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::vector - vecbase
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase2) FLOATNAME(LVector2)::
+operator - (const FLOATNAME(LVecBase2) &other) const {
+  return FLOATNAME(LVecBase2)::operator - (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::vector - vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector2) FLOATNAME(LVector2)::
+operator - (const FLOATNAME(LVector2) &other) const {
+  return FLOATNAME(LVecBase2)::operator - (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::length
+//       Access: Public
+//  Description: Returns the length of the vector, by the Pythagorean
+//               theorem.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVector2)::
+length() const {
+  return csqrt((*this).dot(*this));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::length_squared
+//       Access: Public
+//  Description: Returns the square of the vector's length, cheap and
+//               easy.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVector2)::
+length_squared() const {
+  return (*this).dot(*this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::normalize
+//       Access: Public
+//  Description: Normalizes the vector in place.  Returns true if the
+//               vector was normalized, false if it was a zero-length
+//               vector.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVector2)::
+normalize() {
+  FLOATTYPE l2 = length_squared();
+  if (l2 == (FLOATTYPE)0.0) {
+    set(0.0, 0.0);
+    return false;
+
+  } else if (!IS_THRESHOLD_EQUAL(l2, 1.0, NEARLY_ZERO(FLOATTYPE) * NEARLY_ZERO(FLOATTYPE))) {
+    (*this) /= csqrt(l2);
+  }
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::operator * scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector2) FLOATNAME(LVector2)::
+operator * (FLOATTYPE scalar) const {
+  return FLOATNAME(LVector2)(FLOATNAME(LVecBase2)::operator * (scalar));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector2::operator / scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector2) FLOATNAME(LVector2)::
+operator / (FLOATTYPE scalar) const {
+  return FLOATNAME(LVector2)(FLOATNAME(LVecBase2)::operator / (scalar));
+}

+ 13 - 0
panda/src/linmath/lvector3.cxx

@@ -0,0 +1,13 @@
+// Filename: lvector3.cxx
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "lvector3.h"
+
+#include "fltnames.h"
+#include "lvector3_src.cxx"
+
+#include "dblnames.h"
+#include "lvector3_src.cxx"
+

+ 22 - 0
panda/src/linmath/lvector3.h

@@ -0,0 +1,22 @@
+// Filename: lvector3.h
+// Created by:  drose (24Sep99)
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef LVECTOR3_H
+#define LVECTOR3_H
+
+#include <pandabase.h>
+
+#include "coordinateSystem.h"
+#include "cmath.h"
+#include "config_linmath.h"
+#include "lvecBase3.h"
+
+#include "fltnames.h"
+#include "lvector3_src.h"
+
+#include "dblnames.h"
+#include "lvector3_src.h"
+
+#endif

+ 345 - 0
panda/src/linmath/lvector3_src.I

@@ -0,0 +1,345 @@
+// Filename: lvector3_src.I
+// Created by:  drose (24Sep99)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::Default Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3)::
+FLOATNAME(LVector3)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3)::
+FLOATNAME(LVector3)(const FLOATNAME(LVecBase3) &copy) : FLOATNAME(LVecBase3)(copy) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) &FLOATNAME(LVector3)::
+operator = (const FLOATNAME(LVecBase3) &copy) {
+  FLOATNAME(LVecBase3)::operator = (copy);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::Copy Fill Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) &FLOATNAME(LVector3)::
+operator = (FLOATTYPE fill_value) {
+  FLOATNAME(LVecBase3)::operator = (fill_value);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3)::
+FLOATNAME(LVector3)(FLOATTYPE fill_value) :
+  FLOATNAME(LVecBase3)(fill_value) 
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3)::
+FLOATNAME(LVector3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z) : 
+  FLOATNAME(LVecBase3)(x, y, z) 
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::zero Named Constructor
+//       Access: Public
+//  Description: Returns a zero-length vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVector3) &FLOATNAME(LVector3)::
+zero() {
+  return (const FLOATNAME(LVector3) &)FLOATNAME(LVecBase3)::zero();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::unit_x Named Constructor
+//       Access: Public
+//  Description: Returns a unit X vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVector3) &FLOATNAME(LVector3)::
+unit_x() {
+  return (const FLOATNAME(LVector3) &)FLOATNAME(LVecBase3)::unit_x();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::unit_y Named Constructor
+//       Access: Public
+//  Description: Returns a unit Y vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVector3) &FLOATNAME(LVector3)::
+unit_y() {
+  return (const FLOATNAME(LVector3) &)FLOATNAME(LVecBase3)::unit_y();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::unit_z Named Constructor
+//       Access: Public
+//  Description: Returns a unit Z vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVector3) &FLOATNAME(LVector3)::
+unit_z() {
+  return (const FLOATNAME(LVector3) &)FLOATNAME(LVecBase3)::unit_z();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::unary -
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) FLOATNAME(LVector3)::
+operator - () const {
+  return FLOATNAME(LVecBase3)::operator - ();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::vector + vecbase
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LVector3)::
+operator + (const FLOATNAME(LVecBase3) &other) const {
+  return FLOATNAME(LVecBase3)::operator + (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::vector + vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) FLOATNAME(LVector3)::
+operator + (const FLOATNAME(LVector3) &other) const {
+  return FLOATNAME(LVecBase3)::operator + (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::vector - vecbase
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase3) FLOATNAME(LVector3)::
+operator - (const FLOATNAME(LVecBase3) &other) const {
+  return FLOATNAME(LVecBase3)::operator - (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::vector - vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) FLOATNAME(LVector3)::
+operator - (const FLOATNAME(LVector3) &other) const {
+  return FLOATNAME(LVecBase3)::operator - (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::length
+//       Access: Public
+//  Description: Returns the length of the vector, by the Pythagorean
+//               theorem.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVector3)::
+length() const {
+  return csqrt((*this).dot(*this));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::length_squared
+//       Access: Public
+//  Description: Returns the square of the vector's length, cheap and
+//               easy.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVector3)::
+length_squared() const {
+  return (*this).dot(*this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::normalize
+//       Access: Public
+//  Description: Normalizes the vector in place.  Returns true if the
+//               vector was normalized, false if it was a zero-length
+//               vector.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVector3)::
+normalize() {
+  FLOATTYPE l2 = length_squared();
+  if (l2 == (FLOATTYPE)0.0) {
+    set(0.0, 0.0, 0.0);
+    return false;
+
+  } else if (!IS_THRESHOLD_EQUAL(l2, 1.0, NEARLY_ZERO(FLOATTYPE) * NEARLY_ZERO(FLOATTYPE))) {
+    (*this) /= csqrt(l2);
+  }
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::cross
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) FLOATNAME(LVector3)::
+cross(const FLOATNAME(LVecBase3) &other) const {
+  return FLOATNAME(LVecBase3)::cross(other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::operator * scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) FLOATNAME(LVector3)::
+operator * (FLOATTYPE scalar) const {
+  return FLOATNAME(LVector3)(FLOATNAME(LVecBase3)::operator * (scalar));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::operator / scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) FLOATNAME(LVector3)::
+operator / (FLOATTYPE scalar) const {
+  return FLOATNAME(LVector3)(FLOATNAME(LVecBase3)::operator / (scalar));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::up
+//       Access: Public, Static
+//  Description: Returns the up vector for the given coordinate
+//               system.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) FLOATNAME(LVector3)::
+up(CoordinateSystem cs) {
+  if (cs == CS_default) {
+    cs = default_coordinate_system;
+  }
+  switch (cs) {
+  case CS_zup_right:
+  case CS_zup_left:
+    return FLOATNAME(LVector3)(0.0, 0.0, 1.0);
+
+  case CS_yup_right:
+  case CS_yup_left:
+    return FLOATNAME(LVector3)(0.0, 1.0, 0.0);
+
+  default:
+    linmath_cat.error()
+      << "Invalid coordinate system!\n";
+    return FLOATNAME(LVector3)(0.0, 0.0, 0.0);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::right
+//       Access: Public, Static
+//  Description: Returns the right vector for the given coordinate
+//               system.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) FLOATNAME(LVector3)::
+right(CoordinateSystem) {
+  return FLOATNAME(LVector3)(1.0, 0.0, 0.0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::forward
+//       Access: Public, Static
+//  Description: Returns the forward vector for the given coordinate
+//               system.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) FLOATNAME(LVector3)::
+forward(CoordinateSystem cs) {
+  if (cs == CS_default) {
+    cs = default_coordinate_system;
+  }
+  switch (cs) {
+  case CS_zup_right:
+    return FLOATNAME(LVector3)(0.0, 1.0, 0.0);
+
+  case CS_zup_left:
+    return FLOATNAME(LVector3)(0.0, -1.0, 0.0);
+
+  case CS_yup_right:
+    return FLOATNAME(LVector3)(0.0, 0.0, -1.0);
+
+  case CS_yup_left:
+    return FLOATNAME(LVector3)(0.0, 0.0, 1.0);
+
+  default:
+    linmath_cat.error()
+      << "Invalid coordinate system!\n";
+    return FLOATNAME(LVector3)(0.0, 0.0, 0.0);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::down
+//       Access: Public, Static
+//  Description: Returns the down vector for the given coordinate
+//               system.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) FLOATNAME(LVector3)::
+down(CoordinateSystem cs) {
+  return -up(cs);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::left
+//       Access: Public, Static
+//  Description: Returns the left vector for the given coordinate
+//               system.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) FLOATNAME(LVector3)::
+left(CoordinateSystem cs) {
+  return -right(cs);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::back
+//       Access: Public, Static
+//  Description: Returns the back vector for the given coordinate
+//               system.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) FLOATNAME(LVector3)::
+back(CoordinateSystem cs) {
+  return -forward(cs);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::rfu
+//       Access: Public, Static
+//  Description: Returns a vector that is described by its right,
+//               forward, and up components, in whatever way the
+//               coordinate system represents that vector.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector3) FLOATNAME(LVector3)::
+rfu(FLOATTYPE right_v, FLOATTYPE fwd_v, FLOATTYPE up_v,
+    CoordinateSystem cs) {
+  return forward(cs) * fwd_v + up(cs) * up_v + right(cs) * right_v;
+}

+ 13 - 0
panda/src/linmath/lvector4.cxx

@@ -0,0 +1,13 @@
+// Filename: lvector4.cxx
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "lvector4.h"
+
+#include "fltnames.h"
+#include "lvector4_src.cxx"
+
+#include "dblnames.h"
+#include "lvector4_src.cxx"
+

+ 20 - 0
panda/src/linmath/lvector4.h

@@ -0,0 +1,20 @@
+// Filename: lvector4.h
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef LVECTOR4_H
+#define LVECTOR4_H
+
+#include <pandabase.h>
+#include "cmath.h"
+#include "config_linmath.h"
+#include "lvecBase4.h"
+
+#include "fltnames.h"
+#include "lvector4_src.h"
+
+#include "dblnames.h"
+#include "lvector4_src.h"
+
+#endif

+ 230 - 0
panda/src/linmath/lvector4_src.I

@@ -0,0 +1,230 @@
+// Filename: lvector4_src.I
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::Default Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector4)::
+FLOATNAME(LVector4)() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector4)::
+FLOATNAME(LVector4)(const FLOATNAME(LVecBase4) &copy) : FLOATNAME(LVecBase4)(copy) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector4) &FLOATNAME(LVector4)::
+operator = (const FLOATNAME(LVecBase4) &copy) {
+  FLOATNAME(LVecBase4)::operator = (copy);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::Copy Fill Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector4) &FLOATNAME(LVector4)::
+operator = (FLOATTYPE fill_value) {
+  FLOATNAME(LVecBase4)::operator = (fill_value);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector4)::
+FLOATNAME(LVector4)(FLOATTYPE fill_value) :
+  FLOATNAME(LVecBase4)(fill_value) 
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector4)::
+FLOATNAME(LVector4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w) : 
+  FLOATNAME(LVecBase4)(x, y, z, w) 
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::zero Named Constructor
+//       Access: Public
+//  Description: Returns a zero-length vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVector4) &FLOATNAME(LVector4)::
+zero() {
+  return (const FLOATNAME(LVector4) &)FLOATNAME(LVecBase4)::zero();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::unit_x Named Constructor
+//       Access: Public
+//  Description: Returns a unit X vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVector4) &FLOATNAME(LVector4)::
+unit_x() {
+  return (const FLOATNAME(LVector4) &)FLOATNAME(LVecBase4)::unit_x();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::unit_y Named Constructor
+//       Access: Public
+//  Description: Returns a unit Y vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVector4) &FLOATNAME(LVector4)::
+unit_y() {
+  return (const FLOATNAME(LVector4) &)FLOATNAME(LVecBase4)::unit_y();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::unit_z Named Constructor
+//       Access: Public
+//  Description: Returns a unit Z vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVector4) &FLOATNAME(LVector4)::
+unit_z() {
+  return (const FLOATNAME(LVector4) &)FLOATNAME(LVecBase4)::unit_z();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::unit_w Named Constructor
+//       Access: Public
+//  Description: Returns a unit W vector.
+////////////////////////////////////////////////////////////////////
+INLINE const FLOATNAME(LVector4) &FLOATNAME(LVector4)::
+unit_w() {
+  return (const FLOATNAME(LVector4) &)FLOATNAME(LVecBase4)::unit_w();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::unary -
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector4) FLOATNAME(LVector4)::
+operator - () const {
+  return FLOATNAME(LVecBase4)::operator - ();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::vector + vecbase
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4) FLOATNAME(LVector4)::
+operator + (const FLOATNAME(LVecBase4) &other) const {
+  return FLOATNAME(LVecBase4)::operator + (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::vector + vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector4) FLOATNAME(LVector4)::
+operator + (const FLOATNAME(LVector4) &other) const {
+  return FLOATNAME(LVecBase4)::operator + (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::vector - vecbase
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVecBase4) FLOATNAME(LVector4)::
+operator - (const FLOATNAME(LVecBase4) &other) const {
+  return FLOATNAME(LVecBase4)::operator - (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::vector - vector
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector4) FLOATNAME(LVector4)::
+operator - (const FLOATNAME(LVector4) &other) const {
+  return FLOATNAME(LVecBase4)::operator - (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::length
+//       Access: Public
+//  Description: Returns the length of the vector, by the Pythagorean
+//               theorem.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVector4)::
+length() const {
+  return csqrt((*this).dot(*this));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::length_squared
+//       Access: Public
+//  Description: Returns the square of the vector's length, cheap and
+//               easy.
+////////////////////////////////////////////////////////////////////
+INLINE FLOATTYPE FLOATNAME(LVector4)::
+length_squared() const {
+  return (*this).dot(*this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::normalize
+//       Access: Public
+//  Description: Normalizes the vector in place.  Returns true if the
+//               vector was normalized, false if it was a zero-length
+//               vector.
+////////////////////////////////////////////////////////////////////
+INLINE bool FLOATNAME(LVector4)::
+normalize() {
+  FLOATTYPE l2 = length_squared();
+  if (l2 == (FLOATTYPE)0.0) {
+    set(0.0, 0.0, 0.0, 0.0);
+    return false;
+
+  } else if (!IS_THRESHOLD_EQUAL(l2, 1.0, NEARLY_ZERO(FLOATTYPE) * NEARLY_ZERO(FLOATTYPE))) {
+    (*this) /= csqrt(l2);
+  }
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::operator * scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector4) FLOATNAME(LVector4)::
+operator * (FLOATTYPE scalar) const {
+  return FLOATNAME(LVector4)(FLOATNAME(LVecBase4)::operator * (scalar));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::operator / scalar
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE FLOATNAME(LVector4) FLOATNAME(LVector4)::
+operator / (FLOATTYPE scalar) const {
+  return FLOATNAME(LVector4)(FLOATNAME(LVecBase4)::operator / (scalar));
+}

+ 10 - 0
panda/src/linmath/mathNumbers.cxx

@@ -0,0 +1,10 @@
+// Filename: mathNumbers.cxx
+// Created by:  mike (24Sep99)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "mathNumbers.h" 
+#include <math.h>
+
+const double MathNumbers::pi = 4.0 * atan(1);
+const double MathNumbers::ln2 = log(2);

+ 17 - 0
panda/src/linmath/mathNumbers.h

@@ -0,0 +1,17 @@
+// Filename: mathNumbers.h
+// Created by:  mike (23Jan99)
+//
+////////////////////////////////////////////////////////////////////
+//
+#ifndef MATHNUMBERS_H
+#define MATHNUMBERS_H
+
+#include <pandabase.h>
+
+class EXPCL_PANDA MathNumbers {
+PUBLISHED:
+  static const double pi;
+  static const double ln2;
+};
+
+#endif

+ 58 - 0
panda/src/linmath/nearly_zero.h

@@ -0,0 +1,58 @@
+// Filename: nearly_zero.h
+// Created by:  drose (08Mar00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef NEARLY_ZERO_H
+#define NEARLY_ZERO_H
+
+
+// The following two functions are defined just to make the
+// NEARLY_ZERO() macro work.  They each return a suitable nearly-zero
+// value for their corresponding numeric type.
+INLINE double
+get_nearly_zero_value(double) {
+  return 1.0e-12;
+}
+
+INLINE float
+get_nearly_zero_value(float) {
+  return 1.0e-6f;
+}
+
+
+// IS_THRESHOLD_ZERO(value, threshold) returns true if the value is
+// within threshold of zero.
+#define IS_THRESHOLD_ZERO(value, threshold) \
+  ((value) < (threshold) && (value) > -(threshold))
+
+// IS_THRESHOLD_EQUAL(value1, value2, threshold) returns true if the
+// two values are within threshold of each other.
+#define IS_THRESHOLD_EQUAL(value1, value2, threshold) \
+  (IS_THRESHOLD_ZERO((value1) - (value2), threshold))
+
+
+// NEARLY_ZERO(float) returns a number that is considered to be so
+// close to zero as not to matter for a float.  NEARLY_ZERO(double)
+// returns a similar, smaller number for a double.
+#define NEARLY_ZERO(FLOATTYPE) (get_nearly_zero_value((FLOATTYPE)0))
+
+// IS_NEARLY_ZERO(value) returns true if the value is very close to
+// zero.
+#define IS_NEARLY_ZERO(value) \
+  (IS_THRESHOLD_ZERO(value, get_nearly_zero_value(value)))
+
+// IS_NEARLY_EQUAL(value1, value2) returns true if the two values are
+// very close to each other.
+#define IS_NEARLY_EQUAL(value1, value2) \
+   IS_NEARLY_ZERO((value1) - (value2))
+
+
+// MAYBE_ZERO(value) returns 0 if the value is nearly zero, and the
+// value itself otherwise.
+#define MAYBE_ZERO(value) \
+  (IS_NEARLY_ZERO(value) ? 0.0 : value)
+
+
+#endif
+

+ 11 - 0
panda/src/linmath/pta_Colorf.cxx

@@ -0,0 +1,11 @@
+// Filename: pta_Colorf.cxx
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "pta_Colorf.h"
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma implementation
+#endif

+ 37 - 0
panda/src/linmath/pta_Colorf.h

@@ -0,0 +1,37 @@
+// Filename: pta_Colorf.h
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef PTA_COLORF_H
+#define PTA_COLORF_H
+
+#include <pandabase.h>
+
+#include "vector_Colorf.h"
+
+#include <pointerToArray.h>
+
+////////////////////////////////////////////////////////////////////
+//       Class : PTA_Colorf
+// Description : A pta of Colorfs.  This class is defined once here,
+//               and exported to PANDA.DLL; other packages that want
+//               to use a pta of this type (whether they need to
+//               export it or not) should include this header file,
+//               rather than defining the pta again.
+////////////////////////////////////////////////////////////////////
+
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, RefCountObj<vector_Colorf>);
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToBase<RefCountObj<vector_Colorf> >);
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToArray<Colorf>)
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, ConstPointerToArray<Colorf>)
+
+typedef PointerToArray<Colorf> PTA_Colorf;
+typedef ConstPointerToArray<Colorf> CPTA_Colorf;
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#endif

+ 11 - 0
panda/src/linmath/pta_Normalf.cxx

@@ -0,0 +1,11 @@
+// Filename: pta_Normalf.cxx
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "pta_Normalf.h"
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma implementation
+#endif

+ 37 - 0
panda/src/linmath/pta_Normalf.h

@@ -0,0 +1,37 @@
+// Filename: pta_Normalf.h
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef PTA_NORMALF_H
+#define PTA_NORMALF_H
+
+#include <pandabase.h>
+
+#include "vector_Normalf.h"
+
+#include <pointerToArray.h>
+
+////////////////////////////////////////////////////////////////////
+//       Class : PTA_Normalf
+// Description : A pta of Normalfs.  This class is defined once here,
+//               and exported to PANDA.DLL; other packages that want
+//               to use a pta of this type (whether they need to
+//               export it or not) should include this header file,
+//               rather than defining the pta again.
+////////////////////////////////////////////////////////////////////
+
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, RefCountObj<vector_Normalf>);
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToBase<RefCountObj<vector_Normalf> >);
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToArray<Normalf>)
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, ConstPointerToArray<Normalf>)
+
+typedef PointerToArray<Normalf> PTA_Normalf;
+typedef ConstPointerToArray<Normalf> CPTA_Normalf;
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#endif

+ 11 - 0
panda/src/linmath/pta_TexCoordf.cxx

@@ -0,0 +1,11 @@
+// Filename: pta_TexCoordf.cxx
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "pta_TexCoordf.h"
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma implementation
+#endif

+ 37 - 0
panda/src/linmath/pta_TexCoordf.h

@@ -0,0 +1,37 @@
+// Filename: pta_TexCoordf.h
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef PTA_TEXCOORDF_H
+#define PTA_TEXCOORDF_H
+
+#include <pandabase.h>
+
+#include "vector_TexCoordf.h"
+
+#include <pointerToArray.h>
+
+////////////////////////////////////////////////////////////////////
+//       Class : PTA_TexCoordf
+// Description : A pta of TexCoordfs.  This class is defined once here,
+//               and exported to PANDA.DLL; other packages that want
+//               to use a pta of this type (whether they need to
+//               export it or not) should include this header file,
+//               rather than defining the pta again.
+////////////////////////////////////////////////////////////////////
+
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, RefCountObj<vector_TexCoordf>);
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToBase<RefCountObj<vector_TexCoordf> >);
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToArray<TexCoordf>)
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, ConstPointerToArray<TexCoordf>)
+
+typedef PointerToArray<TexCoordf> PTA_TexCoordf;
+typedef ConstPointerToArray<TexCoordf> CPTA_TexCoordf;
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#endif

+ 11 - 0
panda/src/linmath/pta_Vertexf.cxx

@@ -0,0 +1,11 @@
+// Filename: pta_Vertexf.cxx
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "pta_Vertexf.h"
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma implementation
+#endif

+ 37 - 0
panda/src/linmath/pta_Vertexf.h

@@ -0,0 +1,37 @@
+// Filename: pta_Vertexf.h
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef PTA_VERTEXF_H
+#define PTA_VERTEXF_H
+
+#include <pandabase.h>
+
+#include "vector_Vertexf.h"
+
+#include <pointerToArray.h>
+
+////////////////////////////////////////////////////////////////////
+//       Class : PTA_Vertexf
+// Description : A pta of Vertexfs.  This class is defined once here,
+//               and exported to PANDA.DLL; other packages that want
+//               to use a pta of this type (whether they need to
+//               export it or not) should include this header file,
+//               rather than defining the pta again.
+////////////////////////////////////////////////////////////////////
+
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, RefCountObj<vector_Vertexf>);
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToBase<RefCountObj<vector_Vertexf> >);
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToArray<Vertexf>);
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, ConstPointerToArray<Vertexf>);
+
+typedef PointerToArray<Vertexf> PTA_Vertexf;
+typedef ConstPointerToArray<Vertexf> CPTA_Vertexf;
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#endif

+ 147 - 0
panda/src/linmath/test_math.cxx

@@ -0,0 +1,147 @@
+// Filename: test_math.cxx
+// Created by:  drose (14Jan99)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "luse.h"
+#include "lmatrix.h"
+#include "compose_matrix.h"
+
+#include <notify.h>
+#include <stdlib.h>
+
+void test() {
+  LMatrix4f x = LMatrix4f::ident_mat();
+  LMatrix4f y = LMatrix4f::ident_mat();
+
+  LMatrix4f z = x * y;
+}
+
+int main(int argc, char *argv[]) {
+  test();
+
+  /*
+
+  LOrientationf orientation; // = LQuaternionf::ident_quat();
+  orientation.set(LMatrix4f::rotate_mat(-45.0f, LVector3f(0, 0, 1)));
+  LRotationf rotation(LMatrix4f::rotate_mat(45.0f, LVector3f(0, 0, 1)));
+
+  nout << "Orientation: " << orientation << endl;
+  nout << "Rotation: " << rotation << endl;
+
+  LQuaternionf composition = orientation * rotation;
+
+  nout << "Composition (o * r): " << composition << endl;
+  composition.normalize();
+  nout << "Composition (after normalize): " << composition << endl;
+
+  LPoint3f p(1, 0, 0);
+  LMatrix4f m = LMatrix4f::ident_mat();
+
+  composition.extract_to_matrix(m);
+  cout << "Rotation => Matrix: " << m << endl;
+  cout << "Point: " << p << endl;
+  cout << "Matrix * Point: " << m * p << endl;
+  */
+
+  /*
+  LMatrix4d x = LMatrix4d::ident_mat();
+  LMatrix4d y = LMatrix4d::rotate_mat(90.0, LVector3d::up());
+  LMatrix4d a = LMatrix4d::translate_mat(10.0, 10.0, 0.0);
+
+  nout << "x is " << x << "\ny is " << y << "\n"
+       << "x * y is " << x * y << "\n"
+       << "y * x is " << y * x << "\n"
+       << "invert(x) is " << invert(x) << "\n"
+       << "invert(y) is " << invert(y) << "\n"
+       << "y * a is " << y * a << "\n"
+       << "invert(y * a) is " << invert(y * a) << "\n"
+       << "invert(invert(y * a)) is " << invert(invert(y * a)) << "\n"
+       << "(y * a) * invert(y * a) is " << (y * a) * invert(y * a) << "\n"
+       << "a * y is " << a * y << "\n"
+       << "invert(a * y) is " << invert(a * y) << "\n"
+       << "invert(invert(a * y)) is " << invert(invert(a * y)) << "\n";
+
+  nout << "a is " << a << "\n"
+       << "a * y is " << a * y << "\n"
+       << "y * a is " << y * a << "\n";
+
+  LVector3d r = LVector3d::right();
+  nout << "r is " << r << "\n"
+       << "r * x is " << r * x << "\n"
+       << "r * y is " << r * y << "\n"
+       << "r * invert(y) is " << r * invert(y) << "\n"
+       << "r * a is " << r * a << "\n";
+
+  LPoint3d p(0.0, 1.0, 1.0);
+  nout << "p is " << p << "\n"
+       << "p * x is " << p * x << "\n"
+       << "p * y is " << p * y << "\n"
+       << "p * invert(y) is " << p * invert(y) << "\n" 
+       << "p * a is " << p * a << "\n";
+
+  LVecBase4d q(0.0, 1.0, 1.0, 1.0);
+  nout << "q is " << q << "\n"
+       << "q * x is " << q * x << "\n"
+       << "q * y is " << q * y << "\n"
+       << "q * invert(y) is " << q * invert(y) << "\n"
+       << "q * a is " << q * a << "\n";
+
+  Normald v1(0,0,1), v2(1,1,1);
+  Vertexd p1(1,0,1), p2(1,2,3);
+  Colorf c1(1,1,1,1), c2(0,0,0,0);
+
+  p2 = p2 - v1;
+
+  nout << "v1 = " << v1 
+       << "\nv2 = " << v2
+       << "\np1 = " << p1 
+       << "\np2 = " << p2
+       << "\nc1 = " << c1
+       << "\n(c1 == c2) = " << (c1 == c2)
+       << "\n";
+
+  {
+    LVecBase3f hpr(0.0, 0.0, 0.0);
+    LVecBase3f scale(1.0, 1.0, 1.0);
+
+    if (argc > 3) {
+      hpr.set(atof(argv[1]), atof(argv[2]), atof(argv[3]));
+    }
+    if (argc > 6) {
+      scale.set(atof(argv[4]), atof(argv[5]), atof(argv[6]));
+    }
+
+    cerr << "< hpr = " << hpr << " scale = " << scale << "\n";
+    LMatrix3f mat;
+    compose_matrix(mat, scale, hpr);
+
+    if (decompose_matrix(mat, scale, hpr)) {
+      nout << "> hpr = " << hpr << " scale = " << scale << "\n";
+    } else {
+      nout << "Cannot decompose\n";
+    }
+  }
+  */
+
+  /*
+  for (int p = -90; p < 90; p += 10) {
+    for (int x = -10; x < 10; x += 5) {
+      LVecBase3f hpr(0, p, 0);
+      LVecBase3f xyz(x, x, x);
+      LVecBase3f scale(1, 1, 1);
+      nout << "\n< hpr = " << hpr << " xyz = " << xyz << "\n";
+      LMatrix4f mat;
+      compose_matrix(mat, scale, hpr, xyz);
+      if (decompose_matrix(mat, scale, hpr, xyz)) {
+	nout << "> hpr = " << hpr << " xyz = " << xyz << "\n";
+      } else {
+	nout << "Cannot decompose\n";
+      }
+    }
+  }
+  */
+
+  return(0);
+}
+ 

+ 11 - 0
panda/src/linmath/vector_Colorf.cxx

@@ -0,0 +1,11 @@
+// Filename: vector_Colorf.cxx
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "vector_Colorf.h"
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma implementation
+#endif

+ 32 - 0
panda/src/linmath/vector_Colorf.h

@@ -0,0 +1,32 @@
+// Filename: vector_Colorf.h
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef VECTOR_COLORF_H
+#define VECTOR_COLORF_H
+
+#include <pandabase.h>
+
+#include "luse.h"
+
+#include <vector>
+
+////////////////////////////////////////////////////////////////////
+//       Class : vector_Colorf
+// Description : A vector of Colorfs.  This class is defined once here,
+//               and exported to PANDA.DLL; other packages that want
+//               to use a vector of this type (whether they need to
+//               export it or not) should include this header file,
+//               rather than defining the vector again.
+////////////////////////////////////////////////////////////////////
+
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, std::vector<Colorf>)
+typedef vector<Colorf> vector_Colorf;
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#endif

+ 11 - 0
panda/src/linmath/vector_LPoint2f.cxx

@@ -0,0 +1,11 @@
+// Filename: vector_LPoint2f.cxx
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "vector_LPoint2f.h"
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma implementation
+#endif

+ 32 - 0
panda/src/linmath/vector_LPoint2f.h

@@ -0,0 +1,32 @@
+// Filename: vector_LPoint2f.h
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef VECTOR_LPOINT2F_H
+#define VECTOR_LPOINT2F_H
+
+#include <pandabase.h>
+
+#include "luse.h"
+
+#include <vector>
+
+////////////////////////////////////////////////////////////////////
+//       Class : vector_LPoint2f
+// Description : A vector of LPoint2fs.  This class is defined once here,
+//               and exported to PANDA.DLL; other packages that want
+//               to use a vector of this type (whether they need to
+//               export it or not) should include this header file,
+//               rather than defining the vector again.
+////////////////////////////////////////////////////////////////////
+
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, std::vector<LPoint2f>)
+typedef vector<LPoint2f> vector_LPoint2f;
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#endif

+ 11 - 0
panda/src/linmath/vector_LVecBase3f.cxx

@@ -0,0 +1,11 @@
+// Filename: vector_LVecBase3f.cxx
+// Created by:  drose (11Dec00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "vector_LVecBase3f.h"
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma implementation
+#endif

+ 32 - 0
panda/src/linmath/vector_LVecBase3f.h

@@ -0,0 +1,32 @@
+// Filename: vector_LVecBase3f.h
+// Created by:  drose (11Dec00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef VECTOR_LVECBASE3F_H
+#define VECTOR_LVECBASE3F_H
+
+#include <pandabase.h>
+
+#include "luse.h"
+
+#include <vector>
+
+////////////////////////////////////////////////////////////////////
+//       Class : vector_LVecBase3f
+// Description : A vector of LVecBase3fs.  This class is defined once here,
+//               and exported to PANDA.DLL; other packages that want
+//               to use a vector of this type (whether they need to
+//               export it or not) should include this header file,
+//               rather than defining the vector again.
+////////////////////////////////////////////////////////////////////
+
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, std::vector<LVecBase3f>)
+typedef vector<LVecBase3f> vector_LVecBase3f;
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#endif

+ 11 - 0
panda/src/linmath/vector_Normalf.cxx

@@ -0,0 +1,11 @@
+// Filename: vector_Normalf.cxx
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "vector_Normalf.h"
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma implementation
+#endif

+ 32 - 0
panda/src/linmath/vector_Normalf.h

@@ -0,0 +1,32 @@
+// Filename: vector_Normalf.h
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef VECTOR_NORMALF_H
+#define VECTOR_NORMALF_H
+
+#include <pandabase.h>
+
+#include "luse.h"
+
+#include <vector>
+
+////////////////////////////////////////////////////////////////////
+//       Class : vector_Normalf
+// Description : A vector of Normalfs.  This class is defined once here,
+//               and exported to PANDA.DLL; other packages that want
+//               to use a vector of this type (whether they need to
+//               export it or not) should include this header file,
+//               rather than defining the vector again.
+////////////////////////////////////////////////////////////////////
+
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, std::vector<Normalf>)
+typedef vector<Normalf> vector_Normalf;
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#endif

+ 20 - 0
panda/src/linmath/vector_TexCoordf.h

@@ -0,0 +1,20 @@
+// Filename: vector_TexCoordf.h
+// Created by:  drose (11May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef VECTOR_TEXCOORDF_H
+#define VECTOR_TEXCOORDF_H
+
+#include <pandabase.h>
+
+#include "vector_LPoint2f.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : vector_TexCoordf
+// Description : This is just another name for vector_LPoint2f.
+////////////////////////////////////////////////////////////////////
+
+typedef vector_LPoint2f vector_TexCoordf;
+
+#endif

+ 11 - 0
panda/src/linmath/vector_Vertexf.cxx

@@ -0,0 +1,11 @@
+// Filename: vector_Vertexf.cxx
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "vector_Vertexf.h"
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma implementation
+#endif

+ 32 - 0
panda/src/linmath/vector_Vertexf.h

@@ -0,0 +1,32 @@
+// Filename: vector_Vertexf.h
+// Created by:  drose (10May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef VECTOR_VERTEXF_H
+#define VECTOR_VERTEXF_H
+
+#include <pandabase.h>
+
+#include "luse.h"
+
+#include <vector>
+
+////////////////////////////////////////////////////////////////////
+//       Class : vector_Vertexf
+// Description : A vector of Vertexfs.  This class is defined once here,
+//               and exported to PANDA.DLL; other packages that want
+//               to use a vector of this type (whether they need to
+//               export it or not) should include this header file,
+//               rather than defining the vector again.
+////////////////////////////////////////////////////////////////////
+
+EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, std::vector<Vertexf>)
+typedef vector<Vertexf> vector_Vertexf;
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#endif

+ 47 - 0
panda/src/mathutil/Sources.pp

@@ -0,0 +1,47 @@
+#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
+                   dtoolutil:c dtoolbase:c dtool:m
+
+#begin lib_target
+  #define TARGET mathutil
+  #define LOCAL_LIBS \
+    linmath putil
+  #define USE_FFTW yes
+  #define UNIX_SYS_LIBS m
+
+  #define SOURCES \
+    boundingHexahedron.I boundingHexahedron.cxx boundingHexahedron.h  \
+    boundingLine.I boundingLine.cxx boundingLine.h boundingSphere.I \
+    boundingSphere.cxx boundingSphere.h boundingVolume.I \
+    boundingVolume.cxx boundingVolume.h config_mathutil.cxx \
+    config_mathutil.h fftCompressor.cxx fftCompressor.h \
+    finiteBoundingVolume.cxx finiteBoundingVolume.h frustum.h \
+    frustum_src.I frustum_src.h geometricBoundingVolume.I \
+    geometricBoundingVolume.cxx geometricBoundingVolume.h look_at.cxx \
+    look_at.h look_at_src.I look_at_src.h omniBoundingVolume.I \
+    omniBoundingVolume.cxx omniBoundingVolume.h plane.cxx plane.h \
+    plane_src.I plane_src.h rotate_to.cxx rotate_to.h
+
+  #define INSTALL_HEADERS \
+    boundingHexahedron.I boundingHexahedron.h boundingLine.I \
+    boundingLine.h boundingSphere.I boundingSphere.h boundingVolume.I \
+    boundingVolume.h config_mathutil.h fftCompressor.h \
+    finiteBoundingVolume.h frustum.h frustum_src.I frustum_src.h \
+    geometricBoundingVolume.I geometricBoundingVolume.h look_at.h \
+    look_at_src.I look_at_src.h mathHelpers.I mathHelpers.h \
+    omniBoundingVolume.I omniBoundingVolume.h plane.h plane_src.I \
+    plane_src.h rotate_to.h
+
+  #define IGATESCAN all
+
+#end lib_target
+
+#begin test_bin_target
+  #define TARGET test_mathutil
+  #define LOCAL_LIBS \
+    mathutil
+
+  #define SOURCES \
+    test_mathutil.cxx
+
+#end test_bin_target
+

+ 30 - 0
panda/src/mathutil/boundingHexahedron.I

@@ -0,0 +1,30 @@
+// Filename: boundingHexahedron.I
+// Created by:  drose (03Oct99)
+// 
+////////////////////////////////////////////////////////////////////
+
+INLINE BoundingHexahedron::
+BoundingHexahedron() {
+}
+
+INLINE int BoundingHexahedron::
+get_num_points() const {
+  return num_points;
+}
+
+INLINE LPoint3f BoundingHexahedron::
+get_point(int n) const {
+  nassertr(n >= 0 && n < num_points, LPoint3f(0.0, 0.0, 0.0));
+  return _points[n];
+}
+
+INLINE int BoundingHexahedron::
+get_num_planes() const {
+  return num_planes;
+}
+
+INLINE Planef BoundingHexahedron::
+get_plane(int n) const {
+  nassertr(n >= 0 && n < num_planes, Planef());
+  return _planes[n];
+}

+ 336 - 0
panda/src/mathutil/boundingHexahedron.cxx

@@ -0,0 +1,336 @@
+// Filename: boundingHexahedron.cxx
+// Created by:  drose (03Oct99)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "boundingHexahedron.h"
+#include "boundingSphere.h"
+#include "config_mathutil.h"
+
+#include <math.h>
+#include <algorithm>
+
+TypeHandle BoundingHexahedron::_type_handle;
+
+BoundingHexahedron::
+BoundingHexahedron(const Frustumf &frustum, bool is_ortho,
+		   CoordinateSystem cs) {
+  if (cs == CS_default) {
+    cs = default_coordinate_system;
+  }
+
+  float fs = 1.0;
+  if (!is_ortho) {
+    fs = frustum._ffar / frustum._fnear;
+  }
+
+  // We build the points based on a Z-up right-handed frustum.  If the
+  // requested coordinate system is otherwise, we'll convert it in a
+  // second pass.
+  _points[0].set(frustum._l * fs, frustum._ffar, frustum._b * fs);
+  _points[1].set(frustum._r * fs, frustum._ffar, frustum._b * fs);
+  _points[2].set(frustum._r * fs, frustum._ffar, frustum._t * fs);
+  _points[3].set(frustum._l * fs, frustum._ffar, frustum._t * fs);
+  _points[4].set(frustum._l, frustum._fnear, frustum._b);
+  _points[5].set(frustum._r, frustum._fnear, frustum._b);
+  _points[6].set(frustum._r, frustum._fnear, frustum._t);
+  _points[7].set(frustum._l, frustum._fnear, frustum._t);
+
+  _flags = 0;
+
+  // Now fix the coordinate system, if necessary.
+  if (cs == CS_zup_right) {
+    set_centroid();
+    set_planes();
+  } else {
+    xform(LMatrix4f::convert_mat(CS_zup_right, cs));
+  }
+}
+
+BoundingVolume *BoundingHexahedron::
+make_copy() const {
+  return new BoundingHexahedron(*this);
+}
+
+LPoint3f BoundingHexahedron::
+get_min() const {
+  nassertr(!is_empty(), LPoint3f(0.0, 0.0, 0.0));
+  nassertr(!is_infinite(), LPoint3f(0.0, 0.0, 0.0));
+  int i;
+  LPoint3f m = _points[0];
+  for (i = 1; i < num_points; i++) {
+    m.set(min(m[0], _points[i][0]),
+	  min(m[1], _points[i][1]),
+	  min(m[2], _points[i][2]));
+  }
+  return m;
+}
+
+LPoint3f BoundingHexahedron::
+get_max() const {
+  nassertr(!is_empty(), LPoint3f(0.0, 0.0, 0.0));
+  nassertr(!is_infinite(), LPoint3f(0.0, 0.0, 0.0));
+  int i;
+  LPoint3f m = _points[0];
+  for (i = 1; i < num_points; i++) {
+    m.set(max(m[0], _points[i][0]),
+	  max(m[1], _points[i][1]),
+	  max(m[2], _points[i][2]));
+  }
+  return m;
+}
+
+LPoint3f BoundingHexahedron::
+get_approx_center() const {
+  nassertr(!is_empty(), LPoint3f(0.0, 0.0, 0.0));
+  nassertr(!is_infinite(), LPoint3f(0.0, 0.0, 0.0));
+  return _centroid;
+}
+
+void BoundingHexahedron::
+xform(const LMatrix4f &mat) {
+  if (!is_empty() && !is_infinite()) {
+    for (int i = 0; i < num_points; i++) {
+      _points[i] = _points[i] * mat;
+    }
+    set_centroid();
+    set_planes();
+  }
+}
+
+void BoundingHexahedron::
+output(ostream &out) const {
+  if (is_empty()) {
+    out << "bhexahedron, empty";
+  } else if (is_infinite()) {
+    out << "bhexahedron, infinite";
+  } else {
+    out << "bhexahedron, min " << get_min() << " max " << get_max();
+  }
+}
+
+void BoundingHexahedron::
+write(ostream &out, int indent_level) const {
+  if (is_empty()) {
+    indent(out, indent_level) << "bhexahedron, empty\n";
+  } else if (is_infinite()) {
+    out << "bhexahedron, infinite\n";
+  } else {
+    indent(out, indent_level)
+      << "bhexahedron, min " << get_min() << " max " << get_max() << ":\n";
+    int i;
+    for (i = 0; i < num_points; i++) {
+      indent(out, indent_level + 2) << _points[i] << "\n";
+    }
+    indent(out, indent_level + 2) << "centroid is " << _centroid << "\n";
+  }
+}
+
+bool BoundingHexahedron::
+extend_other(BoundingVolume *other) const {
+  return other->extend_by_hexahedron(this);
+}
+
+bool BoundingHexahedron::
+around_other(BoundingVolume *other,
+	     const BoundingVolume **first,
+	     const BoundingVolume **last) const {
+  return other->around_hexahedrons(first, last);
+}
+
+int BoundingHexahedron::
+contains_other(const BoundingVolume *other) const {
+  return other->contains_hexahedron(this);
+}
+
+
+bool BoundingHexahedron::
+extend_by_point(const LPoint3f &) {
+  mathutil_cat.error()
+    << "BoundingHexahedron::extend_by_point() called\n";
+  return false;
+}
+
+bool BoundingHexahedron::
+extend_by_sphere(const BoundingSphere *) {
+  mathutil_cat.error()
+    << "BoundingHexahedron::extend_by_sphere() called\n";  
+  return false;
+}
+
+bool BoundingHexahedron::
+extend_by_hexahedron(const BoundingHexahedron *) {
+  mathutil_cat.error()
+    << "BoundingHexahedron::extend_by_hexahedron() called\n";  
+  return false;
+}
+
+bool BoundingHexahedron::
+around_points(const LPoint3f *, const LPoint3f *) {
+  mathutil_cat.error()
+    << "BoundingHexahedron::around_points() called\n";  
+  return false;
+}
+
+bool BoundingHexahedron::
+around_spheres(const BoundingVolume **, 
+	       const BoundingVolume **) {
+  mathutil_cat.error()
+    << "BoundingHexahedron::around_spheres() called\n";
+  return false;
+}
+
+bool BoundingHexahedron::
+around_hexahedrons(const BoundingVolume **, 
+		   const BoundingVolume **) {
+  mathutil_cat.error()
+    << "BoundingHexahedron::around_hexahedrons() called\n";
+  return false;
+}
+
+int BoundingHexahedron::
+contains_point(const LPoint3f &point) const {
+  if (is_empty()) {
+    return IF_no_intersection;
+
+  } else if (is_infinite()) {
+    return IF_possible | IF_some | IF_all;
+
+  } else {
+    // The hexahedron contains the point iff the point is behind all of
+    // the planes.
+    for (int i = 0; i < num_planes; i++) {
+      const Planef &p = _planes[i];
+      if (p.dist_to_plane(point) > 0.0) {
+	return IF_no_intersection;
+      }
+    }
+    return IF_possible | IF_some | IF_all;
+  }
+}
+
+int BoundingHexahedron::
+contains_lineseg(const LPoint3f &a, const LPoint3f &b) const {
+  if (is_empty()) {
+    return IF_no_intersection;
+
+  } else if (is_infinite()) {
+    return IF_possible | IF_some | IF_all;
+
+  } else {
+    // The hexahedron does not contains the line segment if both points
+    // are in front of any one plane.
+    for (int i = 0; i < num_planes; i++) {
+      const Planef &p = _planes[i];
+      if (p.dist_to_plane(a) > 0.0 ||
+	  p.dist_to_plane(b) > 0.0) {
+	return IF_no_intersection;
+      }
+    }
+    
+    // If there is no plane that both points are in front of, the
+    // hexahedron may or may not contain the line segment.  For the
+    // moment, we won't bother to check that more thoroughly, though.
+    return IF_possible;
+  }
+}
+
+int BoundingHexahedron::
+contains_sphere(const BoundingSphere *sphere) const {
+  nassertr(!is_empty(), 0);
+
+  // The hexahedron contains the sphere iff the sphere is at least
+  // partly behind all of the planes.
+  const LPoint3f &center = sphere->get_center();
+  float radius = sphere->get_radius();
+
+  int result = IF_possible | IF_some | IF_all;
+
+  for (int i = 0; i < num_planes; i++) {
+    const Planef &p = _planes[i];
+    float dist = p.dist_to_plane(center);
+
+    if (dist > radius) {
+      // The sphere is completely in front of this plane; it's thus
+      // completely outside of the hexahedron.
+      return IF_no_intersection;
+
+    } else if (dist > -radius) {
+      // The sphere is not completely behind this plane, but some of
+      // it is.
+      result &= ~IF_all;
+    } 
+  }
+
+  return result;
+}
+
+int BoundingHexahedron::
+contains_hexahedron(const BoundingHexahedron *hexahedron) const {
+  nassertr(!is_empty(), 0);
+  nassertr(!hexahedron->is_empty(), 0);
+  
+  // Check minmax.
+  LPoint3f min1 = get_min();
+  LPoint3f min2 = hexahedron->get_min();
+  LPoint3f max1 = get_max();
+  LPoint3f max2 = hexahedron->get_max();
+  
+  if (min1[0] > max2[0] || min1[1] > max2[1] || min1[2] > max2[2] ||
+      min2[0] > max1[0] || min2[1] > max1[1] || min2[2] > max1[2] ||
+      max1[0] < min2[0] || max1[1] < min2[1] || max1[2] < min2[2] ||
+      max2[0] < min1[0] || max2[1] < min1[1] || max2[2] < min1[2]) {
+    return IF_no_intersection;
+  }
+
+  int result = IF_possible | IF_all;
+
+  for (int i = 0; i < num_points; i++) {
+    if (contains_point(hexahedron->_points[i])) {
+      result |= IF_some;
+    } else {
+      result &= ~IF_all;
+    }
+  }
+
+  return result;
+}
+
+void BoundingHexahedron::
+set_planes() {
+  _planes[0] = Planef(_points[0], _points[3], _points[2]);
+
+  // Test to see if we have accidentally inverted our frustum by
+  // transforming it with a -1 matrix.  We do this by ensuring that
+  // the centroid is in front of all of the planes (actually, we only
+  // need to test the first plane).
+  if (_planes[0].dist_to_plane(_centroid) >= 0) {
+    // Oops!  We're flipped!  Rebuild the planes in the opposite
+    // direction.
+    _planes[0] = Planef(_points[0], _points[2], _points[3]);
+    _planes[1] = Planef(_points[0], _points[5], _points[1]);
+    _planes[2] = Planef(_points[1], _points[6], _points[2]);
+    _planes[3] = Planef(_points[2], _points[7], _points[3]);
+    _planes[4] = Planef(_points[3], _points[4], _points[0]);
+    _planes[5] = Planef(_points[4], _points[7], _points[6]);
+
+    nassertv(_planes[0].dist_to_plane(_centroid) < 0);
+
+  } else {    
+    // No, a perfectly sane universe.
+    _planes[1] = Planef(_points[0], _points[1], _points[5]);
+    _planes[2] = Planef(_points[1], _points[2], _points[6]);
+    _planes[3] = Planef(_points[2], _points[3], _points[7]);
+    _planes[4] = Planef(_points[3], _points[0], _points[4]);
+    _planes[5] = Planef(_points[4], _points[6], _points[7]);
+  }
+}
+
+void BoundingHexahedron::
+set_centroid() {
+  LPoint3f net = _points[0];
+  for (int i = 1; i < num_points; i++) {
+    net += _points[i];
+  }
+  _centroid = net / (float)num_points;
+}

+ 109 - 0
panda/src/mathutil/boundingHexahedron.h

@@ -0,0 +1,109 @@
+// Filename: boundingHexahedron.h
+// Created by:  drose (03Oct99)
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef BOUNDINGHEXAHEDRON_H
+#define BOUNDINGHEXAHEDRON_H
+
+#include <pandabase.h>
+
+#include "finiteBoundingVolume.h"
+#include "frustum.h"
+#include "plane.h"
+
+#include <coordinateSystem.h>
+
+
+///////////////////////////////////////////////////////////////////
+// 	 Class : BoundingHexahedron
+// Description : This defines a bounding convex hexahedron.  It is
+//               typically used to represent a frustum, but may
+//               represent any enclosing convex hexahedron.
+//
+//               This class does not support any of the around() or
+//               extend_by() functions, but all other functionality
+//               should be well-defined.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA BoundingHexahedron : public FiniteBoundingVolume {
+public:
+  INLINE BoundingHexahedron();
+  BoundingHexahedron(const Frustumf &frustum, bool is_ortho,
+		     CoordinateSystem cs = CS_default);
+  virtual BoundingVolume *make_copy() const;
+
+  virtual LPoint3f get_min() const;
+  virtual LPoint3f get_max() const;
+
+  virtual LPoint3f get_approx_center() const;
+  virtual void xform(const LMatrix4f &mat);
+
+  virtual void output(ostream &out) const;
+  virtual void write(ostream &out, int indent_level = 0) const;
+
+  INLINE int get_num_points() const;
+  INLINE LPoint3f get_point(int n) const;
+  INLINE int get_num_planes() const;
+  INLINE Planef get_plane(int n) const;
+
+protected:
+  virtual bool extend_other(BoundingVolume *other) const;
+  virtual bool around_other(BoundingVolume *other,
+			    const BoundingVolume **first,
+			    const BoundingVolume **last) const;
+  virtual int contains_other(const BoundingVolume *other) const;
+
+
+  virtual bool extend_by_point(const LPoint3f &point);
+  virtual bool extend_by_sphere(const BoundingSphere *sphere);
+  virtual bool extend_by_hexahedron(const BoundingHexahedron *hexahedron);
+
+  virtual bool around_points(const LPoint3f *first,
+			     const LPoint3f *last);
+  virtual bool around_spheres(const BoundingVolume **first,
+			      const BoundingVolume **last);
+  virtual bool around_hexahedrons(const BoundingVolume **first,
+				  const BoundingVolume **last);
+
+  virtual int contains_point(const LPoint3f &point) const;
+  virtual int contains_lineseg(const LPoint3f &a, const LPoint3f &b) const;
+  virtual int contains_sphere(const BoundingSphere *sphere) const;
+  virtual int contains_hexahedron(const BoundingHexahedron *hexahedron) const;
+
+private:
+  void set_planes();
+  void set_centroid();
+
+private:
+  enum {
+    num_points = 8,
+    num_planes = 6
+  };
+  LPoint3f _points[num_points];
+  Planef _planes[num_planes];
+  LPoint3f _centroid;
+
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    FiniteBoundingVolume::init_type();
+    register_type(_type_handle, "BoundingHexahedron",
+		  FiniteBoundingVolume::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+
+  friend class BoundingSphere;
+};
+
+#include "boundingHexahedron.I"
+
+#endif

+ 33 - 0
panda/src/mathutil/boundingLine.I

@@ -0,0 +1,33 @@
+// Filename: boundingLine.I
+// Created by:  drose (04Jul00)
+// 
+////////////////////////////////////////////////////////////////////
+
+INLINE BoundingLine::
+BoundingLine() {
+}
+
+INLINE BoundingLine::
+BoundingLine(const LPoint3f &a, const LPoint3f &b) :
+  _origin(a), _vector(b - a) 
+{
+  _vector.normalize();
+  _flags = 0;
+  nassertd(!_origin.is_nan() && !_vector.is_nan()) {
+    _flags = F_empty;
+  }
+}
+
+INLINE const LPoint3f &BoundingLine::
+get_point_a() const {
+  nassertr(!is_empty(), _origin);
+  nassertr(!is_infinite(), _origin);
+  return _origin;
+}
+
+INLINE LPoint3f BoundingLine::
+get_point_b() const {
+  nassertr(!is_empty(), _origin);
+  nassertr(!is_infinite(), _origin);
+  return _origin + _vector;
+}

+ 114 - 0
panda/src/mathutil/boundingLine.cxx

@@ -0,0 +1,114 @@
+// Filename: boundingLine.cxx
+// Created by:  drose (04Jul00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "boundingLine.h"
+#include "boundingSphere.h"
+#include "config_mathutil.h"
+
+#include <math.h>
+
+TypeHandle BoundingLine::_type_handle;
+
+BoundingVolume *BoundingLine::
+make_copy() const {
+  return new BoundingLine(*this);
+}
+
+LPoint3f BoundingLine::
+get_approx_center() const {
+  nassertr(!is_empty(), LPoint3f(0.0, 0.0, 0.0));
+  nassertr(!is_infinite(), LPoint3f(0.0, 0.0, 0.0));
+  return (get_point_a() + get_point_b()) / 2.0;
+}
+
+void BoundingLine::
+xform(const LMatrix4f &mat) {
+  nassertv(!mat.is_nan());
+
+  if (!is_empty() && !is_infinite()) {
+    _origin = _origin * mat;
+    _vector = _vector * mat;
+    _vector.normalize();
+  }
+}
+
+void BoundingLine::
+output(ostream &out) const {
+  if (is_empty()) {
+    out << "bline, empty";
+  } else if (is_infinite()) {
+    out << "bline, infinite";
+  } else {
+    out << "bline, (" << _origin << ") - (" << _origin + _vector << ")";
+  }
+}
+
+bool BoundingLine::
+extend_other(BoundingVolume *other) const {
+  return other->extend_by_line(this);
+}
+
+bool BoundingLine::
+around_other(BoundingVolume *other,
+	     const BoundingVolume **first,
+	     const BoundingVolume **last) const {
+  return other->around_lines(first, last);
+}
+
+int BoundingLine::
+contains_other(const BoundingVolume *other) const {
+  return other->contains_line(this);
+}
+
+
+bool BoundingLine::
+extend_by_line(const BoundingLine *line) {
+  nassertr(!line->is_empty() && !line->is_infinite(), false);
+  nassertr(!is_infinite(), false);
+
+  if (is_empty()) {
+    _origin = line->_origin;
+    _vector = line->_vector;
+    _flags = 0;
+  } else {
+    _flags = F_infinite;
+  }
+  return true;
+}
+
+int BoundingLine::
+contains_sphere(const BoundingSphere *sphere) const {
+  nassertr(!is_empty() && !is_infinite(), 0);
+  nassertr(!sphere->is_empty() && !sphere->is_infinite(), 0);
+
+  float r = sphere->get_radius();
+
+  if (r * r >= sqr_dist_to_line(sphere->get_center())) {
+    return IF_possible | IF_some;
+  } else {
+    return IF_no_intersection;
+  }
+}
+
+float BoundingLine::
+sqr_dist_to_line(const LPoint3f &point) const {
+  nassertr(!point.is_nan(), 0.0);
+  nassertr(!is_empty() && !is_infinite(), 0.0);
+  nassertr(!_vector.almost_equal(LVector3f(0.0, 0.0, 0.0)), 0.0);
+
+  // The formula for the distance from a point to the line based on
+  // the quadratic equation.
+
+  float A = dot(_vector, _vector);
+  nassertr(A != 0.0, 0.0);
+  LVector3f fc = _origin - point;
+  float B = 2.0 * dot(_vector, fc);
+  float fc_d2 = dot(fc, fc);
+
+  float r2 = fc_d2 - B*B / 4.0*A;
+
+  nassertr(!cnan(r2), 0.0);
+  return r2;
+}

+ 81 - 0
panda/src/mathutil/boundingLine.h

@@ -0,0 +1,81 @@
+// Filename: boundingLine.h
+// Created by:  drose (04Jul00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef BOUNDINGLINE_H
+#define BOUNDINGLINE_H
+
+#include <pandabase.h>
+
+#include "geometricBoundingVolume.h"
+
+///////////////////////////////////////////////////////////////////
+// 	 Class : BoundingLine
+// Description : This funny bounding volume is an infinite line with
+//               no thickness and extending to infinity in both
+//               directions.
+//
+//               Note that it *always* extends in both directions,
+//               despite the fact that you specify two points to the
+//               constructor.  These are not endpoints, they are two
+//               arbitrary points on the line.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA BoundingLine : public GeometricBoundingVolume {
+PUBLISHED:
+  INLINE BoundingLine();
+  INLINE BoundingLine(const LPoint3f &a, const LPoint3f &b);
+
+public:
+  virtual BoundingVolume *make_copy() const;
+
+  virtual LPoint3f get_approx_center() const;
+  virtual void xform(const LMatrix4f &mat);
+
+  virtual void output(ostream &out) const;
+
+PUBLISHED:
+  INLINE const LPoint3f &get_point_a() const;
+  INLINE LPoint3f get_point_b() const;
+
+protected:
+  virtual bool extend_other(BoundingVolume *other) const;
+  virtual bool around_other(BoundingVolume *other,
+			    const BoundingVolume **first,
+			    const BoundingVolume **last) const;
+  virtual int contains_other(const BoundingVolume *other) const;
+
+  virtual bool extend_by_line(const BoundingLine *line);
+
+  virtual int contains_sphere(const BoundingSphere *sphere) const;
+
+  float sqr_dist_to_line(const LPoint3f &point) const;
+
+private:
+  LPoint3f _origin;
+  LVector3f _vector;
+
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    GeometricBoundingVolume::init_type();
+    register_type(_type_handle, "BoundingLine",
+		  GeometricBoundingVolume::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+
+  friend class BoundingSphere;
+};
+
+#include "boundingLine.I"
+
+#endif

Some files were not shown because too many files changed in this diff