diff --git a/panda/src/linmath/Sources.pp b/panda/src/linmath/Sources.pp new file mode 100644 index 0000000000..d2b49f22c8 --- /dev/null +++ b/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 + diff --git a/panda/src/linmath/cast_to_double.I b/panda/src/linmath/cast_to_double.I new file mode 100644 index 0000000000..b4fa0e443e --- /dev/null +++ b/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); +} + diff --git a/panda/src/linmath/cast_to_double.h b/panda/src/linmath/cast_to_double.h new file mode 100644 index 0000000000..bc6f4c7ad6 --- /dev/null +++ b/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 + + diff --git a/panda/src/linmath/cast_to_float.I b/panda/src/linmath/cast_to_float.I new file mode 100644 index 0000000000..50ceabe700 --- /dev/null +++ b/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); +} + diff --git a/panda/src/linmath/cast_to_float.h b/panda/src/linmath/cast_to_float.h new file mode 100644 index 0000000000..64a4c9e0d7 --- /dev/null +++ b/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 + + diff --git a/panda/src/linmath/cmath.I b/panda/src/linmath/cmath.I new file mode 100644 index 0000000000..e6865ce5a9 --- /dev/null +++ b/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 +#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 +} + + diff --git a/panda/src/linmath/cmath.h b/panda/src/linmath/cmath.h new file mode 100644 index 0000000000..ccb164edbb --- /dev/null +++ b/panda/src/linmath/cmath.h @@ -0,0 +1,40 @@ +// Filename: cmath.h +// Created by: drose (19May00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef CMATH_H +#define CMATH_H + +#include + +#include + +// 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 + diff --git a/panda/src/linmath/compose_matrix.cxx b/panda/src/linmath/compose_matrix.cxx new file mode 100644 index 0000000000..d02b944bf9 --- /dev/null +++ b/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" + + + diff --git a/panda/src/linmath/compose_matrix.h b/panda/src/linmath/compose_matrix.h new file mode 100644 index 0000000000..5811bba042 --- /dev/null +++ b/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 +#include +#include "lmatrix.h" +#include "luse.h" + +#include "fltnames.h" +#include "compose_matrix_src.h" + +#include "dblnames.h" +#include "compose_matrix_src.h" + +#endif + diff --git a/panda/src/linmath/compose_matrix_src.I b/panda/src/linmath/compose_matrix_src.I new file mode 100644 index 0000000000..78ca9519ca --- /dev/null +++ b/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; +} diff --git a/panda/src/linmath/config_linmath.cxx b/panda/src/linmath/config_linmath.cxx new file mode 100644 index 0000000000..fe57f8026d --- /dev/null +++ b/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 + +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; +} diff --git a/panda/src/linmath/config_linmath.h b/panda/src/linmath/config_linmath.h new file mode 100644 index 0000000000..c850e7bdcf --- /dev/null +++ b/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 +#include + +NotifyCategoryDecl(linmath, EXPCL_PANDA, EXPTP_PANDA); + +#endif diff --git a/panda/src/linmath/coordinateSystem.cxx b/panda/src/linmath/coordinateSystem.cxx new file mode 100644 index 0000000000..c1317ade4b --- /dev/null +++ b/panda/src/linmath/coordinateSystem.cxx @@ -0,0 +1,96 @@ +// Filename: coordinateSystem.cxx +// Created by: drose (24Sep99) +// +//////////////////////////////////////////////////////////////////// + +#include "coordinateSystem.h" +#include "config_linmath.h" + +#include +#include + +#include +#include + +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; +} diff --git a/panda/src/linmath/coordinateSystem.h b/panda/src/linmath/coordinateSystem.h new file mode 100644 index 0000000000..f82b0efa2e --- /dev/null +++ b/panda/src/linmath/coordinateSystem.h @@ -0,0 +1,46 @@ +// Filename: coordinateSystem.h +// Created by: drose (24Sep99) +// +//////////////////////////////////////////////////////////////////// + +#ifndef COORDINATESYSTEM_H +#define COORDINATESYSTEM_H + +#include + +#include + +#include + +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 + diff --git a/panda/src/linmath/deg_2_rad.h b/panda/src/linmath/deg_2_rad.h new file mode 100644 index 0000000000..b7a29d9b30 --- /dev/null +++ b/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 + +#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 + diff --git a/panda/src/linmath/ioPtaDatagramLinMath.I b/panda/src/linmath/ioPtaDatagramLinMath.I new file mode 100644 index 0000000000..0c73bd82ce --- /dev/null +++ b/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 +void IoPtaDatagramLinMath:: +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 +PTA(LinMathElement) IoPtaDatagramLinMath:: +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; +} + + diff --git a/panda/src/linmath/ioPtaDatagramLinMath.cxx b/panda/src/linmath/ioPtaDatagramLinMath.cxx new file mode 100644 index 0000000000..d14e9caf82 --- /dev/null +++ b/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 diff --git a/panda/src/linmath/ioPtaDatagramLinMath.h b/panda/src/linmath/ioPtaDatagramLinMath.h new file mode 100644 index 0000000000..7076e53464 --- /dev/null +++ b/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 + +#include "luse.h" +#include "pta_Vertexf.h" +#include "pta_Colorf.h" +#include "pta_Normalf.h" +#include "pta_TexCoordf.h" + +#include + +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 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) +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, IoPtaDatagramLinMath) +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, IoPtaDatagramLinMath) +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, IoPtaDatagramLinMath) + + +typedef IoPtaDatagramLinMath IPD_Colorf; +typedef IoPtaDatagramLinMath IPD_Normalf; +typedef IoPtaDatagramLinMath IPD_TexCoordf; +typedef IoPtaDatagramLinMath IPD_Vertexf; + + +// Tell GCC that we'll take care of the instantiation explicitly here. +#ifdef __GNUC__ +#pragma interface +#endif + +#endif diff --git a/panda/src/linmath/lmat_ops.h b/panda/src/linmath/lmat_ops.h new file mode 100644 index 0000000000..7db7174c45 --- /dev/null +++ b/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 diff --git a/panda/src/linmath/lmatrix.cxx b/panda/src/linmath/lmatrix.cxx new file mode 100644 index 0000000000..fd0042df3c --- /dev/null +++ b/panda/src/linmath/lmatrix.cxx @@ -0,0 +1,13 @@ +// Filename: lmatrix.cxx +// Created by: drose (22Feb99) +// +//////////////////////////////////////////////////////////////////// + +#include +#include "lmatrix.h" + +// This tells GCC to explicitly instantiate the templates defined in +// lmatrix.h and leave them here. +#ifdef __GNUC__ +#pragma implementation +#endif diff --git a/panda/src/linmath/lmatrix.h b/panda/src/linmath/lmatrix.h new file mode 100644 index 0000000000..9e68db8ec8 --- /dev/null +++ b/panda/src/linmath/lmatrix.h @@ -0,0 +1,28 @@ +// Filename: lmatrix.h +// Created by: drose (15Jan99) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LMATRIX_H +#define LMATRIX_H + +#include +#include "config_linmath.h" + +#include "lmatrix3.h" +#include "lmatrix4.h" + +/* +typedef LMatrix3 LMatrix3f; +typedef LMatrix4 LMatrix4f; + +typedef LMatrix3 LMatrix3d; +typedef LMatrix4 LMatrix4d; +*/ + +// Tell GCC that we'll take care of the instantiation explicitly here. +#ifdef __GNUC__ +#pragma interface +#endif + +#endif diff --git a/panda/src/linmath/lmatrix3.cxx b/panda/src/linmath/lmatrix3.cxx new file mode 100644 index 0000000000..81b460f617 --- /dev/null +++ b/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" + + diff --git a/panda/src/linmath/lmatrix3.h b/panda/src/linmath/lmatrix3.h new file mode 100644 index 0000000000..8599261db6 --- /dev/null +++ b/panda/src/linmath/lmatrix3.h @@ -0,0 +1,28 @@ +// Filename: lmatrix3.h +// Created by: drose (29Jan99) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LMATRIX3_H +#define LMATRIX3_H + +#include +#include +#include +#include +#include +#include +#include +#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 diff --git a/panda/src/linmath/lmatrix3_src.I b/panda/src/linmath/lmatrix3_src.I new file mode 100644 index 0000000000..f91c39808d --- /dev/null +++ b/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) ©) { + (*this) = copy; +} + +//////////////////////////////////////////////////////////////////// +// Function: LMatrix3::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE FLOATNAME(LMatrix3) &FLOATNAME(LMatrix3):: +operator = (const FLOATNAME(LMatrix3) ©) { + 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; +} diff --git a/panda/src/linmath/lmatrix4.cxx b/panda/src/linmath/lmatrix4.cxx new file mode 100644 index 0000000000..d992bf0751 --- /dev/null +++ b/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" + + diff --git a/panda/src/linmath/lmatrix4.h b/panda/src/linmath/lmatrix4.h new file mode 100644 index 0000000000..e1d8bb1dca --- /dev/null +++ b/panda/src/linmath/lmatrix4.h @@ -0,0 +1,30 @@ +// Filename: lmatrix4.h +// Created by: drose (29Jan99) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LMATRIX4_H +#define LMATRIX4_H + +#include +#include +#include +#include +#include +#include + +#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 diff --git a/panda/src/linmath/lmatrix4_src.I b/panda/src/linmath/lmatrix4_src.I new file mode 100644 index 0000000000..bd2aedbfe3 --- /dev/null +++ b/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) ©) { + (*this) = copy; +} + +//////////////////////////////////////////////////////////////////// +// Function: LMatrix4::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE FLOATNAME(LMatrix4) &FLOATNAME(LMatrix4):: +operator = (const FLOATNAME(LMatrix4) ©) { + 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; +} diff --git a/panda/src/linmath/lorientation.cxx b/panda/src/linmath/lorientation.cxx new file mode 100644 index 0000000000..75684c3a61 --- /dev/null +++ b/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" + diff --git a/panda/src/linmath/lorientation.h b/panda/src/linmath/lorientation.h new file mode 100644 index 0000000000..bb427e0909 --- /dev/null +++ b/panda/src/linmath/lorientation.h @@ -0,0 +1,19 @@ +// Filename: lorientation.h +// Created by: frang, charles (23Jun00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef __LORIENTATION_H__ +#define __LORIENTATION_H__ + +#include +#include +#include "lquaternion.h" + +#include "fltnames.h" +#include "lorientation_src.h" + +#include "dblnames.h" +#include "lorientation_src.h" + +#endif /* __LORIENTATION_H__ */ diff --git a/panda/src/linmath/lorientation_src.I b/panda/src/linmath/lorientation_src.I new file mode 100644 index 0000000000..c52444a920 --- /dev/null +++ b/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; +} diff --git a/panda/src/linmath/lpoint2.cxx b/panda/src/linmath/lpoint2.cxx new file mode 100644 index 0000000000..cf31bc093e --- /dev/null +++ b/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" + diff --git a/panda/src/linmath/lpoint2.h b/panda/src/linmath/lpoint2.h new file mode 100644 index 0000000000..939bba5779 --- /dev/null +++ b/panda/src/linmath/lpoint2.h @@ -0,0 +1,21 @@ +// Filename: lpoint2.h +// Created by: drose (08Mar00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LPOINT2_H +#define LPOINT2_H + +#include + +#include "lvecBase2.h" +#include "lvector2.h" + +#include "fltnames.h" +#include "lpoint2_src.h" + +#include "dblnames.h" +#include "lpoint2_src.h" + + +#endif diff --git a/panda/src/linmath/lpoint2_src.I b/panda/src/linmath/lpoint2_src.I new file mode 100644 index 0000000000..9542ce2e5d --- /dev/null +++ b/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) ©) : FLOATNAME(LVecBase2)(copy) { +} + +//////////////////////////////////////////////////////////////////// +// Function: LPoint2::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE FLOATNAME(LPoint2) &FLOATNAME(LPoint2):: +operator = (const FLOATNAME(LVecBase2) ©) { + 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)); +} diff --git a/panda/src/linmath/lpoint3.cxx b/panda/src/linmath/lpoint3.cxx new file mode 100644 index 0000000000..af010c1fc9 --- /dev/null +++ b/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" + diff --git a/panda/src/linmath/lpoint3.h b/panda/src/linmath/lpoint3.h new file mode 100644 index 0000000000..f3a09c0ced --- /dev/null +++ b/panda/src/linmath/lpoint3.h @@ -0,0 +1,22 @@ +// Filename: lpoint3.h +// Created by: drose (25Sep99) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LPOINT3_H +#define LPOINT3_H + +#include + +#include "coordinateSystem.h" +#include "lvecBase3.h" +#include "lvector3.h" + +#include "fltnames.h" +#include "lpoint3_src.h" + +#include "dblnames.h" +#include "lpoint3_src.h" + + +#endif diff --git a/panda/src/linmath/lpoint3_src.I b/panda/src/linmath/lpoint3_src.I new file mode 100644 index 0000000000..22ae1fbf2f --- /dev/null +++ b/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) ©) : FLOATNAME(LVecBase3)(copy) { +} + +//////////////////////////////////////////////////////////////////// +// Function: LPoint3::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE FLOATNAME(LPoint3) &FLOATNAME(LPoint3):: +operator = (const FLOATNAME(LVecBase3) ©) { + 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); +} diff --git a/panda/src/linmath/lpoint4.cxx b/panda/src/linmath/lpoint4.cxx new file mode 100644 index 0000000000..82289ebda3 --- /dev/null +++ b/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" + diff --git a/panda/src/linmath/lpoint4.h b/panda/src/linmath/lpoint4.h new file mode 100644 index 0000000000..8047f88ef0 --- /dev/null +++ b/panda/src/linmath/lpoint4.h @@ -0,0 +1,20 @@ +// Filename: lpoint4.h +// Created by: drose (08Mar00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LPOINT4_H +#define LPOINT4_H + +#include + +#include "lvecBase4.h" +#include "lvector4.h" + +#include "fltnames.h" +#include "lpoint4_src.h" + +#include "dblnames.h" +#include "lpoint4_src.h" + +#endif diff --git a/panda/src/linmath/lpoint4_src.I b/panda/src/linmath/lpoint4_src.I new file mode 100644 index 0000000000..690a450365 --- /dev/null +++ b/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) ©) : FLOATNAME(LVecBase4)(copy) { +} + +//////////////////////////////////////////////////////////////////// +// Function: LPoint4::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE FLOATNAME(LPoint4) &FLOATNAME(LPoint4):: +operator = (const FLOATNAME(LVecBase4) ©) { + 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)); +} diff --git a/panda/src/linmath/lquaternion.cxx b/panda/src/linmath/lquaternion.cxx new file mode 100644 index 0000000000..ed6d1e0539 --- /dev/null +++ b/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" + diff --git a/panda/src/linmath/lquaternion.h b/panda/src/linmath/lquaternion.h new file mode 100644 index 0000000000..a7a1f5f46d --- /dev/null +++ b/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 + +#include "fltnames.h" +#include "lquaternion_src.h" + +#include "dblnames.h" +#include "lquaternion_src.h" + + +#endif /* __LQUATERNION_H__ */ diff --git a/panda/src/linmath/lquaternion_src.I b/panda/src/linmath/lquaternion_src.I new file mode 100644 index 0000000000..50f73ce2dc --- /dev/null +++ b/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; +} diff --git a/panda/src/linmath/lrotation.cxx b/panda/src/linmath/lrotation.cxx new file mode 100644 index 0000000000..d28aeb7565 --- /dev/null +++ b/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" + diff --git a/panda/src/linmath/lrotation.h b/panda/src/linmath/lrotation.h new file mode 100644 index 0000000000..169c30cf60 --- /dev/null +++ b/panda/src/linmath/lrotation.h @@ -0,0 +1,21 @@ +// Filename: lrotation.h +// Created by: frang, charles (07Jun00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef __LROTATION_H__ +#define __LROTATION_H__ + +#include +#include "lquaternion.h" +#include "cmath.h" + +#include + +#include "fltnames.h" +#include "lrotation_src.h" + +#include "dblnames.h" +#include "lrotation_src.h" + +#endif /* __LROTATION_H__ */ diff --git a/panda/src/linmath/lrotation_src.I b/panda/src/linmath/lrotation_src.I new file mode 100644 index 0000000000..138924bea0 --- /dev/null +++ b/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; +} + + diff --git a/panda/src/linmath/luse.I b/panda/src/linmath/luse.I new file mode 100644 index 0000000000..13fd2a7957 --- /dev/null +++ b/panda/src/linmath/luse.I @@ -0,0 +1,4 @@ +// Filename: luse.I +// Created by: drose (13Jan99) +// +//////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/luse.N b/panda/src/linmath/luse.N new file mode 100644 index 0000000000..f51d30262f --- /dev/null +++ b/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 diff --git a/panda/src/linmath/luse.cxx b/panda/src/linmath/luse.cxx new file mode 100644 index 0000000000..1e7b76a060 --- /dev/null +++ b/panda/src/linmath/luse.cxx @@ -0,0 +1,6 @@ +// Filename: luse.cxx +// Created by: drose (08Mar00) +// +//////////////////////////////////////////////////////////////////// + +#include "luse.h" diff --git a/panda/src/linmath/luse.h b/panda/src/linmath/luse.h new file mode 100644 index 0000000000..de91dc8308 --- /dev/null +++ b/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 + +#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 + diff --git a/panda/src/linmath/lvec2_ops.h b/panda/src/linmath/lvec2_ops.h new file mode 100644 index 0000000000..2bfb82a07f --- /dev/null +++ b/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 +#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 diff --git a/panda/src/linmath/lvec3_ops.h b/panda/src/linmath/lvec3_ops.h new file mode 100644 index 0000000000..ac4e4c3262 --- /dev/null +++ b/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 +#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 diff --git a/panda/src/linmath/lvec4_ops.h b/panda/src/linmath/lvec4_ops.h new file mode 100644 index 0000000000..1e9599f638 --- /dev/null +++ b/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 +#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 diff --git a/panda/src/linmath/lvecBase2.cxx b/panda/src/linmath/lvecBase2.cxx new file mode 100644 index 0000000000..c151f5d6b3 --- /dev/null +++ b/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" + diff --git a/panda/src/linmath/lvecBase2.h b/panda/src/linmath/lvecBase2.h new file mode 100644 index 0000000000..7856d737fe --- /dev/null +++ b/panda/src/linmath/lvecBase2.h @@ -0,0 +1,26 @@ +// Filename: lvecBase2.h +// Created by: drose (08Mar00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LVECBASE2_H +#define LVECBASE2_H + +#include +#include +#include +#include +#include +#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 diff --git a/panda/src/linmath/lvecBase2_src.I b/panda/src/linmath/lvecBase2_src.I new file mode 100644 index 0000000000..d583054210 --- /dev/null +++ b/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) ©) { + (*this) = copy; +} + +//////////////////////////////////////////////////////////////////// +// Function: LVecBase2::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE FLOATNAME(LVecBase2) &FLOATNAME(LVecBase2):: +operator = (const FLOATNAME(LVecBase2) ©) { + 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(); +} + diff --git a/panda/src/linmath/lvecBase3.cxx b/panda/src/linmath/lvecBase3.cxx new file mode 100644 index 0000000000..40f6db34fb --- /dev/null +++ b/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" + diff --git a/panda/src/linmath/lvecBase3.h b/panda/src/linmath/lvecBase3.h new file mode 100644 index 0000000000..1031fbf19a --- /dev/null +++ b/panda/src/linmath/lvecBase3.h @@ -0,0 +1,26 @@ +// Filename: lvecBase3.h +// Created by: drose (08Mar00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LVECBASE3_H +#define LVECBASE3_H + +#include +#include +#include +#include +#include +#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 diff --git a/panda/src/linmath/lvecBase3_src.I b/panda/src/linmath/lvecBase3_src.I new file mode 100644 index 0000000000..a9a9a87db2 --- /dev/null +++ b/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) ©) { + (*this) = copy; +} + +//////////////////////////////////////////////////////////////////// +// Function: LVecBase3::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE FLOATNAME(LVecBase3) &FLOATNAME(LVecBase3):: +operator = (const FLOATNAME(LVecBase3) ©) { + 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(); +} diff --git a/panda/src/linmath/lvecBase4.cxx b/panda/src/linmath/lvecBase4.cxx new file mode 100644 index 0000000000..294b1d09a1 --- /dev/null +++ b/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" + diff --git a/panda/src/linmath/lvecBase4.h b/panda/src/linmath/lvecBase4.h new file mode 100644 index 0000000000..eacee569bf --- /dev/null +++ b/panda/src/linmath/lvecBase4.h @@ -0,0 +1,27 @@ +// Filename: lvecBase4.h +// Created by: drose (08Mar00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LVECBASE4_H +#define LVECBASE4_H + +#include +#include +#include +#include +#include +#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 diff --git a/panda/src/linmath/lvecBase4_src.I b/panda/src/linmath/lvecBase4_src.I new file mode 100644 index 0000000000..2481d56739 --- /dev/null +++ b/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) ©) { + (*this) = copy; +} + +//////////////////////////////////////////////////////////////////// +// Function: LVecBase4::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE FLOATNAME(LVecBase4) &FLOATNAME(LVecBase4):: +operator = (const FLOATNAME(LVecBase4) ©) { + 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(); +} diff --git a/panda/src/linmath/lvector2.cxx b/panda/src/linmath/lvector2.cxx new file mode 100644 index 0000000000..641007ba6e --- /dev/null +++ b/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" + diff --git a/panda/src/linmath/lvector2.h b/panda/src/linmath/lvector2.h new file mode 100644 index 0000000000..b17815b288 --- /dev/null +++ b/panda/src/linmath/lvector2.h @@ -0,0 +1,20 @@ +// Filename: lvector2.h +// Created by: drose (08Mar00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LVECTOR2_H +#define LVECTOR2_H + +#include +#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 diff --git a/panda/src/linmath/lvector2_src.I b/panda/src/linmath/lvector2_src.I new file mode 100644 index 0000000000..844b089b2e --- /dev/null +++ b/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) ©) : FLOATNAME(LVecBase2)(copy) { +} + +//////////////////////////////////////////////////////////////////// +// Function: LVector2::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE FLOATNAME(LVector2) &FLOATNAME(LVector2):: +operator = (const FLOATNAME(LVecBase2) ©) { + 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)); +} diff --git a/panda/src/linmath/lvector3.cxx b/panda/src/linmath/lvector3.cxx new file mode 100644 index 0000000000..9ab4779876 --- /dev/null +++ b/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" + diff --git a/panda/src/linmath/lvector3.h b/panda/src/linmath/lvector3.h new file mode 100644 index 0000000000..c6fe9035ae --- /dev/null +++ b/panda/src/linmath/lvector3.h @@ -0,0 +1,22 @@ +// Filename: lvector3.h +// Created by: drose (24Sep99) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LVECTOR3_H +#define LVECTOR3_H + +#include + +#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 diff --git a/panda/src/linmath/lvector3_src.I b/panda/src/linmath/lvector3_src.I new file mode 100644 index 0000000000..8356d5625e --- /dev/null +++ b/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) ©) : FLOATNAME(LVecBase3)(copy) { +} + +//////////////////////////////////////////////////////////////////// +// Function: LVector3::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE FLOATNAME(LVector3) &FLOATNAME(LVector3):: +operator = (const FLOATNAME(LVecBase3) ©) { + 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; +} diff --git a/panda/src/linmath/lvector4.cxx b/panda/src/linmath/lvector4.cxx new file mode 100644 index 0000000000..c832fa4d69 --- /dev/null +++ b/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" + diff --git a/panda/src/linmath/lvector4.h b/panda/src/linmath/lvector4.h new file mode 100644 index 0000000000..b392e24393 --- /dev/null +++ b/panda/src/linmath/lvector4.h @@ -0,0 +1,20 @@ +// Filename: lvector4.h +// Created by: drose (08Mar00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LVECTOR4_H +#define LVECTOR4_H + +#include +#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 diff --git a/panda/src/linmath/lvector4_src.I b/panda/src/linmath/lvector4_src.I new file mode 100644 index 0000000000..6e2f92020b --- /dev/null +++ b/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) ©) : FLOATNAME(LVecBase4)(copy) { +} + +//////////////////////////////////////////////////////////////////// +// Function: LVector4::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE FLOATNAME(LVector4) &FLOATNAME(LVector4):: +operator = (const FLOATNAME(LVecBase4) ©) { + 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)); +} diff --git a/panda/src/linmath/mathNumbers.cxx b/panda/src/linmath/mathNumbers.cxx new file mode 100644 index 0000000000..1788a6e080 --- /dev/null +++ b/panda/src/linmath/mathNumbers.cxx @@ -0,0 +1,10 @@ +// Filename: mathNumbers.cxx +// Created by: mike (24Sep99) +// +//////////////////////////////////////////////////////////////////// + +#include "mathNumbers.h" +#include + +const double MathNumbers::pi = 4.0 * atan(1); +const double MathNumbers::ln2 = log(2); diff --git a/panda/src/linmath/mathNumbers.h b/panda/src/linmath/mathNumbers.h new file mode 100644 index 0000000000..c71eaf11f5 --- /dev/null +++ b/panda/src/linmath/mathNumbers.h @@ -0,0 +1,17 @@ +// Filename: mathNumbers.h +// Created by: mike (23Jan99) +// +//////////////////////////////////////////////////////////////////// +// +#ifndef MATHNUMBERS_H +#define MATHNUMBERS_H + +#include + +class EXPCL_PANDA MathNumbers { +PUBLISHED: + static const double pi; + static const double ln2; +}; + +#endif diff --git a/panda/src/linmath/nearly_zero.h b/panda/src/linmath/nearly_zero.h new file mode 100644 index 0000000000..5e1472e4bc --- /dev/null +++ b/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 + diff --git a/panda/src/linmath/pta_Colorf.cxx b/panda/src/linmath/pta_Colorf.cxx new file mode 100644 index 0000000000..fe648db736 --- /dev/null +++ b/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 diff --git a/panda/src/linmath/pta_Colorf.h b/panda/src/linmath/pta_Colorf.h new file mode 100644 index 0000000000..e7f4f0a28b --- /dev/null +++ b/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 + +#include "vector_Colorf.h" + +#include + +//////////////////////////////////////////////////////////////////// +// 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); +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToBase >); +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToArray) +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, ConstPointerToArray) + +typedef PointerToArray PTA_Colorf; +typedef ConstPointerToArray CPTA_Colorf; + +// Tell GCC that we'll take care of the instantiation explicitly here. +#ifdef __GNUC__ +#pragma interface +#endif + +#endif diff --git a/panda/src/linmath/pta_Normalf.cxx b/panda/src/linmath/pta_Normalf.cxx new file mode 100644 index 0000000000..596e3595a8 --- /dev/null +++ b/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 diff --git a/panda/src/linmath/pta_Normalf.h b/panda/src/linmath/pta_Normalf.h new file mode 100644 index 0000000000..12df8d4eae --- /dev/null +++ b/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 + +#include "vector_Normalf.h" + +#include + +//////////////////////////////////////////////////////////////////// +// 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); +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToBase >); +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToArray) +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, ConstPointerToArray) + +typedef PointerToArray PTA_Normalf; +typedef ConstPointerToArray CPTA_Normalf; + +// Tell GCC that we'll take care of the instantiation explicitly here. +#ifdef __GNUC__ +#pragma interface +#endif + +#endif diff --git a/panda/src/linmath/pta_TexCoordf.cxx b/panda/src/linmath/pta_TexCoordf.cxx new file mode 100644 index 0000000000..149e36b800 --- /dev/null +++ b/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 diff --git a/panda/src/linmath/pta_TexCoordf.h b/panda/src/linmath/pta_TexCoordf.h new file mode 100644 index 0000000000..ae321bac5b --- /dev/null +++ b/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 + +#include "vector_TexCoordf.h" + +#include + +//////////////////////////////////////////////////////////////////// +// 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); +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToBase >); +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToArray) +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, ConstPointerToArray) + +typedef PointerToArray PTA_TexCoordf; +typedef ConstPointerToArray CPTA_TexCoordf; + +// Tell GCC that we'll take care of the instantiation explicitly here. +#ifdef __GNUC__ +#pragma interface +#endif + +#endif diff --git a/panda/src/linmath/pta_Vertexf.cxx b/panda/src/linmath/pta_Vertexf.cxx new file mode 100644 index 0000000000..1c145bc5b0 --- /dev/null +++ b/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 diff --git a/panda/src/linmath/pta_Vertexf.h b/panda/src/linmath/pta_Vertexf.h new file mode 100644 index 0000000000..7f3eed9c9b --- /dev/null +++ b/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 + +#include "vector_Vertexf.h" + +#include + +//////////////////////////////////////////////////////////////////// +// 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); +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToBase >); +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToArray); +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, ConstPointerToArray); + +typedef PointerToArray PTA_Vertexf; +typedef ConstPointerToArray CPTA_Vertexf; + +// Tell GCC that we'll take care of the instantiation explicitly here. +#ifdef __GNUC__ +#pragma interface +#endif + +#endif diff --git a/panda/src/linmath/test_math.cxx b/panda/src/linmath/test_math.cxx new file mode 100644 index 0000000000..2fd7c4aa83 --- /dev/null +++ b/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 +#include + +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); +} + diff --git a/panda/src/linmath/vector_Colorf.cxx b/panda/src/linmath/vector_Colorf.cxx new file mode 100644 index 0000000000..b5eb7311c5 --- /dev/null +++ b/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 diff --git a/panda/src/linmath/vector_Colorf.h b/panda/src/linmath/vector_Colorf.h new file mode 100644 index 0000000000..753483c87b --- /dev/null +++ b/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 + +#include "luse.h" + +#include + +//////////////////////////////////////////////////////////////////// +// 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) +typedef vector vector_Colorf; + +// Tell GCC that we'll take care of the instantiation explicitly here. +#ifdef __GNUC__ +#pragma interface +#endif + +#endif diff --git a/panda/src/linmath/vector_LPoint2f.cxx b/panda/src/linmath/vector_LPoint2f.cxx new file mode 100644 index 0000000000..cbf77ba3c6 --- /dev/null +++ b/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 diff --git a/panda/src/linmath/vector_LPoint2f.h b/panda/src/linmath/vector_LPoint2f.h new file mode 100644 index 0000000000..2be164f9c9 --- /dev/null +++ b/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 + +#include "luse.h" + +#include + +//////////////////////////////////////////////////////////////////// +// 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) +typedef vector vector_LPoint2f; + +// Tell GCC that we'll take care of the instantiation explicitly here. +#ifdef __GNUC__ +#pragma interface +#endif + +#endif diff --git a/panda/src/linmath/vector_LVecBase3f.cxx b/panda/src/linmath/vector_LVecBase3f.cxx new file mode 100644 index 0000000000..7827bb89f9 --- /dev/null +++ b/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 diff --git a/panda/src/linmath/vector_LVecBase3f.h b/panda/src/linmath/vector_LVecBase3f.h new file mode 100644 index 0000000000..5d152529f7 --- /dev/null +++ b/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 + +#include "luse.h" + +#include + +//////////////////////////////////////////////////////////////////// +// 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) +typedef vector vector_LVecBase3f; + +// Tell GCC that we'll take care of the instantiation explicitly here. +#ifdef __GNUC__ +#pragma interface +#endif + +#endif diff --git a/panda/src/linmath/vector_Normalf.cxx b/panda/src/linmath/vector_Normalf.cxx new file mode 100644 index 0000000000..1e9805076e --- /dev/null +++ b/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 diff --git a/panda/src/linmath/vector_Normalf.h b/panda/src/linmath/vector_Normalf.h new file mode 100644 index 0000000000..22c1577615 --- /dev/null +++ b/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 + +#include "luse.h" + +#include + +//////////////////////////////////////////////////////////////////// +// 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) +typedef vector vector_Normalf; + +// Tell GCC that we'll take care of the instantiation explicitly here. +#ifdef __GNUC__ +#pragma interface +#endif + +#endif diff --git a/panda/src/linmath/vector_TexCoordf.h b/panda/src/linmath/vector_TexCoordf.h new file mode 100644 index 0000000000..f3153b1d7e --- /dev/null +++ b/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 + +#include "vector_LPoint2f.h" + +//////////////////////////////////////////////////////////////////// +// Class : vector_TexCoordf +// Description : This is just another name for vector_LPoint2f. +//////////////////////////////////////////////////////////////////// + +typedef vector_LPoint2f vector_TexCoordf; + +#endif diff --git a/panda/src/linmath/vector_Vertexf.cxx b/panda/src/linmath/vector_Vertexf.cxx new file mode 100644 index 0000000000..40d732c49f --- /dev/null +++ b/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 diff --git a/panda/src/linmath/vector_Vertexf.h b/panda/src/linmath/vector_Vertexf.h new file mode 100644 index 0000000000..a043f6c30e --- /dev/null +++ b/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 + +#include "luse.h" + +#include + +//////////////////////////////////////////////////////////////////// +// 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) +typedef vector vector_Vertexf; + +// Tell GCC that we'll take care of the instantiation explicitly here. +#ifdef __GNUC__ +#pragma interface +#endif + +#endif diff --git a/panda/src/mathutil/Sources.pp b/panda/src/mathutil/Sources.pp new file mode 100644 index 0000000000..c81bf8dc63 --- /dev/null +++ b/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 + diff --git a/panda/src/mathutil/boundingHexahedron.I b/panda/src/mathutil/boundingHexahedron.I new file mode 100644 index 0000000000..6a2069bfac --- /dev/null +++ b/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]; +} diff --git a/panda/src/mathutil/boundingHexahedron.cxx b/panda/src/mathutil/boundingHexahedron.cxx new file mode 100644 index 0000000000..84206f1aea --- /dev/null +++ b/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 +#include + +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 ¢er = 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; +} diff --git a/panda/src/mathutil/boundingHexahedron.h b/panda/src/mathutil/boundingHexahedron.h new file mode 100644 index 0000000000..88a695337f --- /dev/null +++ b/panda/src/mathutil/boundingHexahedron.h @@ -0,0 +1,109 @@ +// Filename: boundingHexahedron.h +// Created by: drose (03Oct99) +// +//////////////////////////////////////////////////////////////////// + +#ifndef BOUNDINGHEXAHEDRON_H +#define BOUNDINGHEXAHEDRON_H + +#include + +#include "finiteBoundingVolume.h" +#include "frustum.h" +#include "plane.h" + +#include + + +/////////////////////////////////////////////////////////////////// +// 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 diff --git a/panda/src/mathutil/boundingLine.I b/panda/src/mathutil/boundingLine.I new file mode 100644 index 0000000000..9ef228ecc9 --- /dev/null +++ b/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; +} diff --git a/panda/src/mathutil/boundingLine.cxx b/panda/src/mathutil/boundingLine.cxx new file mode 100644 index 0000000000..ec60fe013b --- /dev/null +++ b/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 + +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; +} diff --git a/panda/src/mathutil/boundingLine.h b/panda/src/mathutil/boundingLine.h new file mode 100644 index 0000000000..46d409e3e5 --- /dev/null +++ b/panda/src/mathutil/boundingLine.h @@ -0,0 +1,81 @@ +// Filename: boundingLine.h +// Created by: drose (04Jul00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef BOUNDINGLINE_H +#define BOUNDINGLINE_H + +#include + +#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 diff --git a/panda/src/mathutil/boundingSphere.I b/panda/src/mathutil/boundingSphere.I new file mode 100644 index 0000000000..40a20580b5 --- /dev/null +++ b/panda/src/mathutil/boundingSphere.I @@ -0,0 +1,33 @@ +// Filename: boundingSphere.I +// Created by: drose (02Oct99) +// +//////////////////////////////////////////////////////////////////// + +INLINE BoundingSphere:: +BoundingSphere() { +} + +INLINE BoundingSphere:: +BoundingSphere(const LPoint3f ¢er, float radius) : + _center(center), _radius(radius) +{ + _flags = 0; + nassertd(!_center.is_nan() && !cnan(_radius)) { + _flags = F_empty; + } +} + +INLINE const LPoint3f &BoundingSphere:: +get_center() const { + nassertr(!is_empty(), _center); + nassertr(!is_infinite(), _center); + return _center; +} + +INLINE float BoundingSphere:: +get_radius() const { + nassertr(!is_empty(), 0.0); + nassertr(!is_infinite(), 0.0); + return _radius; +} + diff --git a/panda/src/mathutil/boundingSphere.cxx b/panda/src/mathutil/boundingSphere.cxx new file mode 100644 index 0000000000..7089cf57de --- /dev/null +++ b/panda/src/mathutil/boundingSphere.cxx @@ -0,0 +1,455 @@ +// Filename: boundingSphere.cxx +// Created by: drose (01Oct99) +// +//////////////////////////////////////////////////////////////////// + +#include "boundingSphere.h" +#include "boundingHexahedron.h" +#include "boundingLine.h" +#include "config_mathutil.h" + +#include +#include + +TypeHandle BoundingSphere::_type_handle; + +BoundingVolume *BoundingSphere:: +make_copy() const { + return new BoundingSphere(*this); +} + +LPoint3f BoundingSphere:: +get_min() const { + nassertr(!is_empty(), LPoint3f(0.0, 0.0, 0.0)); + nassertr(!is_infinite(), LPoint3f(0.0, 0.0, 0.0)); + return LPoint3f(_center[0] - _radius, + _center[1] - _radius, + _center[2] - _radius); +} + +LPoint3f BoundingSphere:: +get_max() const { + nassertr(!is_empty(), LPoint3f(0.0, 0.0, 0.0)); + nassertr(!is_infinite(), LPoint3f(0.0, 0.0, 0.0)); + return LPoint3f(_center[0] + _radius, + _center[1] + _radius, + _center[2] + _radius); +} + +LPoint3f BoundingSphere:: +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_center(); +} + +void BoundingSphere:: +xform(const LMatrix4f &mat) { + nassertv(!mat.is_nan()); + + if (!is_empty() && !is_infinite()) { + // First, determine the longest axis of the matrix, in case it + // contains a non-proportionate scale. + LVector3f x = mat.get_row3(0); + LVector3f y = mat.get_row3(1); + LVector3f z = mat.get_row3(2); + float xd = dot(x, x); + float yd = dot(y, y); + float zd = dot(z, z); + + float scale; + if (xd < yd) { + if (yd < zd) { + scale = sqrtf(zd); + } else { + scale = sqrtf(yd); + } + } else { + if (xd < zd) { + scale = sqrtf(zd); + } else { + scale = sqrtf(xd); + } + } + + // Transform the center + _center = _center * mat; + + // And the radius. + _radius *= scale; + } +} + +void BoundingSphere:: +output(ostream &out) const { + if (is_empty()) { + out << "bsphere, empty"; + } else if (is_infinite()) { + out << "bsphere, infinite"; + } else { + out << "bsphere, c (" << _center << "), r " << _radius; + } +} + +bool BoundingSphere:: +extend_other(BoundingVolume *other) const { + return other->extend_by_sphere(this); +} + +bool BoundingSphere:: +around_other(BoundingVolume *other, + const BoundingVolume **first, + const BoundingVolume **last) const { + return other->around_spheres(first, last); +} + +int BoundingSphere:: +contains_other(const BoundingVolume *other) const { + return other->contains_sphere(this); +} + + +bool BoundingSphere:: +extend_by_point(const LPoint3f &point) { + nassertr(!point.is_nan(), false); + + if (is_empty()) { + _center = point; + _radius = 0.0; + _flags = 0; + } else if (!is_infinite()) { + LVector3f v = point - _center; + float dist2 = dot(v, v); + if (dist2 > _radius * _radius) { + _radius = sqrtf(dist2); + } + } + return true; +} + +bool BoundingSphere:: +extend_by_sphere(const BoundingSphere *sphere) { + nassertr(!sphere->is_empty() && !sphere->is_infinite(), false); + nassertr(!is_infinite(), false); + + if (is_empty()) { + _center = sphere->_center; + _radius = sphere->_radius; + _flags = 0; + } else { + float dist = length(sphere->_center - _center); + + _radius = max(_radius, dist + sphere->_radius); + } + return true; +} + +bool BoundingSphere:: +extend_by_hexahedron(const BoundingHexahedron *hexahedron) { + return extend_by_finite(hexahedron); +} + +bool BoundingSphere:: +extend_by_finite(const FiniteBoundingVolume *volume) { + nassertr(!volume->is_empty(), false); + + LVector3f min1 = volume->get_min(); + LVector3f max1 = volume->get_max(); + + if (is_empty()) { + _center = (min1 + max1) * 0.5; + _radius = length(LVector3f(max1 - _center)); + _flags = 0; + } else { + LVector3f v = max1 - _center; + float dist2 = dot(v, v); + + if (dist2 > _radius * _radius) { + _radius = sqrtf(dist2); + } + } + + return true; +} + +bool BoundingSphere:: +around_points(const LPoint3f *first, const LPoint3f *last) { + nassertr(first != last, false); + + // First, get the minmax of all the points to construct a bounding + // box. + const LPoint3f *p = first; + +#ifndef NDEBUG + // Skip any NaN points. + int skipped_nan = 0; + while (p != last && (*p).is_nan()) { + ++p; + ++skipped_nan; + } + if (p == last) { + mathutil_cat.warning() + << "BoundingSphere around NaN\n"; + return false; + } +#endif + + LPoint3f min_box = *p; + LPoint3f max_box = *p; + ++p; + +#ifndef NDEBUG + // Skip more NaN points. + while (p != last && (*p).is_nan()) { + ++p; + ++skipped_nan; + } +#endif + + if (p == last) { + // Only one point; we have a radius of zero. This is not the same + // thing as an empty sphere, because our volume contains one + // point; an empty sphere contains no points. + _center = min_box; + _radius = 0.0; + + } else { + // More than one point; we have a nonzero radius. + while (p != last) { +#ifndef NDEBUG + // Skip more NaN points. + if ((*p).is_nan()) { + ++skipped_nan; + } else +#endif + { + min_box.set(min(min_box[0], (*p)[0]), + min(min_box[1], (*p)[1]), + min(min_box[2], (*p)[2])); + max_box.set(max(max_box[0], (*p)[0]), + max(max_box[1], (*p)[1]), + max(max_box[2], (*p)[2])); + } + ++p; + } + + // Now take the center of the bounding box as the center of the sphere. + _center = (min_box + max_box) / 2.0; + + // Now walk back through to get the max distance from center. + float max_dist2 = 0.0; + for (p = first; p != last; ++p) { + LVector3f v = (*p) - _center; + float dist2 = dot(v, v); + max_dist2 = max(max_dist2, dist2); + } + + _radius = sqrtf(max_dist2); + } + +#ifndef NDEBUG + if (skipped_nan != 0) { + mathutil_cat.warning() + << "BoundingSphere ignored " << skipped_nan << " NaN points of " + << (last - first) << " total.\n"; + } +#endif + + _flags = 0; + + return true; +} + +bool BoundingSphere:: +around_spheres(const BoundingVolume **first, + const BoundingVolume **last) { + return around_finite(first, last); +} + +bool BoundingSphere:: +around_hexahedrons(const BoundingVolume **first, + const BoundingVolume **last) { + return around_finite(first, last); +} + +bool BoundingSphere:: +around_finite(const BoundingVolume **first, + const BoundingVolume **last) { + nassertr(first != last, false); + + // We're given a set of bounding volumes, at least the first one of + // which is guaranteed to be finite and nonempty. Some others may + // not be. + + // First, get the minmax of all the points to construct a bounding + // box. + const BoundingVolume **p = first; + nassertr(!(*p)->is_empty() && !(*p)->is_infinite(), false); + nassertr((*p)->is_of_type(FiniteBoundingVolume::get_class_type()), false); + const FiniteBoundingVolume *vol = DCAST(FiniteBoundingVolume, *p); + LPoint3f min_box = vol->get_min(); + LPoint3f max_box = vol->get_max(); + + bool any_unknown = false; + + for (++p; p != last; ++p) { + nassertr(!(*p)->is_infinite(), false); + if (!(*p)->is_empty() && + (*p)->is_of_type(FiniteBoundingVolume::get_class_type())) { + const FiniteBoundingVolume *vol = DCAST(FiniteBoundingVolume, *p); + LPoint3f min1 = vol->get_min(); + LPoint3f max1 = vol->get_max(); + min_box.set(min(min_box[0], min1[0]), + min(min_box[1], min1[1]), + min(min_box[2], min1[2])); + max_box.set(max(max_box[0], max1[0]), + max(max_box[1], max1[1]), + max(max_box[2], max1[2])); + + if (!(*p)->is_of_type(BoundingSphere::get_class_type())) { + any_unknown = true; + } + } + } + + // Now take the center of the bounding box as the center of the sphere. + _center = (min_box + max_box) * 0.5; + + if (any_unknown) { + // If we have any volumes in the list that we don't know what to + // do with, we'll have to make the bounding sphere large enough to + // enclose the bounding box. Less than ideal, but too bad. + _radius = length(max_box - _center); + + } else { + // Otherwise, we do understand all the volumes in the list; make + // the sphere as tight as we can. + _radius = 0.0; + for (p = first; p != last; ++p) { + if (!(*p)->is_empty()) { + if ((*p)->is_of_type(BoundingSphere::get_class_type())) { + const BoundingSphere *sphere = DCAST(BoundingSphere, *p); + float dist = length(sphere->_center - _center); + _radius = max(_radius, dist + sphere->_radius); + } else { + // Shouldn't get here, unless we missed a type from above. + mathutil_cat.error() + << "Unexpected type in BoundingSphere::around_finite()\n"; + nassertr(false, false); + } + } + } + } + + _flags = 0; + return true; +} + +int BoundingSphere:: +contains_point(const LPoint3f &point) const { + nassertr(!point.is_nan(), IF_no_intersection); + + if (is_empty()) { + return IF_no_intersection; + + } else if (is_infinite()) { + return IF_possible | IF_some | IF_all; + + } else { + LVector3f v = point - _center; + float dist2 = dot(v, v); + return (dist2 <= _radius * _radius) ? + IF_possible | IF_some | IF_all : IF_no_intersection; + } +} + +int BoundingSphere:: +contains_lineseg(const LPoint3f &a, const LPoint3f &b) const { + nassertr(!a.is_nan() && !b.is_nan(), IF_no_intersection); + + if (a == b) { + return contains_point(a); + } + if (is_empty()) { + return IF_no_intersection; + + } else if (is_infinite()) { + return IF_possible | IF_some | IF_all; + + } else { + LPoint3f from = a; + LVector3f delta = b - a; + float t1, t2; + + // Solve the equation for the intersection of a line with a sphere + // using the quadratic equation. + float A = dot(delta, delta); + + nassertr(A != 0.0, 0); // Trivial line segment. + + LVector3f fc = from - _center; + float B = 2.0 * dot(delta, fc); + float C = dot(fc, fc) - _radius * _radius; + + float radical = B*B - 4.0*A*C; + + if (IS_NEARLY_ZERO(radical)) { + // Tangent. + t1 = t2 = -B / (2.0*A); + return (t1 >= 0.0 && t1 <= 1.0) ? + IF_possible | IF_some : IF_no_intersection; + } + + if (radical < 0.0) { + // No real roots: no intersection with the line. + return IF_no_intersection; + } + + float reciprocal_2A = 1.0f/(2.0*A); + float sqrt_radical = sqrtf(radical); + + t1 = ( -B - sqrt_radical ) * reciprocal_2A; + t2 = ( -B + sqrt_radical ) * reciprocal_2A; + + if (t1 >= 0.0 && t2 <= 1.0) { + return IF_possible | IF_some | IF_all; + } else if (t1 <= 1.0 && t2 >= 0.0) { + return IF_possible | IF_some; + } else { + return IF_no_intersection; + } + } +} + +int BoundingSphere:: +contains_sphere(const BoundingSphere *sphere) const { + nassertr(!is_empty() && !is_infinite(), 0); + nassertr(!sphere->is_empty() && !sphere->is_infinite(), 0); + + LVector3f v = sphere->_center - _center; + float dist2 = dot(v, v); + + if (_radius >= sphere->_radius && + dist2 <= (_radius - sphere->_radius) * (_radius - sphere->_radius)) { + // The other sphere is completely within this sphere. + return IF_possible | IF_some | IF_all; + + } else if (dist2 > (_radius + sphere->_radius) * (_radius + sphere->_radius)) { + // The other sphere is completely outside this sphere. + return IF_no_intersection; + + } else { + // The other sphere is partially within this sphere. + return IF_possible | IF_some; + } +} + +int BoundingSphere:: +contains_hexahedron(const BoundingHexahedron *hexahedron) const { + return hexahedron->contains_sphere(this) & ~IF_all; +} + +int BoundingSphere:: +contains_line(const BoundingLine *line) const { + return line->contains_sphere(this) & ~IF_all; +} diff --git a/panda/src/mathutil/boundingSphere.h b/panda/src/mathutil/boundingSphere.h new file mode 100644 index 0000000000..b9fe6be1b3 --- /dev/null +++ b/panda/src/mathutil/boundingSphere.h @@ -0,0 +1,94 @@ +// Filename: boundingSphere.h +// Created by: drose (01Oct99) +// +//////////////////////////////////////////////////////////////////// + +#ifndef BOUNDINGSPHERE_H +#define BOUNDINGSPHERE_H + +#include + +#include "finiteBoundingVolume.h" + +/////////////////////////////////////////////////////////////////// +// Class : BoundingSphere +// Description : This defines a bounding sphere, consisting of a +// center and a radius. It is always a sphere, and +// never an ellipsoid or other quadric. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA BoundingSphere : public FiniteBoundingVolume { +PUBLISHED: + INLINE BoundingSphere(); + INLINE BoundingSphere(const LPoint3f ¢er, float radius); + +public: + 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; + +PUBLISHED: + INLINE const LPoint3f &get_center() const; + INLINE float get_radius() 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); + bool extend_by_finite(const FiniteBoundingVolume *volume); + + 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); + bool around_finite(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_hexahedron(const BoundingHexahedron *hexahedron) const; + virtual int contains_sphere(const BoundingSphere *sphere) const; + virtual int contains_line(const BoundingLine *line) const; + +private: + LPoint3f _center; + float _radius; + + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + FiniteBoundingVolume::init_type(); + register_type(_type_handle, "BoundingSphere", + 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 BoundingHexahedron; +}; + +#include "boundingSphere.I" + +#endif diff --git a/panda/src/mathutil/boundingVolume.I b/panda/src/mathutil/boundingVolume.I new file mode 100644 index 0000000000..9f6a497184 --- /dev/null +++ b/panda/src/mathutil/boundingVolume.I @@ -0,0 +1,112 @@ +// Filename: boundingVolume.I +// Created by: drose (01Oct99) +// +//////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE BoundingVolume:: +BoundingVolume() { + _flags = F_empty; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::is_empty +// Access: Public +// Description: Any kind of volume might be empty. This is a +// degenerate volume that contains no points; it's not +// the same as, for instance, a sphere with radius zero, +// since that contains one point (the center). It +// intersects with no other volumes. +//////////////////////////////////////////////////////////////////// +INLINE bool BoundingVolume:: +is_empty() const { + return (_flags & F_empty) != 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::is_infinite +// Access: Public +// Description: The other side of the empty coin is an infinite +// volume. This is a degenerate state of a normally +// finite volume that contains all points. (Note that +// some kinds of infinite bounding volumes, like binary +// separating planes, do not contain all points and thus +// correctly return is_infinite() == false, even though +// they are technically infinite. This is a special +// case of the word 'infinite' meaning the volume covers +// all points in space.) +// +// It completely intersects with all other volumes +// except empty volumes. +//////////////////////////////////////////////////////////////////// +INLINE bool BoundingVolume:: +is_infinite() const { + return (_flags & F_infinite) != 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::set_infinite +// Access: Public +// Description: Marks the volume as infinite, even if it is normally +// finite. You can think of this as an infinite +// extend_by() operation. +//////////////////////////////////////////////////////////////////// +INLINE void BoundingVolume:: +set_infinite() { + _flags = F_infinite; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::extend_by +// Access: Public +// Description: Increases the size of the volume to include the given +// volume. +//////////////////////////////////////////////////////////////////// +INLINE bool BoundingVolume:: +extend_by(const BoundingVolume *vol) { + if (vol->is_infinite()) { + set_infinite(); + + } else if (!vol->is_empty()) { + // This is a double-dispatch. We call this virtual function on the + // volume we were given, which will in turn call the appropriate + // virtual function in our own class to perform the operation. + return vol->extend_other(this); + } + return true; +} + + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::contains +// Access: Public +// Description: Returns the appropriate set of IntersectionFlags to +// indicate the amount of intersection with the +// indicated volume. +//////////////////////////////////////////////////////////////////// +INLINE int BoundingVolume:: +contains(const BoundingVolume *vol) const { + if (is_empty() || vol->is_empty()) { + return IF_no_intersection; + + } else if (is_infinite()) { + return IF_possible | IF_some | IF_all; + + } else if (vol->is_infinite()) { + return IF_possible | IF_some; + } + + // This is a double-dispatch. We call this virtual function on the + // volume we were given, which will in turn call the appropriate + // virtual function in our own class to perform the operation. + return vol->contains_other(this); +} + +INLINE ostream &operator << (ostream &out, const BoundingVolume &bound) { + bound.output(out); + return out; +} diff --git a/panda/src/mathutil/boundingVolume.cxx b/panda/src/mathutil/boundingVolume.cxx new file mode 100644 index 0000000000..a32f14acda --- /dev/null +++ b/panda/src/mathutil/boundingVolume.cxx @@ -0,0 +1,191 @@ +// Filename: boundingVolume.cxx +// Created by: drose (01Oct99) +// +//////////////////////////////////////////////////////////////////// + +#include "boundingVolume.h" +#include "finiteBoundingVolume.h" + +#include + +TypeHandle BoundingVolume::_type_handle; + + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::around +// Access: Public +// Description: Resets the volume to enclose only the volumes +// indicated. Returns true if successful, false if the +// volume doesn't know how to do that or can't do that. +//////////////////////////////////////////////////////////////////// +bool BoundingVolume:: +around(const BoundingVolume **first, const BoundingVolume **last) { + _flags = F_empty; + + // Skip any empty volumes at the beginning of the list. We want to + // get to the first real volume. + while (first != last && (*first)->is_empty()) { + if ((*first)->is_infinite()) { + // If we go around an infinite volume, we're infinite too. + _flags = F_infinite; + return true; + } + ++first; + } + + bool okflag = true; + + if (first != last) { + // Check for more infinite bounding volumes in the list. + const BoundingVolume **bvi; + for (bvi = first; bvi != last; ++bvi) { + if ((*bvi)->is_infinite()) { + _flags = F_infinite; + return true; + } + } + + // This is a double-dispatch. We call this virtual function on + // the volume we were given, which will in turn call the + // appropriate virtual function in our own class to perform the + // operation. + if (!(*first)->around_other(this, first, last)) { + okflag = false; + } + } + + return okflag; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::write +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void BoundingVolume:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) << *this << "\n"; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::extend_by_sphere +// Access: Protected, Virtual +// Description: Double-dispatch support: called by extend_other() +// when the type we're extending by is known to be a +// sphere. +//////////////////////////////////////////////////////////////////// +bool BoundingVolume:: +extend_by_sphere(const BoundingSphere *) { + _flags = F_infinite; + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::extend_by_hexahedron +// Access: Protected, Virtual +// Description: Double-dispatch support: called by extend_other() +// when the type we're extending by is known to be a +// hexahedron. +//////////////////////////////////////////////////////////////////// +bool BoundingVolume:: +extend_by_hexahedron(const BoundingHexahedron *) { + _flags = F_infinite; + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::extend_by_line +// Access: Protected, Virtual +// Description: Double-dispatch support: called by extend_other() +// when the type we're extending by is known to be a +// line. +//////////////////////////////////////////////////////////////////// +bool BoundingVolume:: +extend_by_line(const BoundingLine *) { + _flags = F_infinite; + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::around_spheres +// Access: Protected, Virtual +// Description: Double-dispatch support: called by around_other() +// when the type of the first element in the list is +// known to be a nonempty sphere. +//////////////////////////////////////////////////////////////////// +bool BoundingVolume:: +around_spheres(const BoundingVolume **, const BoundingVolume **) { + _flags = F_infinite; + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::around_hexahedrons +// Access: Protected, Virtual +// Description: Double-dispatch support: called by around_other() +// when the type of the first element in the list is +// known to be a nonempty hexahedron. +//////////////////////////////////////////////////////////////////// +bool BoundingVolume:: +around_hexahedrons(const BoundingVolume **, const BoundingVolume **) { + _flags = F_infinite; + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::around_lines +// Access: Protected, Virtual +// Description: Double-dispatch support: called by around_other() +// when the type of the first element in the list is +// known to be a nonempty line. +//////////////////////////////////////////////////////////////////// +bool BoundingVolume:: +around_lines(const BoundingVolume **, const BoundingVolume **) { + _flags = F_infinite; + if (is_of_type(FiniteBoundingVolume::get_class_type())) { + // If it's a FiniteBoundingVolume, we can't do any better than + // making it infinite. So we return true. + return true; + } + + // Otherwise, we might do better, and we require each class to + // define a function. If we get here, the function isn't defined, + // so we return false to indicate this. + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::contains_sphere +// Access: Protected, Virtual +// Description: Double-dispatch support: called by contains_other() +// when the type we're testing for intersection is known +// to be a sphere. +//////////////////////////////////////////////////////////////////// +int BoundingVolume:: +contains_sphere(const BoundingSphere *) const { + return IF_dont_understand; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::contains_hexahedron +// Access: Protected, Virtual +// Description: Double-dispatch support: called by contains_other() +// when the type we're testing for intersection is known +// to be a hexahedron. +//////////////////////////////////////////////////////////////////// +int BoundingVolume:: +contains_hexahedron(const BoundingHexahedron *) const { + return IF_dont_understand; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::contains_line +// Access: Protected, Virtual +// Description: Double-dispatch support: called by contains_other() +// when the type we're testing for intersection is known +// to be a line. +//////////////////////////////////////////////////////////////////// +int BoundingVolume:: +contains_line(const BoundingLine *) const { + return IF_dont_understand; +} diff --git a/panda/src/mathutil/boundingVolume.h b/panda/src/mathutil/boundingVolume.h new file mode 100644 index 0000000000..8291ac6d37 --- /dev/null +++ b/panda/src/mathutil/boundingVolume.h @@ -0,0 +1,147 @@ +// Filename: boundingVolume.h +// Created by: drose (01Oct99) +// +//////////////////////////////////////////////////////////////////// + +#ifndef BOUNDINGVOLUME_H +#define BOUNDINGVOLUME_H + +#include + +#include +#include + +class BoundingSphere; +class BoundingHexahedron; +class BoundingLine; + + +/////////////////////////////////////////////////////////////////// +// Class : BoundingVolume +// Description : This is an abstract class for any volume in any sense +// which can be said to define the locality of reference +// of a node in a graph, along with all of its +// descendants. It is not necessarily a geometric +// volume (although see GeometricBoundingVolume); this +// is simply an abstract interface for bounds of any +// sort. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA BoundingVolume : public TypedReferenceCount { +PUBLISHED: + INLINE BoundingVolume(); + virtual BoundingVolume *make_copy() const=0; + + INLINE bool is_empty() const; + INLINE bool is_infinite() const; + + INLINE void set_infinite(); + + INLINE bool extend_by(const BoundingVolume *vol); + + // It might be nice to make these template member functions so we + // could have true STL-style first/last iterators, but that's + // impossible for virtual functions. + bool around(const BoundingVolume **first, + const BoundingVolume **last); + + // The contains() functions return the union of one or more of these + // bits. + enum IntersectionFlags { + // If no bits are set, it is known that there is no intersection. + IF_no_intersection = 0, + + // IF_possible is set if there might be an intersection. + IF_possible = 0x01, + + // IF_some is set if there is definitely an intersection. In this + // case, IF_possible will also be set. + IF_some = 0x02, + + // IF_all is set if the other bounding volume is known to be + // completely within this bounding volume: that is, there is no + // part of the other bounding volume that does not intersect this + // one. It does *not* indicate the inverse; it is possible that + // some part of this bounding volume does not intersect the other. + + // Also, the converse is not implied: if IF_all is not set, you + // simply don't know whether the other volume is completely + // contained within this one or not. + + // When IF_all is set, both IF_possible and IF_some will also be + // set. + IF_all = 0x04, + + // IF_dont_understand is set if the particular volume/volume + // intersection test has not been implemented. + IF_dont_understand = 0x08 + }; + + INLINE int contains(const BoundingVolume *vol) const; + + virtual void output(ostream &out) const=0; + virtual void write(ostream &out, int indent_level = 0) const; + +protected: + enum Flags { + F_empty = 0x01, + F_infinite = 0x02 + }; + int _flags; + +protected: + // The following functions support double-dispatch of virtual + // methods, so we can easily extend_by() various types of bounding + // volumes. + + // These functions are the first dispatch point. + virtual bool extend_other(BoundingVolume *other) const=0; + virtual bool around_other(BoundingVolume *other, + const BoundingVolume **first, + const BoundingVolume **last) const=0; + virtual int contains_other(const BoundingVolume *other) const=0; + + // These functions are the second dispatch point. They actually do + // the work. + virtual bool extend_by_sphere(const BoundingSphere *sphere); + virtual bool extend_by_hexahedron(const BoundingHexahedron *hexahedron); + virtual bool extend_by_line(const BoundingLine *line); + + virtual bool around_spheres(const BoundingVolume **first, + const BoundingVolume **last); + virtual bool around_hexahedrons(const BoundingVolume **first, + const BoundingVolume **last); + virtual bool around_lines(const BoundingVolume **first, + const BoundingVolume **last); + + virtual int contains_sphere(const BoundingSphere *sphere) const; + virtual int contains_hexahedron(const BoundingHexahedron *hexahedron) const; + virtual int contains_line(const BoundingLine *line) const; + + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedReferenceCount::init_type(); + register_type(_type_handle, "BoundingVolume", + TypedReferenceCount::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; + friend class BoundingHexahedron; + friend class BoundingLine; +}; + +INLINE ostream &operator << (ostream &out, const BoundingVolume &bound); + +#include "boundingVolume.I" + +#endif diff --git a/panda/src/mathutil/config_mathutil.cxx b/panda/src/mathutil/config_mathutil.cxx new file mode 100644 index 0000000000..407a92178b --- /dev/null +++ b/panda/src/mathutil/config_mathutil.cxx @@ -0,0 +1,32 @@ +// Filename: config_mathutil.cxx +// Created by: drose (01Oct99) +// +//////////////////////////////////////////////////////////////////// + +#include "config_mathutil.h" +#include "boundingVolume.h" +#include "geometricBoundingVolume.h" +#include "finiteBoundingVolume.h" +#include "omniBoundingVolume.h" +#include "boundingSphere.h" +#include "boundingHexahedron.h" +#include "boundingLine.h" +#include + +Configure(config_mathutil); +NotifyCategoryDef(mathutil, ""); + +const double fft_offset = config_mathutil.GetDouble("fft-offset", 0.001); +const double fft_factor = config_mathutil.GetDouble("fft-factor", 0.1); +const double fft_exponent = config_mathutil.GetDouble("fft-exponent", 4); + +ConfigureFn(config_mathutil) { + BoundingHexahedron::init_type(); + BoundingSphere::init_type(); + BoundingVolume::init_type(); + FiniteBoundingVolume::init_type(); + GeometricBoundingVolume::init_type(); + OmniBoundingVolume::init_type(); + BoundingLine::init_type(); +} + diff --git a/panda/src/mathutil/config_mathutil.h b/panda/src/mathutil/config_mathutil.h new file mode 100644 index 0000000000..80b4b77ebf --- /dev/null +++ b/panda/src/mathutil/config_mathutil.h @@ -0,0 +1,20 @@ +// Filename: config_mathutil.h +// Created by: drose (01Oct99) +// +//////////////////////////////////////////////////////////////////// + +#ifndef CONFIG_MATHUTIL_H +#define CONFIG_MATHUTIL_H + +#include +#include + +NotifyCategoryDecl(mathutil, EXPCL_PANDA, EXPTP_PANDA); + +extern const double fft_offset; +extern const double fft_factor; +extern const double fft_exponent; + +#endif + + diff --git a/panda/src/mathutil/fftCompressor.cxx b/panda/src/mathutil/fftCompressor.cxx new file mode 100644 index 0000000000..62f406aea0 --- /dev/null +++ b/panda/src/mathutil/fftCompressor.cxx @@ -0,0 +1,805 @@ +// Filename: fftCompressor.cxx +// Created by: drose (11Dec00) +// +//////////////////////////////////////////////////////////////////// + +#include "fftCompressor.h" +#include "config_mathutil.h" + +#include +#include +#include +#include + +#ifdef HAVE_FFTW + +#include + +// These FFTW support objects can only be defined if we actually have +// the FFTW library available. +static rfftw_plan get_real_compress_plan(int length); +static rfftw_plan get_real_decompress_plan(int length); + +typedef map RealPlans; +static RealPlans _real_compress_plans; +static RealPlans _real_decompress_plans; + +#endif + +//////////////////////////////////////////////////////////////////// +// Function: FFTCompressor::Constructor +// Access: Public +// Description: Constructs a new compressor object with default +// parameters. +//////////////////////////////////////////////////////////////////// +FFTCompressor:: +FFTCompressor() { + set_quality(-1); +} + +//////////////////////////////////////////////////////////////////// +// Function: FFTCompressor::is_compression_available +// Access: Public, Static +// Description: Returns true if the FFTW library is compiled in, so +// that this class is actually capable of doing useful +// compression/decompression work. Returns false +// otherwise, in which case any attempt to write a +// compressed stream will actually write an uncompressed +// stream, and any attempt to read a compressed stream +// will fail. +//////////////////////////////////////////////////////////////////// +bool FFTCompressor:: +is_compression_available() { +#ifndef HAVE_FFTW + return false; +#else + return true; +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: FFTCompressor::set_quality +// Access: Public +// Description: Sets the quality factor for the compression. This is +// an integer in the range 0 - 100 that roughly controls +// how aggressively the reals are compressed; lower +// numbers mean smaller output, and more data loss. +// +// There are a few special cases. Quality -1 means to +// use whatever individual parameters are set in the +// user's Configrc file, rather than the single quality +// dial. Quality 101 or higher means to generate +// lossless output (this is the default if libfftw is +// not available). Quality 102 writes all four +// components of quaternions to the output file, rather +// than just three, and quality 103 doesn't even convert +// hpr to quat. +//////////////////////////////////////////////////////////////////// +void FFTCompressor:: +set_quality(int quality) { +#ifndef HAVE_FFTW + // If we don't actually have FFTW, we can't really compress anything. + if (_quality <= 100) { + mathutil_cat.warning() + << "FFTW library is not available; generating uncompressed output.\n"; + } + _quality = 101; + +#else + _quality = quality; + + if (_quality < 0) { + // A negative quality indicates we should read the various + // parameters from individual config variables. + _fft_offset = fft_offset; + _fft_factor = fft_factor; + _fft_exponent = fft_exponent; + + } else if (_quality < 40) { + // 0 - 40 : + // fft-offset 1.0 - 0.001 + // fft-factor 1.0 + // fft-exponent 4.0 + + double t = (double)_quality / 40.0; + _fft_offset = interpolate(t, 1.0, 0.001); + _fft_factor = 1.0; + _fft_exponent = 4.0; + + } else if (_quality < 95) { + // 40 - 95: + // fft-offset 0.001 + // fft-factor 1.0 - 0.1 + // fft-exponent 4.0 + + double t = (double)(_quality - 40) / 55.0; + _fft_offset = 0.001; + _fft_factor = interpolate(t, 1.0, 0.1); + _fft_exponent = 4.0; + + } else { + // 95 - 100: + // fft-offset 0.001 + // fft-factor 0.1 - 0.0 + // fft-exponent 4.0 + + double t = (double)(_quality - 95) / 5.0; + _fft_offset = 0.001; + _fft_factor = interpolate(t, 0.1, 0.0); + _fft_exponent = 4.0; + } +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: FFTCompressor::get_quality +// Access: Public +// Description: Returns the quality number that was previously set +// via set_quality(). +//////////////////////////////////////////////////////////////////// +int FFTCompressor:: +get_quality() const { + return _quality; +} + +//////////////////////////////////////////////////////////////////// +// Function: FFTCompressor::write_header +// Access: Public +// Description: Writes the compression parameters to the indicated +// datagram. It is necessary to call this before +// writing anything else to the datagram, since these +// parameters will be necessary to correctly decompress +// the data later. +//////////////////////////////////////////////////////////////////// +void FFTCompressor:: +write_header(Datagram &datagram) { + datagram.add_int8(_quality); + if (_quality < 0) { + datagram.add_float64(_fft_offset); + datagram.add_float64(_fft_factor); + datagram.add_float64(_fft_exponent); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: FFTCompressor::write_reals +// Access: Public +// Description: Writes an array of floating-point numbers to the +// indicated datagram. +//////////////////////////////////////////////////////////////////// +void FFTCompressor:: +write_reals(Datagram &datagram, const float *array, int length) { + datagram.add_int32(length); + + if (_quality > 100) { + // Special case: lossless output. + for (int i = 0; i < length; i++) { + datagram.add_float32(array[i]); + } + return; + } + +#ifndef HAVE_FFTW + // If we don't have FFTW, we shouldn't get here. + nassertv(false); + +#else + + if (length == 0) { + // Special case: do nothing. + return; + } + + if (length == 1) { + // Special case: just write out the one number. + datagram.add_float32(array[0]); + return; + } + + // Normal case: FFT the array, and write that out. + double *data = (double *)alloca(length * sizeof(double)); + int i; + for (i = 0; i < length; i++) { + data[i] = array[i]; + } + + double *half_complex = (double *)alloca(length * sizeof(double)); + + rfftw_plan plan = get_real_compress_plan(length); + rfftw_one(plan, data, half_complex); + + // Now encode the numbers, run-length encoded by size, so we only + // write out the number of bits we need for each number. + + vector_double run; + RunWidth run_width = RW_invalid; + int num_written = 0; + + for (i = 0; i < length; i++) { + static const double max_range_32 = 2147483647.0; + static const double max_range_16 = 32767.0; + static const double max_range_8 = 127.0; + + double scale_factor = get_scale_factor(i, length); + double num = floor(half_complex[i] / scale_factor + 0.5); + + // How many bits do we need to encode this integer? + double a = fabs(num); + RunWidth num_width; + + if (a == 0.0) { + num_width = RW_0; + + } else if (a <= max_range_8) { + num_width = RW_8; + + } else if (a <= max_range_16) { + num_width = RW_16; + + } else if (a <= max_range_32) { + num_width = RW_32; + + } else { + num_width = RW_double; + } + + // A special case: if we're writing a string of one-byters and we + // come across a single intervening zero, don't interrupt the run + // just for that. + if (run_width == RW_8 && num_width == RW_0) { + if (i + 1 >= length || half_complex[i + 1] != 0.0) { + num_width = RW_8; + } + } + + if (num_width != run_width) { + // Now we need to flush the last run. + num_written += write_run(datagram, run_width, run); + run.clear(); + run_width = num_width; + } + + run.push_back(num); + } + + num_written += write_run(datagram, run_width, run); + nassertv(num_written == length); +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: FFTCompressor::write_hprs +// Access: Public +// Description: Writes an array of HPR angles to the indicated +// datagram. +//////////////////////////////////////////////////////////////////// +void FFTCompressor:: +write_hprs(Datagram &datagram, const LVecBase3f *array, int length) { + if (_quality >= 103) { + // If quality level is at least 103, we don't even convert hpr to + // quat. + vector_float h, p, r; + for (int i = 0; i < length; i++) { + h.push_back(array[i][0]); + p.push_back(array[i][1]); + r.push_back(array[i][2]); + } + + write_reals(datagram, &h[0], length); + write_reals(datagram, &p[0], length); + write_reals(datagram, &r[0], length); + return; + } + + // First, convert the HPR's to quats. We expect quats to have + // better FFT consistency, and therefore compress better, even + // though they have an extra component. + + // However, because the quaternion will be normalized, we don't even + // have to write out all three components; any three can be used to + // determine the fourth (provided we ensure consistency of sign). + + vector_float qr, qi, qj, qk; + + for (int i = 0; i < length; i++) { + LMatrix3f mat; + compose_matrix(mat, LVecBase3f(1.0, 1.0, 1.0), array[i]); + + LOrientationf rot(mat); + rot.normalize(); + + if (rot.get_r() < 0) { + // Since rot == -rot, we can flip the quarternion if need be to + // keep the r component positive. This has two advantages. + // One, it makes it possible to infer r completely given i, j, + // and k (since we know it must be >= 0), and two, it helps + // protect against poor continuity caused by inadvertent + // flipping of the quarternion's sign between frames. + + // The choice of leaving r implicit rather than any of the other + // three seems to work the best in terms of guaranteeing + // continuity. + rot.set(-rot.get_r(), -rot.get_i(), -rot.get_j(), -rot.get_k()); + } + + // This is a debug severity, and not a warning or error, because + // (a) some small errors in hpr are usually acceptable, and (b) + // sometimes two different hpr trios actually represent the same + // rotation, e.g. (180, 0, -180) vs. (0, 0, 0). + if (mathutil_cat.is_debug()) { + LMatrix3f mat2; + rot.extract_to_matrix(mat2); + LVecBase3f scale, hpr; + bool success = decompose_matrix(mat2, scale, hpr); + nassertv(success); + if (!array[i].almost_equal(hpr, 0.001) || + !scale.almost_equal(LVecBase3f(1.0, 1.0, 1.0), 0.001)) { + mathutil_cat.debug() + << "Converted hpr to quaternion incorrectly!\n" + << " Source hpr: " << array[i] << "\n" + << " Quaternion: " << rot << "\n" + << " Which represents: hpr " << hpr << " scale " + << scale << "\n"; + } + } + + qr.push_back(rot.get_r()); + qi.push_back(rot.get_i()); + qj.push_back(rot.get_j()); + qk.push_back(rot.get_k()); + } + + // If quality is at least 102, we write all four quat components, + // instead of just the three. + if (_quality >= 102) { + write_reals(datagram, &qr[0], length); + } + write_reals(datagram, &qi[0], length); + write_reals(datagram, &qj[0], length); + write_reals(datagram, &qk[0], length); +} + +//////////////////////////////////////////////////////////////////// +// Function: FFTCompressor::read_header +// Access: Public +// Description: Reads the compression header that was written +// previously. This fills in the compression parameters +// necessary to correctly decompress the following data. +// +// Returns true if the header is read successfully, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool FFTCompressor:: +read_header(DatagramIterator &di) { + _quality = di.get_int8(); + + if (mathutil_cat.is_debug()) { + mathutil_cat.debug() + << "Found compressed data at quality level " << _quality << "\n"; + } + +#ifndef HAVE_FFTW + if (_quality <= 100) { + mathutil_cat.error() + << "FFTW library is not available; cannot read compressed data.\n"; + return false; + } +#endif + + set_quality(_quality); + + if (_quality < 0) { + _fft_offset = di.get_float64(); + _fft_factor = di.get_float64(); + _fft_exponent = di.get_float64(); + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: FFTCompressor::read_reals +// Access: Public +// Description: Reads an array of floating-point numbers. The result +// is pushed onto the end of the indicated vector, which +// is not cleared first; it is the user's responsibility +// to ensure that the array is initially empty. Returns +// true if the data is read correctly, false if there is +// an error. +//////////////////////////////////////////////////////////////////// +bool FFTCompressor:: +read_reals(DatagramIterator &di, vector_float &array) { + int length = di.get_int32(); + + if (_quality > 100) { + // Special case: lossless output. + for (int i = 0; i < length; i++) { + array.push_back(di.get_float32()); + } + return true; + } + +#ifndef HAVE_FFTW + // If we don't have FFTW, we shouldn't get here. + return false; + +#else + + if (length == 0) { + // Special case: do nothing. + return true; + } + + if (length == 1) { + // Special case: just read in the one number. + array.push_back(di.get_float32()); + return true; + } + + // Normal case: read in the FFT array, and convert it back to + // (nearly) the original numbers. + vector_double half_complex; + half_complex.reserve(length); + int num_read = 0; + while (num_read < length) { + num_read += read_run(di, half_complex); + } + nassertr(num_read == length, false); + nassertr((int)half_complex.size() == length, false); + + int i; + for (i = 0; i < length; i++) { + half_complex[i] *= get_scale_factor(i, length); + } + + double *data = (double *)alloca(length * sizeof(double)); + rfftw_plan plan = get_real_decompress_plan(length); + rfftw_one(plan, &half_complex[0], data); + + double scale = 1.0 / (double)length; + array.reserve(array.size() + length); + for (i = 0; i < length; i++) { + array.push_back(data[i] * scale); + } + + return true; +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: FFTCompressor::read_hprs +// Access: Public +// Description: Reads an array of HPR angles. The result is pushed +// onto the end of the indicated vector, which is not +// cleared first; it is the user's responsibility to +// ensure that the array is initially empty. +//////////////////////////////////////////////////////////////////// +bool FFTCompressor:: +read_hprs(DatagramIterator &di, vector_LVecBase3f &array) { + if (_quality >= 103) { + // If quality level is at least 103, we don't even convert hpr to + // quat. + vector_float h, p, r; + bool okflag = true; + okflag = + read_reals(di, h) && + read_reals(di, p) && + read_reals(di, r); + + if (okflag) { + nassertr(h.size() == p.size() && p.size() == r.size(), false); + for (int i = 0; i < (int)h.size(); i++) { + array.push_back(LVecBase3f(h[i], p[i], r[i])); + } + } + + return okflag; + } + + vector_float qr, qi, qj, qk; + + bool okflag = true; + + if (_quality >= 102) { + okflag = read_reals(di, qr); + } + + okflag = + okflag && + read_reals(di, qi) && + read_reals(di, qj) && + read_reals(di, qk); + + if (okflag) { + nassertr(qi.size() == qj.size() && qj.size() == qk.size(), false); + + array.reserve(array.size() + qi.size()); + for (int i = 0; i < (int)qi.size(); i++) { + LOrientationf rot; + + if (_quality >= 102) { + // If we have written out all four components, use them. + rot.set(qr[i], qi[i], qj[i], qj[i]); + + } else { + // Otherwise, infer the real component from the remaining + // three. + float qr2 = 1.0 - (qi[i] * qi[i] + qj[i] * qj[i] + qk[i] * qk[i]); + float qr1 = qr2 < 0.0 ? 0.0 : sqrtf(qr2); + rot.set(qr1, qi[i], qj[i], qk[i]); + } + + rot.normalize(); // Just for good measure. + + LMatrix3f mat; + rot.extract_to_matrix(mat); + LVecBase3f scale, hpr; + bool success = decompose_matrix(mat, scale, hpr); + nassertr(success, false); + + array.push_back(hpr); + } + } + + return okflag; +} + + +//////////////////////////////////////////////////////////////////// +// Function: FFTCompressor::free_storage +// Access: Public, Static +// Description: Frees memory that has been allocated during past runs +// of the FFTCompressor. This is an optional call, but +// it may be made from time to time to empty the global +// cache that the compressor objects keep to facilitate +// fast compression/decompression. +//////////////////////////////////////////////////////////////////// +void FFTCompressor:: +free_storage() { +#ifdef HAVE_FFTW + RealPlans::iterator pi; + for (pi = _real_compress_plans.begin(); + pi != _real_compress_plans.end(); + ++pi) { + rfftw_destroy_plan((*pi).second); + } + _real_compress_plans.clear(); + + for (pi = _real_decompress_plans.begin(); + pi != _real_decompress_plans.end(); + ++pi) { + rfftw_destroy_plan((*pi).second); + } + _real_decompress_plans.clear(); +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: FFTCompressor::write_run +// Access: Private +// Description: Writes a sequence of integers that all require the +// same number of bits. Returns the number of integers +// written, i.e. run.size(). +//////////////////////////////////////////////////////////////////// +int FFTCompressor:: +write_run(Datagram &datagram, FFTCompressor::RunWidth run_width, + const vector_double &run) { + if (run.empty()) { + return 0; + } + nassertr(run_width != RW_invalid, 0); + + if (run_width != RW_double) { + // If the width is anything other than RW_double, we write a + // single byte indicating the width and length of the upcoming + // run. + + if (run.size() <= RW_length_mask && + ((int)run_width | run.size()) != RW_double) { + // If there are enough bits remaining in the byte, use them to + // indicate the length of the run. We have to be a little + // careful, however, not to accidentally write a byte that looks + // like an RW_double flag. + datagram.add_uint8((int)run_width | run.size()); + + } else { + // Otherwise, write zero as the length, to indicate that we'll + // write the actual length in the following 16-bit word. + datagram.add_uint8(run_width); + + // Assuming, of course, that the length fits within 16 bits. + nassertr(run.size() < 65536, 0); + nassertr(run.size() != 0, 0); + + datagram.add_uint16(run.size()); + } + } + + // Now write the data itself. + vector_double::const_iterator ri; + switch (run_width) { + case RW_0: + // If it's a string of zeroes, we're done! + break; + + case RW_8: + for (ri = run.begin(); ri != run.end(); ++ri) { + datagram.add_int8((int)*ri); + } + break; + + case RW_16: + for (ri = run.begin(); ri != run.end(); ++ri) { + datagram.add_int16((int)*ri); + } + break; + + case RW_32: + for (ri = run.begin(); ri != run.end(); ++ri) { + datagram.add_int32((int)*ri); + } + break; + + case RW_double: + for (ri = run.begin(); ri != run.end(); ++ri) { + // In the case of RW_double, we only write the numbers one at a + // time, each time preceded by the RW_double flag. Hopefully + // this will happen only rarely. + datagram.add_int8((PN_int8)RW_double); + datagram.add_float64(*ri); + } + break; + + default: + break; + } + + return run.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: FFTCompressor::read_run +// Access: Private +// Description: Reads a sequence of integers that all require the +// same number of bits. Returns the number of integers +// read. It is the responsibility of the user to clear +// the vector before calling this function, or the +// numbers read will be appended to the end. +//////////////////////////////////////////////////////////////////// +int FFTCompressor:: +read_run(DatagramIterator &di, vector_double &run) { + PN_uint8 start = di.get_uint8(); + RunWidth run_width; + int length; + + if ((start & 0xff) == RW_double) { + // RW_double is a special case, and requires the whole byte. In + // this case, we don't encode a length, but assume it's only one. + run_width = RW_double; + length = 1; + + } else { + run_width = (RunWidth)(start & RW_width_mask); + length = start & RW_length_mask; + } + + if (length == 0) { + // If the length was zero, it means the actual length follows as a + // 16-bit word. + length = di.get_uint16(); + } + nassertr(length != 0, 0); + + run.reserve(run.size() + length); + + int i; + switch (run_width) { + case RW_0: + for (i = 0; i < length; i++) { + run.push_back(0.0); + } + break; + + case RW_8: + for (i = 0; i < length; i++) { + run.push_back((double)(int)di.get_int8()); + } + break; + + case RW_16: + for (i = 0; i < length; i++) { + run.push_back((double)(int)di.get_int16()); + } + break; + + case RW_32: + for (i = 0; i < length; i++) { + run.push_back((double)(int)di.get_int32()); + } + break; + + case RW_double: + for (i = 0; i < length; i++) { + run.push_back(di.get_float64()); + } + break; + + default: + break; + } + + return length; +} + +//////////////////////////////////////////////////////////////////// +// Function: FFTCompressor::get_scale_factor +// Access: Private +// Description: Returns the appropriate scaling for the given +// position within the halfcomplex array. +//////////////////////////////////////////////////////////////////// +double FFTCompressor:: +get_scale_factor(int i, int length) const { + int m = (length / 2) + 1; + int k = (i < m) ? i : length - i; + nassertr(k >= 0 && k < m, 1.0); + + return _fft_offset + + _fft_factor * pow((double)(m-1 - k) / (double)(m-1), _fft_exponent); +} + +//////////////////////////////////////////////////////////////////// +// Function: FFTCompressor::interpolate +// Access: Private, Static +// Description: Returns a number between a and b, inclusive, +// according to the value of t between 0 and 1, +// inclusive. +//////////////////////////////////////////////////////////////////// +double FFTCompressor:: +interpolate(double t, double a, double b) { + return a + t * (b - a); +} + + +#ifdef HAVE_FFTW + +//////////////////////////////////////////////////////////////////// +// Function: get_real_compress_plan +// Description: Returns a FFTW plan suitable for compressing a float +// array of the indicated length. +//////////////////////////////////////////////////////////////////// +static rfftw_plan +get_real_compress_plan(int length) { + RealPlans::iterator pi; + pi = _real_compress_plans.find(length); + if (pi != _real_compress_plans.end()) { + return (*pi).second; + } + + rfftw_plan plan; + plan = rfftw_create_plan(length, FFTW_REAL_TO_COMPLEX, FFTW_MEASURE); + _real_compress_plans.insert(RealPlans::value_type(length, plan)); + + return plan; +} + +//////////////////////////////////////////////////////////////////// +// Function: get_real_decompress_plan +// Description: Returns a FFTW plan suitable for decompressing a float +// array of the indicated length. +//////////////////////////////////////////////////////////////////// +static rfftw_plan +get_real_decompress_plan(int length) { + RealPlans::iterator pi; + pi = _real_decompress_plans.find(length); + if (pi != _real_decompress_plans.end()) { + return (*pi).second; + } + + rfftw_plan plan; + plan = rfftw_create_plan(length, FFTW_COMPLEX_TO_REAL, FFTW_MEASURE); + _real_decompress_plans.insert(RealPlans::value_type(length, plan)); + + return plan; +} + +#endif diff --git a/panda/src/mathutil/fftCompressor.h b/panda/src/mathutil/fftCompressor.h new file mode 100644 index 0000000000..e5e51f46ca --- /dev/null +++ b/panda/src/mathutil/fftCompressor.h @@ -0,0 +1,83 @@ +// Filename: fftCompressor.h +// Created by: drose (11Dec00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef FFTCOMPRESSOR_H +#define FFTCOMPRESSOR_H + +#include + +#include +#include +#include +#include + +class Datagram; +class DatagramIterator; + +//////////////////////////////////////////////////////////////////// +// Class : FFTCompressor +// Description : This class manages a lossy compression and +// decompression of a stream of floating-point numbers +// to a datagram, based a fourier transform algorithm +// (similar in principle to JPEG compression). +// +// Actually, it doesn't do any real compression on its +// own; it just outputs a stream of integers that should +// compress much tighter via gzip than the original +// stream of floats would have. +// +// This class depends on the external FFTW library; +// without it, it will fall back on lossless output of +// the original data. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA FFTCompressor { +public: + FFTCompressor(); + + static bool is_compression_available(); + + void set_quality(int quality); + int get_quality() const; + + void write_header(Datagram &datagram); + void write_reals(Datagram &datagram, const float *array, int length); + void write_hprs(Datagram &datagram, const LVecBase3f *array, int length); + + bool read_header(DatagramIterator &di); + bool read_reals(DatagramIterator &di, vector_float &array); + bool read_hprs(DatagramIterator &di, vector_LVecBase3f &array); + + static void free_storage(); + +private: + enum RunWidth { + // We write a byte to the datagram at the beginning of each run to + // encode the width and length of the run. The width is indicated + // by the top two bits, while the length fits in the lower six, + // except RW_double, which is a special case. + RW_width_mask = 0xc0, + RW_length_mask = 0x3f, + RW_0 = 0x00, + RW_8 = 0x40, + RW_16 = 0x80, + RW_32 = 0xc0, + RW_double = 0xff, + RW_invalid = 0x01 + }; + + int write_run(Datagram &datagram, RunWidth run_width, + const vector_double &run); + int read_run(DatagramIterator &di, vector_double &run); + double get_scale_factor(int i, int length) const; + static double interpolate(double t, double a, double b); + + int _quality; + double _fft_offset; + double _fft_factor; + double _fft_exponent; +}; + +#endif + diff --git a/panda/src/mathutil/finiteBoundingVolume.cxx b/panda/src/mathutil/finiteBoundingVolume.cxx new file mode 100644 index 0000000000..216096c741 --- /dev/null +++ b/panda/src/mathutil/finiteBoundingVolume.cxx @@ -0,0 +1,8 @@ +// Filename: finiteBoundingVolume.cxx +// Created by: drose (02Oct99) +// +//////////////////////////////////////////////////////////////////// + +#include "finiteBoundingVolume.h" + +TypeHandle FiniteBoundingVolume::_type_handle; diff --git a/panda/src/mathutil/finiteBoundingVolume.h b/panda/src/mathutil/finiteBoundingVolume.h new file mode 100644 index 0000000000..90c6ca8812 --- /dev/null +++ b/panda/src/mathutil/finiteBoundingVolume.h @@ -0,0 +1,63 @@ +// Filename: finiteBoundingVolume.h +// Created by: drose (02Oct99) +// +//////////////////////////////////////////////////////////////////// + +#ifndef FINITEBOUNDINGVOLUME_H +#define FINITEBOUNDINGVOLUME_H + +#include + +#include "geometricBoundingVolume.h" + + +/////////////////////////////////////////////////////////////////// +// Class : FiniteBoundingVolume +// Description : A special kind of GeometricBoundingVolume that is +// known to be finite. It is possible to query this +// kind of volume for its minimum and maximum extents. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA FiniteBoundingVolume : public GeometricBoundingVolume { +PUBLISHED: + virtual LPoint3f get_min() const=0; + virtual LPoint3f get_max() const=0; + + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + GeometricBoundingVolume::init_type(); + register_type(_type_handle, "FiniteBoundingVolume", + 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; +}; + +#endif + + + + + + + + + + + + + + + + + + + diff --git a/panda/src/mathutil/frustum.N b/panda/src/mathutil/frustum.N new file mode 100644 index 0000000000..fd8a62819a --- /dev/null +++ b/panda/src/mathutil/frustum.N @@ -0,0 +1,7 @@ +forcetype Frustumf +renametype Frustumf Frustumf +forcetype Frustumd +renametype Frustumd Frustumd + +noinclude frustum_src.h +noinclude look_at_src.h diff --git a/panda/src/mathutil/frustum.h b/panda/src/mathutil/frustum.h new file mode 100644 index 0000000000..49be89221d --- /dev/null +++ b/panda/src/mathutil/frustum.h @@ -0,0 +1,23 @@ +// Filename: frustum.h +// Created by: mike (09Jan97) +// +//////////////////////////////////////////////////////////////////// +// +#ifndef FRUSTUM_H +#define FRUSTUM_H +// +//////////////////////////////////////////////////////////////////// +// Includes +//////////////////////////////////////////////////////////////////// +#include +#include +#include +#include "config_mathutil.h" + +#include "fltnames.h" +#include "frustum_src.h" + +#include "dblnames.h" +#include "frustum_src.h" + +#endif diff --git a/panda/src/mathutil/geometricBoundingVolume.I b/panda/src/mathutil/geometricBoundingVolume.I new file mode 100644 index 0000000000..253c64d7e6 --- /dev/null +++ b/panda/src/mathutil/geometricBoundingVolume.I @@ -0,0 +1,108 @@ +// Filename: geometricBoundingVolume.I +// Created by: drose (07Oct99) +// +//////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// Function: GeometricBoundingVolume::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE GeometricBoundingVolume:: +GeometricBoundingVolume() { +} + +//////////////////////////////////////////////////////////////////// +// Function: GeometricBoundingVolume::extend_by +// Access: Public +// Description: Increases the size of the volume to include the given +// volume. +//////////////////////////////////////////////////////////////////// +INLINE bool GeometricBoundingVolume:: +extend_by(const GeometricBoundingVolume *vol) { + return BoundingVolume::extend_by(vol); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeometricBoundingVolume::extend_by +// Access: Public +// Description: Increases the size of the volume to include the given +// point. +//////////////////////////////////////////////////////////////////// +INLINE bool GeometricBoundingVolume:: +extend_by(const LPoint3f &point) { + return extend_by_point(point); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeometricBoundingVolume::around +// Access: Public +// Description: Resets the volume to enclose only the volumes +// indicated. +//////////////////////////////////////////////////////////////////// +INLINE bool GeometricBoundingVolume:: +around(const GeometricBoundingVolume **first, + const GeometricBoundingVolume **last) { + return BoundingVolume::around((const BoundingVolume **)first, + (const BoundingVolume **)last); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeometricBoundingVolume::around +// Access: Public +// Description: Resets the volume to enclose only the points +// indicated. +//////////////////////////////////////////////////////////////////// +INLINE bool GeometricBoundingVolume:: +around(const LPoint3f *first, const LPoint3f *last) { + _flags = F_empty; + if (first != last) { + return around_points(first, last); + } + return true; +} + + +//////////////////////////////////////////////////////////////////// +// Function: GeometricBoundingVolume::contains +// Access: Public +// Description: Returns the appropriate set of IntersectionFlags to +// indicate the amount of intersection with the +// indicated volume. +//////////////////////////////////////////////////////////////////// +INLINE int GeometricBoundingVolume:: +contains(const GeometricBoundingVolume *vol) const { + return BoundingVolume::contains(vol); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeometricBoundingVolume::contains +// Access: Public +// Description: Returns the appropriate set of IntersectionFlags to +// indicate the amount of intersection with the +// indicated point. +//////////////////////////////////////////////////////////////////// +INLINE int GeometricBoundingVolume:: +contains(const LPoint3f &point) const { + if (is_empty()) { + return IF_no_intersection; + } + + return contains_point(point); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeometricBoundingVolume::contains +// Access: Public +// Description: Returns the appropriate set of IntersectionFlags to +// indicate the amount of intersection with the +// indicated line segment. +//////////////////////////////////////////////////////////////////// +INLINE int GeometricBoundingVolume:: +contains(const LPoint3f &a, const LPoint3f &b) const { + if (is_empty()) { + return IF_no_intersection; + } + + return contains_lineseg(a, b); +} diff --git a/panda/src/mathutil/geometricBoundingVolume.cxx b/panda/src/mathutil/geometricBoundingVolume.cxx new file mode 100644 index 0000000000..f8275607a5 --- /dev/null +++ b/panda/src/mathutil/geometricBoundingVolume.cxx @@ -0,0 +1,30 @@ +// Filename: geometricBoundingVolume.cxx +// Created by: drose (07Oct99) +// +//////////////////////////////////////////////////////////////////// + +#include "geometricBoundingVolume.h" + +TypeHandle GeometricBoundingVolume::_type_handle; + + +bool GeometricBoundingVolume:: +extend_by_point(const LPoint3f &) { + return false; +} + +bool GeometricBoundingVolume:: +around_points(const LPoint3f *, const LPoint3f *) { + _flags = F_empty; + return false; +} + +int GeometricBoundingVolume:: +contains_point(const LPoint3f &) const { + return IF_dont_understand; +} + +int GeometricBoundingVolume:: +contains_lineseg(const LPoint3f &, const LPoint3f &) const { + return IF_dont_understand; +} diff --git a/panda/src/mathutil/geometricBoundingVolume.h b/panda/src/mathutil/geometricBoundingVolume.h new file mode 100644 index 0000000000..2e0a15780e --- /dev/null +++ b/panda/src/mathutil/geometricBoundingVolume.h @@ -0,0 +1,76 @@ +// Filename: geometricBoundingVolume.h +// Created by: drose (07Oct99) +// +//////////////////////////////////////////////////////////////////// + +#ifndef GEOMETRICBOUNDINGVOLUME_H +#define GEOMETRICBOUNDINGVOLUME_H + +#include + +#include "boundingVolume.h" + +#include +#include + +/////////////////////////////////////////////////////////////////// +// Class : GeometricBoundingVolume +// Description : This is another abstract class, for a general class +// of bounding volumes that actually enclose points in +// 3-d space, such as BSP's and bounding spheres. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA GeometricBoundingVolume : public BoundingVolume { +public: + INLINE GeometricBoundingVolume(); + +PUBLISHED: + INLINE bool extend_by(const GeometricBoundingVolume *vol); + INLINE bool extend_by(const LPoint3f &point); + + // It might be nice to make these template member functions so we + // could have true STL-style first/last iterators, but that's + // impossible for virtual functions. + INLINE bool around(const GeometricBoundingVolume **first, + const GeometricBoundingVolume **last); + INLINE bool around(const LPoint3f *first, + const LPoint3f *last); + + INLINE int contains(const GeometricBoundingVolume *vol) const; + INLINE int contains(const LPoint3f &point) const; + INLINE int contains(const LPoint3f &a, const LPoint3f &b) const; + + virtual LPoint3f get_approx_center() const=0; + virtual void xform(const LMatrix4f &mat)=0; + +protected: + // Some virtual functions to implement fundamental bounding + // operations on points in 3-d space. + + virtual bool extend_by_point(const LPoint3f &point); + virtual bool around_points(const LPoint3f *first, + const LPoint3f *last); + virtual int contains_point(const LPoint3f &point) const; + virtual int contains_lineseg(const LPoint3f &a, const LPoint3f &b) const; + + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + BoundingVolume::init_type(); + register_type(_type_handle, "GeometricBoundingVolume", + BoundingVolume::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; +}; + +#include "geometricBoundingVolume.I" + +#endif diff --git a/panda/src/mathutil/look_at.cxx b/panda/src/mathutil/look_at.cxx new file mode 100644 index 0000000000..9d9842c339 --- /dev/null +++ b/panda/src/mathutil/look_at.cxx @@ -0,0 +1,12 @@ +// Filename: look_at.cxx +// Created by: drose (25Apr97) +// +//////////////////////////////////////////////////////////////////// + +#include "look_at.h" + +#include "fltnames.h" +#include "look_at_src.cxx" + +#include "dblnames.h" +#include "look_at_src.cxx" diff --git a/panda/src/mathutil/look_at.h b/panda/src/mathutil/look_at.h new file mode 100644 index 0000000000..d314ca5feb --- /dev/null +++ b/panda/src/mathutil/look_at.h @@ -0,0 +1,23 @@ +// Filename: look_at.h +// Created by: drose (25Apr97) +// +//////////////////////////////////////////////////////////////////// + +#ifndef LOOKAT_H +#define LOOKAT_H + +//////////////////////////////////////////////////////////////////// +// Includes +/////////////////////////////////////////////////////////////////// +#include +#include "cmath.h" +#include "coordinateSystem.h" +#include "luse.h" + +#include "fltnames.h" +#include "look_at_src.h" + +#include "dblnames.h" +#include "look_at_src.h" + +#endif diff --git a/panda/src/mathutil/look_at_src.I b/panda/src/mathutil/look_at_src.I new file mode 100644 index 0000000000..c1d4577e96 --- /dev/null +++ b/panda/src/mathutil/look_at_src.I @@ -0,0 +1,41 @@ +// Filename: look_at_src.I +// Created by: drose (25Sep99) +// +//////////////////////////////////////////////////////////////////// + +INLINE void +heads_up(FLOATNAME(LMatrix3) &mat, const FLOATNAME(LVector3) &fwd, CoordinateSystem cs) { + heads_up(mat, fwd, FLOATNAME(LVector3)::up(cs), cs); +} + +INLINE void +look_at(FLOATNAME(LMatrix3) &mat, const FLOATNAME(LVector3) &fwd, CoordinateSystem cs) { + look_at(mat, fwd, FLOATNAME(LVector3)::up(cs), cs); +} + +INLINE void +heads_up(FLOATNAME(LMatrix4) &mat, const FLOATNAME(LVector3) &fwd, + const FLOATNAME(LVector3) &up, CoordinateSystem cs) { + FLOATNAME(LMatrix3) mat3; + heads_up(mat3, fwd, up, cs); + mat = FLOATNAME(LMatrix4)(mat3); +} + +INLINE void +look_at(FLOATNAME(LMatrix4) &mat, const FLOATNAME(LVector3) &fwd, + const FLOATNAME(LVector3) &up, CoordinateSystem cs) { + FLOATNAME(LMatrix3) mat3; + look_at(mat3, fwd, up, cs); + mat = FLOATNAME(LMatrix4)(mat3); +} + +INLINE void +heads_up(FLOATNAME(LMatrix4) &mat, const FLOATNAME(LVector3) &fwd, CoordinateSystem cs) { + heads_up(mat, fwd, FLOATNAME(LVector3)::up(cs), cs); +} + +INLINE void +look_at(FLOATNAME(LMatrix4) &mat, const FLOATNAME(LVector3) &fwd, CoordinateSystem cs) { + look_at(mat, fwd, FLOATNAME(LVector3)::up(cs), cs); +} + diff --git a/panda/src/mathutil/mathHelpers.I b/panda/src/mathutil/mathHelpers.I new file mode 100644 index 0000000000..2698113d06 --- /dev/null +++ b/panda/src/mathutil/mathHelpers.I @@ -0,0 +1,14 @@ +// Filename: mathHelpers.I +// Created by: mike (25Apr97) +// +//////////////////////////////////////////////////////////////////// +// +//////////////////////////////////////////////////////////////////// +// Includes +//////////////////////////////////////////////////////////////////// +#include + +INLINE float distance(const LPoint3f &pos0, const LPoint3f &pos1) { + LVector3f v = pos0 - pos1; + return length(v); +} diff --git a/panda/src/mathutil/mathHelpers.h b/panda/src/mathutil/mathHelpers.h new file mode 100644 index 0000000000..a3607c7e4a --- /dev/null +++ b/panda/src/mathutil/mathHelpers.h @@ -0,0 +1,24 @@ +// Filename: mathHelpers.h +// Created by: mike (25Apr97) +// +//////////////////////////////////////////////////////////////////// + +#ifndef MATHHELPERS_H +#define MATHHELPERS_H + +//////////////////////////////////////////////////////////////////// +// Includes +/////////////////////////////////////////////////////////////////// +#include + +#include + +BEGIN_PUBLISH + +INLINE float distance(const LPoint3f &pos0, const LPoint3f &pos1); + +END_PUBLISH + +#include "mathHelpers.I" + +#endif diff --git a/panda/src/mathutil/omniBoundingVolume.I b/panda/src/mathutil/omniBoundingVolume.I new file mode 100644 index 0000000000..2882be4f2d --- /dev/null +++ b/panda/src/mathutil/omniBoundingVolume.I @@ -0,0 +1,14 @@ +// Filename: omniBoundingVolume.I +// Created by: drose (22Jun00) +// +//////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE OmniBoundingVolume:: +OmniBoundingVolume() { + _flags = F_infinite; +} diff --git a/panda/src/mathutil/omniBoundingVolume.cxx b/panda/src/mathutil/omniBoundingVolume.cxx new file mode 100644 index 0000000000..c88ec2157e --- /dev/null +++ b/panda/src/mathutil/omniBoundingVolume.cxx @@ -0,0 +1,187 @@ +// Filename: omniBoundingVolume.cxx +// Created by: drose (22Jun00) +// +//////////////////////////////////////////////////////////////////// + +#include "omniBoundingVolume.h" +#include "boundingHexahedron.h" +#include "config_mathutil.h" + +#include + +TypeHandle OmniBoundingVolume::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +BoundingVolume *OmniBoundingVolume:: +make_copy() const { + return new OmniBoundingVolume(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::get_approx_center +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +LPoint3f OmniBoundingVolume:: +get_approx_center() const { + return LPoint3f(0.0, 0.0, 0.0); +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::xform +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void OmniBoundingVolume:: +xform(const LMatrix4f &) { +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void OmniBoundingVolume:: +output(ostream &out) const { + out << "omni"; +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::extend_other +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +bool OmniBoundingVolume:: +extend_other(BoundingVolume *other) const { + other->set_infinite(); + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::around_other +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +bool OmniBoundingVolume:: +around_other(BoundingVolume *other, + const BoundingVolume **, + const BoundingVolume **) const { + other->set_infinite(); + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::contains_other +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +int OmniBoundingVolume:: +contains_other(const BoundingVolume *) const { + return IF_possible | IF_some | IF_all; +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::extend_by_point +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +bool OmniBoundingVolume:: +extend_by_point(const LPoint3f &) { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::extend_by_sphere +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +bool OmniBoundingVolume:: +extend_by_sphere(const BoundingSphere *) { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::extend_by_hexahedron +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +bool OmniBoundingVolume:: +extend_by_hexahedron(const BoundingHexahedron *) { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::around_points +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +bool OmniBoundingVolume:: +around_points(const LPoint3f *, const LPoint3f *) { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::around_spheres +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +bool OmniBoundingVolume:: +around_spheres(const BoundingVolume **, + const BoundingVolume **) { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::around_hexahedrons +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +bool OmniBoundingVolume:: +around_hexahedrons(const BoundingVolume **, + const BoundingVolume **) { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::contains_point +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +int OmniBoundingVolume:: +contains_point(const LPoint3f &) const { + return IF_possible | IF_some | IF_all; +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::contains_lineseg +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +int OmniBoundingVolume:: +contains_lineseg(const LPoint3f &, const LPoint3f &) const { + return IF_possible | IF_some | IF_all; +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::contains_sphere +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +int OmniBoundingVolume:: +contains_sphere(const BoundingSphere *) const { + return IF_possible | IF_some | IF_all; +} + +//////////////////////////////////////////////////////////////////// +// Function: OmniBoundingVolume::contains_hexahedron +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +int OmniBoundingVolume:: +contains_hexahedron(const BoundingHexahedron *) const { + return IF_possible | IF_some | IF_all; +} diff --git a/panda/src/mathutil/omniBoundingVolume.h b/panda/src/mathutil/omniBoundingVolume.h new file mode 100644 index 0000000000..6b41e15c82 --- /dev/null +++ b/panda/src/mathutil/omniBoundingVolume.h @@ -0,0 +1,76 @@ +// Filename: omniBoundingVolume.h +// Created by: drose (22Jun00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef OMNIBOUNDINGVOLUME_H +#define OMNIBOUNDINGVOLUME_H + +#include + +#include "geometricBoundingVolume.h" + +/////////////////////////////////////////////////////////////////// +// Class : OmniBoundingVolume +// Description : This is a special kind of GeometricBoundingVolume +// that fills all of space. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA OmniBoundingVolume : public GeometricBoundingVolume { +PUBLISHED: + INLINE OmniBoundingVolume(); + +public: + virtual BoundingVolume *make_copy() const; + + virtual LPoint3f get_approx_center() const; + virtual void xform(const LMatrix4f &mat); + + virtual void output(ostream &out) 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_hexahedron(const BoundingHexahedron *hexahedron) const; + virtual int contains_sphere(const BoundingSphere *sphere) const; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + GeometricBoundingVolume::init_type(); + register_type(_type_handle, "OmniBoundingVolume", + 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 BoundingHexahedron; +}; + +#include "omniBoundingVolume.I" + +#endif diff --git a/panda/src/mathutil/plane.N b/panda/src/mathutil/plane.N new file mode 100644 index 0000000000..2ac43a7735 --- /dev/null +++ b/panda/src/mathutil/plane.N @@ -0,0 +1,6 @@ +forcetype Planef +renametype Planef Planef +forcetype Planed +renametype Planed Planed + +noinclude plane_src.h diff --git a/panda/src/mathutil/plane.cxx b/panda/src/mathutil/plane.cxx new file mode 100644 index 0000000000..95504474b4 --- /dev/null +++ b/panda/src/mathutil/plane.cxx @@ -0,0 +1,12 @@ +// Filename: plane.cxx +// Created by: drose (19May00) +// +//////////////////////////////////////////////////////////////////// + +#include "plane.h" + +#include "fltnames.h" +#include "plane_src.cxx" + +#include "dblnames.h" +#include "plane_src.cxx" diff --git a/panda/src/mathutil/plane.h b/panda/src/mathutil/plane.h new file mode 100644 index 0000000000..e6f9a90502 --- /dev/null +++ b/panda/src/mathutil/plane.h @@ -0,0 +1,25 @@ +// Filename: plane.h +// Created by: mike (09Jan97) +// +//////////////////////////////////////////////////////////////////// + +#ifndef PLANE_H +#define PLANE_H + +#include + +#include +#include +#include +#include + +class Datagram; +class DatagramIterator; + +#include "fltnames.h" +#include "plane_src.h" + +#include "dblnames.h" +#include "plane_src.h" + +#endif diff --git a/panda/src/mathutil/rotate_to.cxx b/panda/src/mathutil/rotate_to.cxx new file mode 100644 index 0000000000..15ff059b6d --- /dev/null +++ b/panda/src/mathutil/rotate_to.cxx @@ -0,0 +1,14 @@ +// Filename: rotate_to.cxx +// Created by: drose (04Nov99) +// +//////////////////////////////////////////////////////////////////// + +#include +#include +#include "rotate_to.h" + +#include "fltnames.h" +#include "rotate_to_src.cxx" + +#include "dblnames.h" +#include "rotate_to_src.cxx" diff --git a/panda/src/mathutil/rotate_to.h b/panda/src/mathutil/rotate_to.h new file mode 100644 index 0000000000..24142443b2 --- /dev/null +++ b/panda/src/mathutil/rotate_to.h @@ -0,0 +1,34 @@ +// Filename: rotate_to.h +// Created by: drose (04Nov99) +// +//////////////////////////////////////////////////////////////////// + +#ifndef ROTATE_TO_H +#define ROTATE_TO_H + +//////////////////////////////////////////////////////////////////// +// +// rotate_to() +// +// This function computes a suitable rotation matrix to rotate vector +// a onto vector b. That is, it computes mat so that a * mat = b. +// The rotation axis is chosen to give the smallest possible rotation +// angle. +// +//////////////////////////////////////////////////////////////////// + +#include +#include +#include "luse.h" + +BEGIN_PUBLISH + +EXPCL_PANDA void rotate_to(LMatrix3f &mat, const LVector3f &a, const LVector3f &b); +EXPCL_PANDA void rotate_to(LMatrix3d &mat, const LVector3d &a, const LVector3d &b); + +EXPCL_PANDA void rotate_to(LMatrix4f &mat, const LVector3f &a, const LVector3f &b); +EXPCL_PANDA void rotate_to(LMatrix4d &mat, const LVector3d &a, const LVector3d &b); + +END_PUBLISH + +#endif diff --git a/panda/src/mathutil/test_mathutil.cxx b/panda/src/mathutil/test_mathutil.cxx new file mode 100644 index 0000000000..62896f1f59 --- /dev/null +++ b/panda/src/mathutil/test_mathutil.cxx @@ -0,0 +1,53 @@ +// Filename: test_mathutil.cxx +// Created by: drose (16Mar00) +// +//////////////////////////////////////////////////////////////////// + +#include +#include "rotate_to.h" +#include "boundingLine.h" +#include "boundingSphere.h" + +int +main() { + /* + LVector3d a(1.0, 0.0, 0.0); + LVector3d b = normalize(LVector3d(0.5, 0.5, 0.0)); + + LMatrix3d rot; + rotate_to(rot, a, b); + + nout << "a = " << a << "\n" + << "b = " << b << "\n" + << "rot =\n"; + rot.write(nout, 2); + nout << "a * rot = " << a * rot << " length " << length(a * rot) << "\n" + << "a * invert(rot) = " << a * invert(rot) + << " length " << length(a * invert(rot)) << "\n" + << "b * rot = " << b * rot + << " length " << length(b * rot) << "\n" + << "b * invert(rot) = " << b * invert(rot) + << " length " << length(a * invert(rot)) << "\n"; + */ + + BoundingLine line(LPoint3f(0, 0, 1), LPoint3f(0, 0, 0)); + + BoundingSphere s1(LPoint3f(0, 0, 10), 1); + BoundingSphere s2(LPoint3f(10, 0, 10), 1); + BoundingSphere s3(LPoint3f(1, 0, 0), 1); + BoundingSphere s4(LPoint3f(-1, -1, -1), 1); + + line.contains(&s1); + line.contains(&s2); + line.contains(&s3); + line.contains(&s4); + + /* + s1.contains(LPoint3f(0, 0, 1), LPoint3f(0, 0, 0)); + s2.contains(LPoint3f(0, 0, 1), LPoint3f(0, 0, 0)); + s3.contains(LPoint3f(0, 0, 1), LPoint3f(0, 0, 0)); + s4.contains(LPoint3f(0, 0, 1), LPoint3f(0, 0, 0)); + */ + + return (0); +}