math.h

Go to the documentation of this file.
00001 //**************************************************************************/
00002 // Copyright (c) 2008 Autodesk, Inc.
00003 // All rights reserved.
00004 
00005 // Use of this software is subject to the terms of the Autodesk license
00006 // agreement provided at the time of installation or download, or which
00007 // otherwise accompanies this software in either electronic or hard copy form.
00008 //
00009 
00010 //**************************************************************************/                      
00011 // DESCRIPTION:
00012 // CREATED: October 2008
00013 //**************************************************************************/
00014 
00015 #if defined(_MSC_VER)
00016 #pragma warning(push)
00017 #pragma warning(disable : 4201)
00018 #endif
00019 
00020 
00021 #include <xmmintrin.h>
00022 
00023 #if defined(WIN32) || defined(WIN64)
00024 #include <intrin.h>
00025 #endif
00026 
00027 #if (defined(_WIN32) && !defined(_WIN64))
00028 #define OS_32BIT true
00029 #endif
00030 
00031 
00032 namespace mudbox {
00033 
00035 class MBDLL_DECL Vector
00036 {
00037 public:
00039     inline Vector( void ) throw() { x = y = z = 0.0f; };
00040 
00042     inline Vector( float fX, float fY, float fZ = 0.0f ) throw() 
00043     { x = fX; y = fY; z = fZ; };
00044 
00046     inline Vector( const Vector &vVector ) throw() 
00047     { x = vVector.x; y = vVector.y; z = vVector.z; };
00048 
00052     inline Vector( const char *pVector ) throw()
00053     { x = pVector[0]*(1.0f/127.0f); y = pVector[1]*(1.0f/127.0f); z = pVector[2]*(1.0f/127.0f); };
00054 
00057     inline Vector( const short *pVector ) throw() 
00058     { x = pVector[0]*(1.0f/32767.0f); y = pVector[1]*(1.0f/32767.0f); z = pVector[2]*(1.0f/32767.0f); };
00059 
00061     inline Vector &Set( float fX, float fY, float fZ ) throw() 
00062     { x = fX; y = fY; z = fZ; return *this; };
00063 
00065     inline Vector &Clear( void ) throw () 
00066     { return Set( 0.0f, 0.0f, 0.0f ); };
00067 
00071     Vector &Normalize( void ) throw();
00072 
00077     Vector &NormalizeApprox( void ) throw();
00078 
00080     Vector Normalized( void ) const throw();
00081 
00087     Vector &MakeOrthogonal( const Vector &vBase );
00088 
00094     inline Vector &SetLength( float fLength ) 
00095     { Normalize(); operator *=( fLength ); return *this; };
00096 
00097 
00103     inline Vector &RotateOrthogonal( const Vector &vBase ) 
00104     { float fLen = Length(); MakeOrthogonal( vBase ); SetLength( fLen ); return *this; };
00105 
00106     
00108     inline float LengthSquare( void ) const { return x*x+y*y+z*z; };
00109     
00111     float Length() const throw();
00112 
00114     float Length2D() const throw();
00115 
00118     inline float DistanceFrom( const Vector &v ) const { return operator -(v).Length(); };
00119 
00122     float DistanceFromLine( const Vector &v0, const Vector &v1 ) const;
00123 
00126     float DistanceFromSegment( const Vector &v0, const Vector &v1 ) const;
00127 
00134     float DistanceFromTriangleSquared( const Vector& v0, const Vector& v1, const Vector& v2, 
00135                                        float* aBaryCoords = 0 ) const;
00136 
00149     const Vector &Relocate2D( const Vector &v0, const Vector &v1 );
00150 
00160     void Relocate( const Vector &v0, const Vector &v1, const Vector &v2 );
00161 
00162 
00183     bool Relocate2DQuad( const Vector &v0, const Vector &v1, 
00184                          const Vector &v2, const Vector &v3 );
00185 
00191     bool RelocateQuad( const Vector &v0, const Vector &v1, 
00192                          const Vector &v2, const Vector &v3 );
00193     
00195     float AngleCos( const Vector &v1 ) const throw() 
00196     { return Vector(*this).Normalize()|Vector(v1).Normalize(); };
00197     
00198 
00201     inline Vector Minimum( const Vector &o ) 
00202     { return Vector( Min(x, o.x), Min(y, o.y), Min(z, o.z) ); };
00203 
00206     inline Vector Maximum( const Vector &o ) 
00207     { return Vector( Max(x, o.x), Max(y, o.y), Max(z, o.z) ); };
00208 
00210     inline Vector operator -( void ) const throw() 
00211     { return Vector( -x, -y, -z ); };
00212 
00215     inline Vector operator +( float f ) const throw() 
00216     { return Vector( x+f, y+f, z+f ); };
00217 
00219     inline Vector operator +( const Vector &v ) const throw() 
00220     { return Vector( x+v.x, y+v.y, z+v.z ); };
00221 
00223     inline Vector operator -( const Vector &v ) const throw() 
00224     { return Vector( x-v.x, y-v.y, z-v.z ); };
00225 
00227     inline Vector operator *( const Vector &v ) const throw() 
00228     { return Vector( x*v.x, y*v.y, z*v.z ); };
00229 
00231     inline Vector operator *( float f ) const throw() 
00232     { return Vector( x*f, y*f, z*f ); };
00233     
00235     inline Vector operator /( const Vector &v ) const throw() 
00236     { return Vector( x/v.x, y/v.y, z/v.z ); };
00237 
00239     inline Vector operator /( float f ) const throw() 
00240     { return operator *( 1.0f/f ); };
00241 
00243     inline Vector operator *( int i ) const throw() 
00244     { return operator *( float(i) ); };
00245 
00247     inline Vector operator /( int i ) const throw() 
00248     { return operator /( float(i) ); };
00249 
00251     inline Vector operator /( unsigned int i ) const throw() 
00252     { return operator /( float(i) ); };
00253 
00255     inline float operator |( const Vector &v ) const throw() 
00256     { return x*v.x+y*v.y+z*v.z; };
00257 
00259     Vector operator &( const Vector &v ) const
00260     {
00261         Vector vR;
00262         vR.m_fX = m_fY*v.m_fZ-m_fZ*v.m_fY;
00263         vR.m_fY = m_fZ*v.m_fX-m_fX*v.m_fZ;
00264         vR.m_fZ = m_fX*v.m_fY-m_fY*v.m_fX;
00265         return vR;
00266     };
00267 
00268 
00271     inline bool operator ==( const Vector &v ) const throw() 
00272     { return x == v.x && y == v.y && z == v.z; };
00273 
00275     inline bool operator !=( const Vector &v ) const throw() 
00276     { return !operator ==( v ); };
00277 
00279     inline operator bool( void ) const throw() { return x || y || z; };
00280     
00282     inline bool operator !( void ) const throw() { return !operator bool(); };
00283 
00285     inline Vector &operator =( const Vector &v ) 
00286     { x = v.x; y = v.y; z = v.z; return *this; };
00287 
00289     inline Vector &operator <<( const Vector &v ) 
00290     { x = v.x; y = v.y; z = v.z; return *this; };
00291 
00294     inline Vector &operator -=( const Vector &v ) throw() 
00295     { x-=v.x; y-=v.y; z-=v.z; return *this; };
00296     
00298     inline Vector &operator +=( const Vector &v ) throw() 
00299         { x+=v.x; y+=v.y; z+=v.z; return *this; };
00300 
00303     inline Vector &operator *=( float f ) { x *= f; y *= f; z *= f; return *this; };
00304 
00307     inline Vector &operator *=( const Vector &v ) 
00308         { x *= v.x; y *= v.y; z *= v.z; return *this; };
00309 
00311     inline Vector &operator /=( float f ) { return operator *=( 1.0f/f ); };
00312 
00314     inline float &operator [] (
00315         int i   
00316         ) throw() { return m_aCoors[i]; };
00317 
00319     inline float &operator [](
00320         unsigned int i  
00321         ) throw() { return m_aCoors[i]; };
00322         
00324     inline operator const float *( void ) const { return &x; };
00325     union 
00326     {
00327         struct { float m_fX, m_fY, m_fZ; };
00328         struct { float x, y, z; };
00329         float m_aCoors[3];
00330     };
00331 };
00332 
00333 
00334 
00336 class MBDLL_DECL DblVector
00337 {
00338 public:
00340     inline DblVector( void ) throw() { x = y = z = 0.0; };
00341 
00342 
00343     Vector Vec() const {
00344         return Vector((float)x, (float)y, (float)z);
00345     }
00346 
00348     inline DblVector( double fX, double  fY, double  fZ = 0.0 ) throw() 
00349     { x = fX; y = fY; z = fZ; };
00350 
00352     inline DblVector( const DblVector &vVector ) throw() 
00353     { x = vVector.x; y = vVector.y; z = vVector.z; };
00354 
00356     inline DblVector( const Vector &vVector ) throw() 
00357     { x = vVector.x; y = vVector.y; z = vVector.z; };
00358 
00362     inline DblVector( const char *pVector ) throw()
00363     { x = pVector[0]*(1.0/127.0); y = pVector[1]*(1.0/127.0); z = pVector[2]*(1.0/127.0); };
00364 
00367     inline DblVector( const short *pVector ) throw() 
00368     { x = pVector[0]*(1.0/32767.0); y = pVector[1]*(1.0/32767.0); z = pVector[2]*(1.0/32767.0); };
00369 
00371     inline DblVector &Set( double fX, double fY, double fZ ) throw() 
00372     { x = fX; y = fY; z = fZ; return *this; };
00373 
00375     inline DblVector &Clear( void ) throw () 
00376     { return Set( 0.0, 0.0, 0.0 ); };
00377 
00381     DblVector &Normalize( void ) throw();
00382 
00384     DblVector Normalized( void ) const throw();
00385 
00391     DblVector &MakeOrthogonal( const DblVector &vBase );
00392 
00398     inline DblVector &SetLength( double fLength ) 
00399     { Normalize(); operator *=( fLength ); return *this; };
00400 
00401     
00403     inline double LengthSquare( void ) const { return x*x+y*y+z*z; };
00404     
00406     double Length() const throw();
00407 
00409     double Length2D() const throw();
00410 
00413     inline double DistanceFrom( const DblVector &v ) const { return operator -(v).Length(); };
00414 
00417     double DistanceFromLine( const DblVector &v0, const DblVector &v1 ) const;
00418 
00421     double DistanceFromSegment( const DblVector &v0, const DblVector &v1 ) const;
00422 
00423     
00425     double AngleCos( const DblVector &v1 ) const throw() 
00426     { return DblVector(*this).Normalize()|DblVector(v1).Normalize(); };
00427     
00430     inline DblVector Minimum( const DblVector &o ) 
00431     { return DblVector( Min(x, o.x), Min(y, o.y), Min(z, o.z) ); };
00432 
00435     inline DblVector Maximum( const DblVector &o ) 
00436     { return DblVector( Max(x, o.x), Max(y, o.y), Max(z, o.z) ); };
00437 
00439     inline DblVector operator -( void ) const throw() 
00440     { return DblVector( -x, -y, -z ); };
00441 
00444     inline DblVector operator +( double f ) const throw() 
00445     { return DblVector( x+f, y+f, z+f ); };
00446 
00448     inline DblVector operator +( const DblVector &v ) const throw() 
00449     { return DblVector( x+v.x, y+v.y, z+v.z ); };
00450 
00452     inline DblVector operator -( const DblVector &v ) const throw() 
00453     { return DblVector( x-v.x, y-v.y, z-v.z ); };
00454 
00456     inline DblVector operator *( const DblVector &v ) const throw() 
00457     { return DblVector( x*v.x, y*v.y, z*v.z ); };
00458 
00460     inline DblVector operator *( double f ) const throw() 
00461     { return DblVector( x*f, y*f, z*f ); };
00462     
00464     inline DblVector operator /( const DblVector &v ) const throw() 
00465     { return DblVector( x/v.x, y/v.y, z/v.z ); };
00466 
00468     inline DblVector operator /( double f ) const throw() 
00469     { return operator *( 1.0/f ); };
00470 
00472     inline DblVector operator *( int i ) const throw() 
00473     { return operator *( double(i) ); };
00474 
00476     inline DblVector operator /( int i ) const throw() 
00477     { return operator /( double(i) ); };
00478 
00480     inline DblVector operator /( unsigned int i ) const throw() 
00481     { return operator /( double(i) ); };
00482 
00484     inline double operator |( const DblVector &v ) const throw() 
00485     { return x*v.x+y*v.y+z*v.z; };
00486 
00488     DblVector operator &( const DblVector &v ) const
00489     {
00490         DblVector vR;
00491         vR.m_fX = m_fY*v.m_fZ-m_fZ*v.m_fY;
00492         vR.m_fY = m_fZ*v.m_fX-m_fX*v.m_fZ;
00493         vR.m_fZ = m_fX*v.m_fY-m_fY*v.m_fX;
00494         return vR;
00495     };
00496 
00499     inline bool operator ==( const DblVector &v ) const throw() 
00500     { return x == v.x && y == v.y && z == v.z; };
00501 
00503     inline bool operator !=( const DblVector &v ) const throw() 
00504     { return !operator ==( v ); };
00505 
00507     inline operator bool( void ) const throw() { return x || y || z; };
00508     
00510     inline bool operator !( void ) const throw() { return !operator bool(); };
00511 
00513     inline DblVector &operator =( const DblVector &v ) 
00514     { x = v.x; y = v.y; z = v.z; return *this; };
00515 
00517     inline DblVector &operator <<( const DblVector &v ) 
00518     { x = v.x; y = v.y; z = v.z; return *this; };
00519 
00522     inline DblVector &operator -=( const DblVector &v ) throw() 
00523     { x-=v.x; y-=v.y; z-=v.z; return *this; };
00524     
00526     inline DblVector &operator +=( const DblVector &v ) throw() 
00527         { x+=v.x; y+=v.y; z+=v.z; return *this; };
00528 
00531     inline DblVector &operator *=( double f ) { x *= f; y *= f; z *= f; return *this; };
00532 
00535     inline DblVector &operator *=( const DblVector &v ) 
00536         { x *= v.x; y *= v.y; z *= v.z; return *this; };
00537 
00539     inline DblVector &operator /=( double f ) { return operator *=( 1.0/f ); };
00540 
00542     inline double &operator [] (
00543         int i   
00544         ) throw() { return m_aCoors[i]; };
00545 
00547     inline double &operator [](
00548         unsigned int i  
00549         ) throw() { return m_aCoors[i]; };
00550         
00552     inline operator const double *( void ) const { return &x; };
00553     union 
00554     {
00555         struct { double m_fX, m_fY, m_fZ; };
00556         struct { double x, y, z; };
00557         double m_aCoors[3];
00558     };
00559 };
00560 
00561 
00563 inline MBDLL_DECL Vector operator *( float f, const Vector &v ) throw() 
00564 { return v*f; };
00565 
00567 inline MBDLL_DECL Vector operator *( int i, const Vector &v ) throw() 
00568 { return float(i)*v; };
00569 
00571 inline MBDLL_DECL DblVector operator *( double f, const DblVector &v ) throw() 
00572 { return v*f; };
00573 
00575 inline MBDLL_DECL DblVector operator *( int i, const DblVector &v ) throw() 
00576 { return double(i)*v; };
00577 
00578 typedef AttributeInstance<Vector> avector;
00579 
00580 MBDLL_DECL AttributeWidget *CreateNewVectorWidget( QWidget *pParent, 
00581                                                    int      iWidth, 
00582                                                    avector *pAttribute );
00583 
00584 template <> inline
00585 AttributeWidget *avector::CreateEditorWidget( QWidget *pParent, int iWidth ) 
00586 { return CreateNewVectorWidget( pParent, iWidth, this ); };
00587 
00588 template <> inline
00589 QString avector::AsString( unsigned int /*options*/ ) const 
00590 { return QString("%1 %2 %3").arg(m_cValue.x).arg(m_cValue.y).arg(m_cValue.z); };
00591 
00592 template <> inline
00593 void avector::SetFromString( const QString &s, unsigned int /*options*/ ) 
00594 { m_cValue.x = s.section( ' ', 0,0 ).toFloat();
00595   m_cValue.y = s.section( ' ', 1,1 ).toFloat(); 
00596   m_cValue.z = s.section( ' ', 2,2 ).toFloat(); };
00597 
00598 template <> inline
00599 
00600 Attribute::AttributeType avector::Type( void ) const { return typeVector; };
00601 
00602 
00604 class MBDLL_DECL Vector4
00605 {
00606 public:
00607     Vector4() { x=y=z=w=0.0f; }
00608 
00609     Vector4(float X, float Y, float Z, float W) {x=X; y=Y; z=Z; w=W;}
00610 
00611     inline bool operator ==( const Vector4 &v ) const throw() 
00612     { return x == v.x && y == v.y && z == v.z; };
00613 
00614     inline bool operator !=( const Vector4 &v ) const throw() 
00615     { return !operator ==( v ); };
00616 
00617     union {
00618         struct {
00619             float x, y, z, w;
00620         };
00621         double  m_dAlignDummy;    // try for 8 byte alignment.
00622 #if !defined  OS_32BIT 
00623         __m128  m_VecSSE;         // get 16 byte alignment.
00624 #endif
00625     };
00626 };
00627 
00628 
00629 
00630 typedef AttributeInstance<Vector4> avector4;
00631 
00632 MBDLL_DECL AttributeWidget *CreateNewVector4Widget( QWidget *pParent, int iWidth, avector4 *pAttribute );
00633 
00634 template <> inline
00635 
00636 AttributeWidget *avector4::CreateEditorWidget( QWidget *pParent, int iWidth ) 
00637 { return CreateNewVector4Widget( pParent, iWidth, this ); };
00638 
00639 template <> inline
00640 QString avector4::AsString( unsigned int /*options*/ ) const 
00641 { return QString("%1 %2 %3 %4").arg(m_cValue.x).arg(m_cValue.y).arg(m_cValue.z).arg(m_cValue.w); };
00642 
00643 template <> inline
00644 void avector4::SetFromString( const QString &s, unsigned int /*options*/ ) 
00645 { m_cValue.x = s.section( ' ', 0, 0 ).toFloat(); 
00646   m_cValue.y = s.section( ' ', 1, 1 ).toFloat(); 
00647   m_cValue.z = s.section( ' ', 2, 2 ).toFloat(); 
00648   m_cValue.w = s.section( ' ', 3, 3 ).toFloat();};
00649 
00650 template <> inline
00651 Attribute::AttributeType avector4::Type( void ) const { return typeVector; };
00652 
00653 
00654 
00658 
00659 class MBDLL_DECL Color
00660 
00661 {
00662 public:
00663 
00666     Color( float fRed = 1.0f, float fGreen = 1.0f, float fBlue = 1.0f, float fAlpha = 1.0f ) 
00667     { m_fRed = fRed; m_fGreen = fGreen; m_fBlue = fBlue, m_fAlpha = fAlpha; };
00668 
00669 #ifdef QT_VERSION
00670 
00671     Color( const QColor &c ) 
00672     { r = c.redF(); 
00673       g = c.greenF(); 
00674       b = c.blueF(); 
00675       a = 1.0f; };
00676 
00677 #endif
00678 
00680     inline void Set( float fRed, float fGreen, float fBlue, float fAlpha = 1.0f ) 
00681     { r = fRed; g = fGreen; b = fBlue; a = fAlpha; };
00682 
00683 
00686     inline operator const float *( void ) const { return &m_fRed; };
00687 
00689     inline float &operator[]( unsigned int iChannel ) 
00690     { MB_ASSERT( iChannel < 4 ); return m_fData[iChannel]; };
00691 
00694     inline operator unsigned int( void ) const 
00695         { return (unsigned int)(0xff*m_fRed)+(((unsigned int)(0xff*m_fGreen))<<8)+
00696             (((unsigned int)(0xff*m_fBlue))<<16)+(((unsigned int)(0xff*m_fAlpha))<<24); };
00697 
00698 
00701     Color &operator *=(const float f) { r*=f; g*=f; b*=f; return *this; };
00702 
00704     Color operator *( float f ) const 
00705         { return Color( r*f, g*f, b*f, a*f ); };
00706 
00708     Color operator /( float f ) const 
00709         { return operator *( 1/f ); };
00710 
00712     Color operator *( const Color &c ) const 
00713         { return Color( r*c.r, g*c.g, b*c.b, a*c.a ); };
00714 
00717     Color &operator *=( const Color &c ) 
00718     { r *= c.r; g *= c.g; b *= c.b; a *= c.a; return *this; };
00719 
00721     Color operator +( const Color &c ) const 
00722         { return Color( r+c.r, g+c.g, b+c.b, a+c.a ); };
00723 
00725     Color operator -( const Color &c ) const 
00726         { return Color( r-c.r, g-c.g, b-c.b, a-c.a ); };
00727 
00729     Color &operator +=( const Color &c ) 
00730     { r += c.r; g += c.g; b += c.b; a += c.a; return *this; };
00731 
00733     bool operator ==( const Color &c ) const 
00734         { return r == c.r && g == c.g && b == c.b && a == c.a; };
00735 
00737     inline bool operator !=( const Color &c ) const { return !operator ==( c ); };
00738     
00739 
00747     Color Mix( const Color &c, float f ) const
00748     { return Color( r*f+c.r*(1-f), g*f+c.g*(1-f), b*f+c.b*(1-f), a*f+c.a*(1-f) ); };
00749 
00751     inline float Luminance() const 
00752         { return 0.299f * r + 0.587f * g + 0.114f * b; }
00753 
00754     
00755 
00756 #ifdef QT_VERSION
00757     operator QColor( void ) const { QColor col; col.setRgbF( r, g, b ); return col; };
00758     QColor ToQColor( void ) const { QColor col; col.setRgbF( r, g, b ); return col; };
00759 #endif
00760 
00761     union {
00762         struct { float m_fRed, m_fGreen, m_fBlue, m_fAlpha; };
00763         struct { float r, g, b, a; };
00764         float  m_fData[4];
00765 
00766         double m_dAlignDummy;   // try for 8 byte alignment.
00767 #if !defined  OS_32BIT 
00768         __m128 m_vAlignDummy;   // try for 16 byte alignment....
00769 #endif
00770     };
00771 
00772     static Color black;
00773     static Color white;
00774     static Color red;
00775     static Color green;
00776     static Color blue;
00777     static Color gray;
00778 };
00779 
00780 
00781 
00783 inline Color operator *( float f, const Color &c ) 
00784 { return Color( c.r*f, c.g*f, c.b*f, c.a*f ); };
00785 
00786 
00787 typedef AttributeInstance<Color> acolor;
00788 
00789 MBDLL_DECL AttributeWidget *CreateNewColorWidget( QWidget *pParent, int iWidth, acolor *pAttribute );
00790 
00791 template <> inline
00792 AttributeWidget *acolor::CreateEditorWidget( QWidget *pParent, int iWidth ) 
00793 { return CreateNewColorWidget( pParent, iWidth, this ); };
00794 
00795 template <> inline
00796 Attribute::AttributeType acolor::Type( void ) const { return typeColor; };
00797 
00798 template <> inline
00799 QString acolor::AsString( unsigned int /*options*/ ) 
00800 const { return QString("%1 %2 %3 %4").arg(m_cValue.r).arg(m_cValue.g).arg(m_cValue.b).arg(m_cValue.a); };
00801 
00802 template <> inline
00803 
00804 void acolor::SetFromString( const QString &s, unsigned int /*options*/ ) {
00805     m_cValue.r = s.section( ' ', 0, 0 ).toFloat(); 
00806     m_cValue.g = s.section( ' ', 1, 1 ).toFloat(); 
00807     m_cValue.b = s.section( ' ', 2, 2 ).toFloat(); 
00808     m_cValue.a = s.section( ' ', 3, 3 ).toFloat();
00809 };
00810 
00811 
00812 
00816 class MBDLL_DECL AxisAlignedBoundingBox
00817 {
00818 public:
00820     AxisAlignedBoundingBox( void ) { Reset(); };
00821 
00823     AxisAlignedBoundingBox( const Vector &vStart, const Vector &vEnd ) :
00824         m_vStart( vStart ),
00825         m_vEnd( vEnd ) {};
00826 
00829     AxisAlignedBoundingBox( const Vector &vCenter, float fSize )
00830     {
00831         Vector v( fSize, fSize, fSize );
00832         m_vStart = vCenter-v;
00833         m_vEnd   = vCenter+v;
00834     };
00835 
00837     AxisAlignedBoundingBox( const AxisAlignedBoundingBox &cA ) :
00838     m_vStart( cA.m_vStart ),
00839     m_vEnd( cA.m_vEnd ) {};
00840 
00842     AxisAlignedBoundingBox &operator =( const AxisAlignedBoundingBox &cBB )
00843     {
00844         m_vStart = cBB.m_vStart;
00845         m_vEnd = cBB.m_vEnd;
00846         return *this;
00847     };
00848 
00850     AxisAlignedBoundingBox &operator +=( const AxisAlignedBoundingBox &cBB )
00851     {
00852         for ( int i = 0; i < 8; i++ ) Extend( cBB[i] );
00853         return *this;
00854     };
00855 
00857     bool operator ==( const AxisAlignedBoundingBox &cBB ) const
00858     {
00859         return m_vStart == cBB.m_vStart && m_vEnd == cBB.m_vEnd;
00860     };
00861 
00863     void Reset( void )
00864     {
00865         m_vStart.Set( 0, 0, 0 );
00866         m_vEnd.Set( -1, -1, -1 );
00867     };
00868 
00870     void Serialize( Stream &s );
00871 
00872 
00874     bool operator !=( const AxisAlignedBoundingBox &cBox ) const 
00875         { return !(operator ==(cBox)); };
00876 
00877 
00879     void Extend( const Vector & );
00880 
00882     void Extend( const AxisAlignedBoundingBox &bb )
00883     {
00884         if ( !bb.IsEmpty() ) {
00885             Extend( bb.m_vStart );
00886             Extend( bb.m_vEnd );
00887         };
00888     };
00889 
00890     
00895     void Transform( const class Matrix &mMatrix );
00896 
00898     Vector operator []( int iCornerIndex ) const;
00899 
00901     float Size( void ) const { return Max( Max( XSize(), YSize() ), ZSize() ); };
00902 
00904     float XSize( void ) const { return m_vEnd.m_fX-m_vStart.m_fX; };
00905 
00907     float YSize( void ) const { return m_vEnd.m_fY-m_vStart.m_fY; };
00908 
00910     float ZSize( void ) const { return m_vEnd.m_fZ-m_vStart.m_fZ; };
00911 
00913     float Volume( void ) const { return XSize()*YSize()*ZSize(); };
00914 
00916     Vector Center( void ) const { return (m_vStart+m_vEnd)*0.5f; };
00917 
00919     bool IsPartOf( const AxisAlignedBoundingBox &cBB ) const
00920     {
00921         return (
00922             m_vStart.m_fX >= cBB.m_vStart.m_fX && m_vEnd.m_fX <= cBB.m_vEnd.m_fX &&
00923             m_vStart.m_fY >= cBB.m_vStart.m_fY && m_vEnd.m_fY <= cBB.m_vEnd.m_fY &&
00924             m_vStart.m_fZ >= cBB.m_vStart.m_fZ && m_vEnd.m_fZ <= cBB.m_vEnd.m_fZ );
00925     };
00926 
00928     bool IsTouching( const AxisAlignedBoundingBox &cBB ) const
00929     {
00930         return (
00931             m_vStart.m_fX < cBB.m_vEnd.m_fX && m_vEnd.m_fX > cBB.m_vStart.m_fX &&
00932             m_vStart.m_fY < cBB.m_vEnd.m_fY && m_vEnd.m_fY > cBB.m_vStart.m_fY &&
00933             m_vStart.m_fZ < cBB.m_vEnd.m_fZ && m_vEnd.m_fZ > cBB.m_vStart.m_fZ );
00934     };
00935     
00936 
00943     bool IsTouching(
00944         const Vector &vStart,   
00945         const Vector &vEnd,     
00946         float &fPlace           
00947 
00948         ) const;
00949 
00951     bool IsContaining( const Vector &cV ) const
00952     {
00953         return (
00954             m_vStart.m_fX <= cV.m_fX && m_vEnd.m_fX >= cV.m_fX &&
00955             m_vStart.m_fY <= cV.m_fY && m_vEnd.m_fY >= cV.m_fY &&
00956             m_vStart.m_fZ <= cV.m_fZ && m_vEnd.m_fZ >= cV.m_fZ );
00957     };
00958     
00959 
00961     bool IsContaining( const AxisAlignedBoundingBox &b ) const 
00962         { return IsContaining( b.m_vStart ) && IsContaining( b.m_vEnd ); };
00963     
00964 
00967     bool IsEmpty( void ) const { return m_vStart.x > m_vEnd.x; };
00968 
00970     AxisAlignedBoundingBox operator *( float fFactor )
00971     {
00972         return AxisAlignedBoundingBox( m_vStart*fFactor, m_vEnd*fFactor );
00973     };
00974 
00975     Vector m_vStart;
00976     Vector m_vEnd;
00977 };
00978 
00979 
00980 
00984 class MBDLL_DECL Base
00985 {
00986 
00987 public:
00989     Base( void );
00990 
00992     Base( const Vector &vA, const Vector &vB, const Vector &vC );
00993 
00995     bool operator !=( const Base &o ) const { return a != o.a || b != o.b || c != o.c; };
00996 
00998     void Derive(
00999         unsigned int iIndex,    
01000         bool bRightHand = true  
01001         );
01002 
01003 
01005 
01006     void Orthogonalize(
01007         unsigned int iIndex,        
01008         unsigned int iSource = -1   
01009 
01010         );
01011 
01013     void Normalize( void ) { a.Normalize(); b.Normalize(); c.Normalize(); };
01014 
01015 
01017     Vector TransformFrom( const Vector &cSource ) const;
01018 
01020     Vector TransformTo( const Vector &cSource ) const;
01021 
01023     Base operator *( float fFactor ) const;
01024 
01026     Base operator +( const Base &bOther ) const;
01027 
01029     Base operator -( const Base &bOther ) const;
01030     
01032     Vector& Axis(
01033         unsigned int iIndex 
01034         );
01035 
01036 
01038     const Vector& Axis(
01039         unsigned int iIndex 
01040         ) const;
01041 
01042     Vector a, b, c;
01043 };
01044 
01045 
01046 
01048 class SubSpace : public Node
01049 
01050 {
01051     DECLARE_CLASS;
01052 
01053 public:
01054     virtual void Initialize( const class Mesh *pMesh, Store<unsigned int> aFaceList, float fAClip, float fBClip );
01055     virtual bool IsOutside( const Vector &vPos, float fRange ) const;
01056     virtual AxisAlignedBoundingBox BoundingBox( void ) const;
01057 };
01058 
01059 
01060 
01062 class MBDLL_DECL Matrix
01063 {
01064 public:
01065 
01067     Matrix( void ) {};
01068 
01069     Matrix( const Matrix &m ) :
01070         _11(m._11), _12(m._12), _13(m._13), _14(m._14), 
01071         _21(m._21), _22(m._22), _23(m._23), _24(m._24), 
01072         _31(m._31), _32(m._32), _33(m._33), _34(m._34), 
01073         _41(m._41), _42(m._42), _43(m._43), _44(m._44) {};
01074 
01076     Matrix( float f11, float f12, float f13, float f14,
01077             float f21, float f22, float f23, float f24,
01078             float f31, float f32, float f33, float f34,
01079             float f41, float f42, float f43, float f44 ) :
01080         _11(f11), _12(f12), _13(f13), _14(f14), 
01081         _21(f21), _22(f22), _23(f23), _24(f24), 
01082         _31(f31), _32(f32), _33(f33), _34(f34), 
01083         _41(f41), _42(f42), _43(f43), _44(f44) {};
01084 
01086     Matrix( const double *pMatrix );
01087 
01089     float &operator()( int iRow, int iColumn ) 
01090     { 
01091         return m_fData[iRow*4+iColumn]; 
01092     };
01093     
01095     float operator()( int iRow, int iColumn ) const 
01096     { 
01097         return m_fData[iRow*4+iColumn]; 
01098     };
01099     
01102     operator const float *( void ) const { return m_fData; };
01103     
01106     operator float *( void ) { return m_fData; };
01107 
01109     Matrix &SetIdentity( void );
01110 
01112     bool IsIdentity( void ) const;
01113 
01115     bool IsRigid( void ) const;
01116     
01118     Matrix &operator *=( float );
01119 
01121     Matrix operator *( const Matrix &m ) const;
01122 
01124     Matrix operator *( float ) const;
01125 
01127     Matrix operator +( const Matrix & ) const;
01128 
01130     Matrix &operator *=( const Matrix &m );
01131 
01133     bool operator ==( const Matrix &m ) const;
01134 
01137     void SetRow( int iRowIndex, const Vector &vValue );
01138 
01140     Matrix &Transpose( void );
01141 
01143     Matrix &Invert( void );
01144 
01147     Matrix &FromEuler( const Vector &vAngles );
01148 
01150     Vector ToEuler( void ) const;
01151     
01153     Matrix &FromAxisAngle( const Vector &vAxis, float fAngle );
01154 
01158     Vector Transform(
01159         const Vector &v,    
01160         float fW = 1.0f     
01161         ) const
01162     {
01163         return Vector( 
01164             v.m_fX*_11+v.m_fY*_21+v.m_fZ*_31+fW*_41,
01165             v.m_fX*_12+v.m_fY*_22+v.m_fZ*_32+fW*_42,
01166             v.m_fX*_13+v.m_fY*_23+v.m_fZ*_33+fW*_43 );
01167     };
01168 
01173     Vector ProjectedTransform(
01174         const Vector &v,    
01175         float fW = 1.0f     
01176         ) const
01177     {
01178         float fRW = v.m_fX*_14+v.m_fY*_24+v.m_fZ*_34+fW*_44;
01179         return (1/fRW)*Vector( 
01180             v.m_fX*_11+v.m_fY*_21+v.m_fZ*_31+fW*_41,
01181             v.m_fX*_12+v.m_fY*_22+v.m_fZ*_32+fW*_42,
01182             v.m_fX*_13+v.m_fY*_23+v.m_fZ*_33+fW*_43 );
01183     };
01184 
01185 
01191     Vector Transform(
01192         const Vector &v,    
01193         float fW,           
01194         float &fRW          
01195         ) const
01196     {
01197         fRW = v.m_fX*_14+v.m_fY*_24+v.m_fZ*_34+fW*_44;
01198         return Vector( 
01199             v.m_fX*_11+v.m_fY*_21+v.m_fZ*_31+fW*_41,
01200             v.m_fX*_12+v.m_fY*_22+v.m_fZ*_32+fW*_42,
01201             v.m_fX*_13+v.m_fY*_23+v.m_fZ*_33+fW*_43 );
01202     };
01203 
01208     Vector TransformDirection( const Vector &v ) const
01209     {
01210         return Vector( 
01211             v.m_fX*_11+v.m_fY*_21+v.m_fZ*_31,
01212             v.m_fX*_12+v.m_fY*_22+v.m_fZ*_32,
01213             v.m_fX*_13+v.m_fY*_23+v.m_fZ*_33 );
01214     };
01215 
01216     union {
01217         float  m_fData[16];
01218         struct {
01219             float _11, _12, _13, _14;
01220             float _21, _22, _23, _24;
01221             float _31, _32, _33, _34;
01222             float _41, _42, _43, _44;
01223         };
01224         double  m_fAlignDummy[8];   // at least get it 8 byte aligned.
01225 #if !defined  OS_32BIT 
01226         __m128  m_vAlignDummy[4];   // try for 16 byte....
01227 #endif
01228     };
01229 };
01231 typedef AttributeInstance<Matrix> amatrix;
01239 class MBDLL_DECL Quaternion
01240 {
01241 public:
01243     inline Quaternion( void ) { SetIdentity(); };
01244 
01246     inline Quaternion( 
01247         float fW, 
01248         const Vector &vXYZ 
01249         )
01250     { m_fW = fW; m_fX = vXYZ.x; m_fY = vXYZ.y; m_fZ = vXYZ.z; };
01251 
01253     inline Quaternion( float fW, float fX, float fY, float fZ )
01254     { m_fW = fW; m_fX = fX; m_fY = fY; m_fZ = fZ; };
01255 
01257     Quaternion( 
01258         const Vector &vAxis, 
01259         float fAngle 
01260         );
01261 
01263     Quaternion( const Matrix &mRotation );
01264 
01266     float LengthSquare( void ) const;
01267 
01270     float Length( void ) const;
01271 
01273     Matrix ToMatrix( void ) const;
01274 
01276     Vector Transform( 
01277         const Vector &vPoint 
01278         ) const;
01279 
01281     inline Quaternion operator *( float fMultiplier ) const
01282     { return Quaternion( m_fW*fMultiplier, m_fX*fMultiplier, m_fY*fMultiplier, m_fZ*fMultiplier ); };
01283 
01285     inline Quaternion &operator *=( float fMultiplier ) 
01286     { *this = operator *( fMultiplier ); return *this; };
01287 
01289     inline Quaternion operator -( void ) const 
01290     { return Quaternion( -m_fW, -m_fX, -m_fY, -m_fZ ); };
01291 
01293     Quaternion operator +( const Quaternion &vAddition ) const;
01294 
01296     Quaternion &operator +=( const Quaternion &vAddition );
01297 
01299     Quaternion operator -( const Quaternion &vAddition ) const;
01300 
01302     Quaternion &operator -=( const Quaternion &vAddition );
01303 
01306     Quaternion operator *( const Quaternion &vMultiplier ) const;
01307 
01309     Quaternion &operator *=( const Quaternion &vMultiplier );
01310 
01312     float operator |( const Quaternion &vMultiplier ) const;
01313 
01316     Quaternion &Normalize( void );
01317 
01319     Quaternion &Conjugate( void );
01320 
01323     Quaternion &Invert( void );
01324 
01326     Quaternion Slerp( const Quaternion &vTarget, float fWeight ) const;
01327 
01329     inline void SetIdentity( void ) 
01330     { m_fW = 1.0; m_fX = m_fY = m_fZ = 0.0f; };
01331 
01333     void SetZero( void ) { m_fW = m_fX = m_fY = m_fZ = 0.0f; };
01334 
01336     float operator []( 
01337         int iIndex 
01338         ) const;
01339 
01344     float m_fW, m_fX, m_fY, m_fZ;
01345 };
01346 
01354 class MBDLL_DECL DualQuaternion
01355 {
01356 public:
01358     inline DualQuaternion( void ) { SetIdentity(); };
01359 
01361     inline DualQuaternion( 
01362         const Quaternion &vReal, 
01363         const Quaternion &vDual  
01364         )
01365     { m_vReal = vReal; m_vDual = vDual; };
01366 
01369     DualQuaternion( 
01370         const Vector &vPivot, 
01371         const Vector &vAxis, 
01372         float fAngle 
01373         );
01374 
01376     DualQuaternion(
01377         float fAngle, 
01378         float fPitch, 
01379         const Vector &vDirection,
01380         const Vector &vMoment 
01381         );
01382 
01384     DualQuaternion( 
01385         const Vector &vTranslation, 
01386         const Quaternion &vRotation 
01387         );
01388 
01390     DualQuaternion( const Matrix &mRigid );
01391 
01393     Matrix ToMatrix( void ) const;
01394 
01396     Vector Translation( void ) const;
01397 
01399     Vector Transform( const Vector &vPoint ) const;
01400 
01402     DualQuaternion operator +( const DualQuaternion &vAddition ) const;
01403 
01405     DualQuaternion &operator +=( const DualQuaternion &vAddition );
01406 
01408     DualQuaternion operator -( const DualQuaternion &vAddition ) const;
01409 
01411     DualQuaternion &operator -=( const DualQuaternion &vAddition );
01412 
01415     DualQuaternion operator *( const DualQuaternion &vMultiplier ) const;
01416 
01418     DualQuaternion &operator *=( const DualQuaternion &vMultiplier );
01419 
01421     DualQuaternion operator *( float fMultiplier ) const;
01422 
01425     DualQuaternion &Normalize( void );
01426 
01428     void ToScrew( float &fAngle, float &fPitch, Vector &vDirection, Vector &vMoment ) const;
01429 
01431     DualQuaternion &Power( float fExponent );
01432 
01435     DualQuaternion Slerp( const DualQuaternion &vTarget, float fWeight ) const;
01436 
01438     DualQuaternion &Conjugate( void );
01439 
01441     DualQuaternion &DualConjugate( void );
01442 
01445     inline DualQuaternion &DoubleConjugate( void ) { Conjugate(); DualConjugate(); return *this; };
01446 
01449     DualQuaternion &Invert( void );
01450 
01452     void SetIdentity( void ) { m_vReal.SetIdentity(); m_vDual.SetZero(); };
01453 
01455     float operator []( 
01456         int iIndex 
01457         ) const;
01458 
01464     Quaternion m_vReal, m_vDual;
01465 
01466 private:
01469     DualQuaternion( const Vector &vPoint );
01470 
01471 };
01472 
01474 class MBDLL_DECL Line
01475 {
01476     Vector m_vStart, m_vEnd, m_vDirection;
01477     float m_fFactor;
01478 
01479 public:
01480 
01482     Line( const Vector &vStart, const Vector &vEnd );
01483 
01489 
01491 
01492     float RangeFrom( const Vector &vPoint );
01493 
01495     enum IntersectionResult
01496 
01497     {
01498 
01499         PARALLEL,
01500 
01501         COINCIDENT,
01502 
01503         NOT_INTERSECTING,
01504 
01505         INTERSECTING
01506 
01507     };
01508 
01509 
01510 
01512 
01514 
01516 
01517     IntersectionResult Intersection2D( const Line& cOther, Vector &vResult, bool bSegmentOnly = false );
01518 
01519 };
01520 
01521 
01522 
01523 
01524 
01531 
01533 
01537 
01538 class MBDLL_DECL Selector : virtual public Node
01539 {
01540     DECLARE_CLASS;
01541 
01542 public:
01543     enum EState
01544     {
01545         eInside,
01546         eOutside,
01547         eTouching
01548     };
01549 
01551     virtual EState IsTouchedBy( const AxisAlignedBoundingBox &cArea ) const;
01552 };
01553 
01554 
01555 inline MBDLL_DECL Vector operator *( const Vector &v, const Matrix &m )
01556 {
01557     return Vector( 
01558         v.m_fX*m._11+v.m_fY*m._21+v.m_fZ*m._31+m._41,
01559         v.m_fX*m._12+v.m_fY*m._22+v.m_fZ*m._32+m._42,
01560         v.m_fX*m._13+v.m_fY*m._23+v.m_fZ*m._33+m._43 );
01561 };
01562 
01563 inline MBDLL_DECL Vector operator *( const Matrix &m, const Vector &v ) 
01564 {
01565     return Vector( 
01566         v.m_fX*m._11+v.m_fY*m._12+v.m_fZ*m._13+m._14,
01567         v.m_fX*m._21+v.m_fY*m._22+v.m_fZ*m._23+m._24,
01568         v.m_fX*m._31+v.m_fY*m._32+v.m_fZ*m._33+m._34 );
01569 };
01570 
01571 
01576 class CheckableFloat
01577 {
01578 public:
01579     CheckableFloat( void ) { m_bState = true; m_fValue = 0.0f; };
01580     CheckableFloat( bool bState, float fValue ) { m_bState = bState; m_fValue = fValue; };
01581     
01583     void SetValue( float f ) { m_fValue = f; };
01584     
01586     float Value( void ) const { return m_fValue; };
01587     
01589     void SetState( bool b ) { m_bState = b; };
01590     
01592     bool State( void ) const { return m_bState; };
01593     
01594     inline bool operator ==( const CheckableFloat &cf ) const throw() { return State() == cf.State() && Value() == cf.Value(); };
01595     inline bool operator !=( const CheckableFloat &cf ) const throw() { return !operator ==( cf ); };
01596     inline CheckableFloat &operator =( const CheckableFloat &cf ) { m_bState = cf.m_bState; m_fValue = cf.m_fValue; return *this; };
01597 
01598     void Serialize( Stream &s )
01599     {
01600         s == m_bState == m_fValue;
01601     };
01602 
01603 
01604 protected:
01605     bool m_bState;
01606     float m_fValue;
01607 };
01608 
01609 MBDLL_DECL AttributeWidget *CreateNewCheckableFloatWidget( QWidget *pParent, int iWidth, class AttributeCheckableFloat *pAttribute );
01610 
01611 class AttributeCheckableFloat : public AttributeInstance<CheckableFloat>
01612 {
01613 public:
01614     AttributeCheckableFloat( Node *pOwner = 0, const QString &sID = "", const QString &sValueName = "" ) : AttributeInstance<CheckableFloat>( pOwner, sID )
01615         { m_iSize = sizeof(CheckableFloat); m_sValueName = sValueName; };
01616     void SetValueName( const QString &sValueName ) { m_sValueName = sValueName; };
01617     QString ValueName( void ) const { return m_sValueName; };
01618 
01619     Attribute::AttributeType Type( void ) const { return typeUnknown; };
01620     AttributeWidget *CreateEditorWidget( QWidget *pParent, int iWidth ) { return CreateNewCheckableFloatWidget( pParent, iWidth, (AttributeCheckableFloat *)this ); };
01621     QString AsString( unsigned int /*options*/ ) const { return QString("%1 %2").arg(m_cValue.State() ? "true" : "false").arg(m_cValue.Value()); };
01622     void SetFromString( const QString &s, unsigned int /*options*/ = asStringInternal )
01623     {
01624         m_cValue.SetState( s.section( ' ', 0, 0 ) == "true" ? true : false );
01625         m_cValue.SetValue( s.section( ' ', 1, 1 ).toFloat() );
01626     };
01627 
01628 protected:
01629     QString m_sValueName;
01630 };
01631 
01632 typedef AttributeCheckableFloat acheckablefloat;
01633 // data structure, references: StampConfiguration and CheckableFloat.
01634 struct MBDLL_DECL CheckableFloatArray  
01635 {
01636 
01637     CheckableFloatArray()
01638     {
01639         m_iSize = 2;
01640         m_aValue[0] = 0; m_aValue[1] = 1;
01641         m_bComplementary = false;
01642     }
01643 
01645     void SetState( bool b ) { s_bActive = b; }; 
01647     bool State( void ) const { return s_bActive; };
01648 
01649     float Value(unsigned int i) const { MB_ASSERT(i < m_iSize); return m_aValue[i]; } 
01650     void SetValue(int i, float v) { MB_ASSERT(i < m_iSize); m_aValue[i] = v; }
01651 
01652     void AddElement(int i, QString sLabel, float fMin, float fMax, float fValue)
01653     {
01654         MB_ASSERT(i < m_iSize); 
01655         MB_ASSERT(fValue > fMin && fValue < fMax); 
01656         m_aLabel[i] = sLabel;
01657         m_aMin[i] = fMin;
01658         m_aMax[i] = fMax;
01659         m_aValue[i] = fValue; 
01660     }
01661     
01662     unsigned int Size() const { return m_iSize; }
01663 
01666     bool IsComplementary() const { return m_bComplementary; }
01667     void SetComplementary(bool b) { m_bComplementary = b; }
01668 
01669     inline bool operator ==( const CheckableFloatArray & ) const throw() { return false; };
01670     inline bool operator !=( const CheckableFloatArray &v ) const throw() { return !operator ==( v ); };
01671 
01672     void Serialize( Stream &s )
01673     {
01674         s == s_bActive == m_iSize == m_bComplementary;
01675         for (unsigned int i = 0; i < m_iSize; ++i)
01676             s == m_aLabel[i] == m_aMin[i] == m_aMax[i] == m_aValue[i];
01677     };
01678 
01679     static bool s_bActive;
01680     unsigned int m_iSize;
01681     QString m_aLabel[2];
01682     float m_aMin[2];
01683     float m_aMax[2];         
01684     float m_aValue[2];  
01685     bool m_bComplementary;
01686 };
01687 
01688 
01689 MBDLL_DECL AttributeWidget *CreateNewCheckableFloatArrayWidget( QWidget *pParent, int iWidth, class AttributeCheckableFloatArray *pAttribute );
01690 
01691 class AttributeCheckableFloatArray : public AttributeInstance<CheckableFloatArray>
01692 {
01693 public:
01694     AttributeCheckableFloatArray( Node *pOwner = 0, const QString &sID = "" ) 
01695         : AttributeInstance<CheckableFloatArray>( pOwner, sID )
01696     { m_iSize = sizeof(CheckableFloat); }; 
01697 
01698     Attribute::AttributeType Type( void ) const { return typeUnknown; };
01699     AttributeWidget *CreateEditorWidget( QWidget *pParent, int iWidth ) 
01700     { 
01701         return CreateNewCheckableFloatArrayWidget( pParent, iWidth, (AttributeCheckableFloatArray *)this ); 
01702     };
01703     // the data structure of this attribute 
01704     //QString AsString( unsigned int /*options*/ ) const { return QString("%1 %2").arg(m_cValue.State() ? "true" : "false").arg(m_cValue.Value()); };
01705     //void SetFromString( const QString &s, unsigned int /*options*/ = asStringInternal )
01706     //{
01707     //  m_cValue.SetState( s.section( ' ', 0, 0 ) == "true" ? true : false );
01708     //  m_cValue.SetValue( s.section( ' ', 1, 1 ).toFloat() );
01709     //};
01710 
01711 protected:                
01712 };
01713 
01714 //-----------------------------------------------------------------------------
01718 static inline bool FloatEqual(float A, float B, const int max_ulps = 4)
01719 {   
01720     int a = *(int*)&A; // load the float bits into integers
01721     int b = *(int*)&B;
01722     // floats have a sign bit, convert to 2's compliment
01723     if (a < 0) a = 0x80000000 - a; // correctly handles 0 vs -0 and
01724     if (b < 0) b = 0x80000000 - b; // positive and negative denormals
01725     return (abs(a - b) <= max_ulps);
01726 }
01727 
01728 //-----------------------------------------------------------------------------
01732 static inline bool FloatGreaterOrEqual(float A, float B, const int max_ulps = 4)
01733 {   
01734     int a = *(int*)&A; // load the float bits into integers
01735     int b = *(int*)&B;
01736     // floats have a sign bit, convert to 2's compliment
01737     if (a < 0) a = 0x80000000 - a; // correctly handles 0 vs -0 and
01738     if (b < 0) b = 0x80000000 - b; // positive and negative denormals
01739     return (a - b) >= -max_ulps;
01740 }
01741 
01742 //-----------------------------------------------------------------------------
01746 static inline bool FloatLessOrEqual(float A, float B, const int max_ulps = 4)
01747 {   
01748     return FloatGreaterOrEqual(B, A, max_ulps);
01749 }
01750 
01751 
01752 }; // end of namespace mudbox
01753 
01754 
01755 #if defined(_MSC_VER)
01756 #pragma warning(pop)
01757 #endif