diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/public/mathlib/compressed_3d_unitvec.h | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/public/mathlib/compressed_3d_unitvec.h')
| -rw-r--r-- | mp/src/public/mathlib/compressed_3d_unitvec.h | 568 |
1 files changed, 284 insertions, 284 deletions
diff --git a/mp/src/public/mathlib/compressed_3d_unitvec.h b/mp/src/public/mathlib/compressed_3d_unitvec.h index d9f2f597..a92dba22 100644 --- a/mp/src/public/mathlib/compressed_3d_unitvec.h +++ b/mp/src/public/mathlib/compressed_3d_unitvec.h @@ -1,284 +1,284 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//
-//=============================================================================//
-#ifndef _3D_UNITVEC_H
-#define _3D_UNITVEC_H
-
-
-#define UNITVEC_DECLARE_STATICS \
- float cUnitVector::mUVAdjustment[0x2000]; \
- Vector cUnitVector::mTmpVec;
-
-// upper 3 bits
-#define SIGN_MASK 0xe000
-#define XSIGN_MASK 0x8000
-#define YSIGN_MASK 0x4000
-#define ZSIGN_MASK 0x2000
-
-// middle 6 bits - xbits
-#define TOP_MASK 0x1f80
-
-// lower 7 bits - ybits
-#define BOTTOM_MASK 0x007f
-
-// unitcomp.cpp : A Unit Vector to 16-bit word conversion
-// algorithm based on work of Rafael Baptista ([email protected])
-// Accuracy improved by O.D. ([email protected])
-// Used with Permission.
-
-// a compressed unit vector. reasonable fidelty for unit
-// vectors in a 16 bit package. Good enough for surface normals
-// we hope.
-class cUnitVector // : public c3dMathObject
-{
-public:
- cUnitVector() { mVec = 0; }
- cUnitVector( const Vector& vec )
- {
- packVector( vec );
- }
- cUnitVector( unsigned short val ) { mVec = val; }
-
- cUnitVector& operator=( const Vector& vec )
- { packVector( vec ); return *this; }
-
- operator Vector()
- {
- unpackVector( mTmpVec );
- return mTmpVec;
- }
-
- void packVector( const Vector& vec )
- {
- // convert from Vector to cUnitVector
-
- Assert( vec.IsValid());
- Vector tmp = vec;
-
- // input vector does not have to be unit length
- // Assert( tmp.length() <= 1.001f );
-
- mVec = 0;
- if ( tmp.x < 0 ) { mVec |= XSIGN_MASK; tmp.x = -tmp.x; }
- if ( tmp.y < 0 ) { mVec |= YSIGN_MASK; tmp.y = -tmp.y; }
- if ( tmp.z < 0 ) { mVec |= ZSIGN_MASK; tmp.z = -tmp.z; }
-
- // project the normal onto the plane that goes through
- // X0=(1,0,0),Y0=(0,1,0),Z0=(0,0,1).
- // on that plane we choose an (projective!) coordinate system
- // such that X0->(0,0), Y0->(126,0), Z0->(0,126),(0,0,0)->Infinity
-
- // a little slower... old pack was 4 multiplies and 2 adds.
- // This is 2 multiplies, 2 adds, and a divide....
- float w = 126.0f / ( tmp.x + tmp.y + tmp.z );
- long xbits = (long)( tmp.x * w );
- long ybits = (long)( tmp.y * w );
-
- Assert( xbits < 127 );
- Assert( xbits >= 0 );
- Assert( ybits < 127 );
- Assert( ybits >= 0 );
-
- // Now we can be sure that 0<=xp<=126, 0<=yp<=126, 0<=xp+yp<=126
- // however for the sampling we want to transform this triangle
- // into a rectangle.
- if ( xbits >= 64 )
- {
- xbits = 127 - xbits;
- ybits = 127 - ybits;
- }
-
- // now we that have xp in the range (0,127) and yp in
- // the range (0,63), we can pack all the bits together
- mVec |= ( xbits << 7 );
- mVec |= ybits;
- }
-
- void unpackVector( Vector& vec )
- {
- // if we do a straightforward backward transform
- // we will get points on the plane X0,Y0,Z0
- // however we need points on a sphere that goes through
- // these points. Therefore we need to adjust x,y,z so
- // that x^2+y^2+z^2=1 by normalizing the vector. We have
- // already precalculated the amount by which we need to
- // scale, so all we do is a table lookup and a
- // multiplication
-
- // get the x and y bits
- long xbits = (( mVec & TOP_MASK ) >> 7 );
- long ybits = ( mVec & BOTTOM_MASK );
-
- // map the numbers back to the triangle (0,0)-(0,126)-(126,0)
- if (( xbits + ybits ) >= 127 )
- {
- xbits = 127 - xbits;
- ybits = 127 - ybits;
- }
-
- // do the inverse transform and normalization
- // costs 3 extra multiplies and 2 subtracts. No big deal.
- float uvadj = mUVAdjustment[mVec & ~SIGN_MASK];
- vec.x = uvadj * (float) xbits;
- vec.y = uvadj * (float) ybits;
- vec.z = uvadj * (float)( 126 - xbits - ybits );
-
- // set all the sign bits
- if ( mVec & XSIGN_MASK ) vec.x = -vec.x;
- if ( mVec & YSIGN_MASK ) vec.y = -vec.y;
- if ( mVec & ZSIGN_MASK ) vec.z = -vec.z;
-
- Assert( vec.IsValid());
- }
-
- static void initializeStatics()
- {
- for ( int idx = 0; idx < 0x2000; idx++ )
- {
- long xbits = idx >> 7;
- long ybits = idx & BOTTOM_MASK;
-
- // map the numbers back to the triangle (0,0)-(0,127)-(127,0)
- if (( xbits + ybits ) >= 127 )
- {
- xbits = 127 - xbits;
- ybits = 127 - ybits;
- }
-
- // convert to 3D vectors
- float x = (float)xbits;
- float y = (float)ybits;
- float z = (float)( 126 - xbits - ybits );
-
- // calculate the amount of normalization required
- mUVAdjustment[idx] = 1.0f / sqrtf( y*y + z*z + x*x );
- Assert( _finite( mUVAdjustment[idx]));
-
- //cerr << mUVAdjustment[idx] << "\t";
- //if ( xbits == 0 ) cerr << "\n";
- }
- }
-
-#if 0
- void test()
- {
- #define TEST_RANGE 4
- #define TEST_RANDOM 100
- #define TEST_ANGERROR 1.0
-
- float maxError = 0;
- float avgError = 0;
- int numVecs = 0;
-
- {for ( int x = -TEST_RANGE; x < TEST_RANGE; x++ )
- {
- for ( int y = -TEST_RANGE; y < TEST_RANGE; y++ )
- {
- for ( int z = -TEST_RANGE; z < TEST_RANGE; z++ )
- {
- if (( x + y + z ) == 0 ) continue;
-
- Vector vec( (float)x, (float)y, (float)z );
- Vector vec2;
-
- vec.normalize();
- packVector( vec );
- unpackVector( vec2 );
-
- float ang = vec.dot( vec2 );
- ang = (( fabs( ang ) > 0.99999f ) ? 0 : (float)acos(ang));
-
- if (( ang > TEST_ANGERROR ) | ( !_finite( ang )))
- {
- cerr << "error: " << ang << endl;
- cerr << "orig vec: " << vec.x << ",\t"
- << vec.y << ",\t" << vec.z << "\tmVec: "
- << mVec << endl;
- cerr << "quantized vec2: " << vec2.x
- << ",\t" << vec2.y << ",\t"
- << vec2.z << endl << endl;
- }
- avgError += ang;
- numVecs++;
- if ( maxError < ang ) maxError = ang;
- }
- }
- }}
-
- for ( int w = 0; w < TEST_RANDOM; w++ )
- {
- Vector vec( genRandom(), genRandom(), genRandom());
- Vector vec2;
- vec.normalize();
-
- packVector( vec );
- unpackVector( vec2 );
-
- float ang =vec.dot( vec2 );
- ang = (( ang > 0.999f ) ? 0 : (float)acos(ang));
-
- if (( ang > TEST_ANGERROR ) | ( !_finite( ang )))
- {
- cerr << "error: " << ang << endl;
- cerr << "orig vec: " << vec.x << ",\t"
- << vec.y << ",\t" << vec.z << "\tmVec: "
- << mVec << endl;
- cerr << "quantized vec2: " << vec2.x << ",\t"
- << vec2.y << ",\t"
- << vec2.z << endl << endl;
- }
- avgError += ang;
- numVecs++;
- if ( maxError < ang ) maxError = ang;
- }
-
- { for ( int x = 0; x < 50; x++ )
- {
- Vector vec( (float)x, 25.0f, 0.0f );
- Vector vec2;
-
- vec.normalize();
- packVector( vec );
- unpackVector( vec2 );
-
- float ang = vec.dot( vec2 );
- ang = (( fabs( ang ) > 0.999f ) ? 0 : (float)acos(ang));
-
- if (( ang > TEST_ANGERROR ) | ( !_finite( ang )))
- {
- cerr << "error: " << ang << endl;
- cerr << "orig vec: " << vec.x << ",\t"
- << vec.y << ",\t" << vec.z << "\tmVec: "
- << mVec << endl;
- cerr << " quantized vec2: " << vec2.x << ",\t"
- << vec2.y << ",\t" << vec2.z << endl << endl;
- }
-
- avgError += ang;
- numVecs++;
- if ( maxError < ang ) maxError = ang;
- }}
-
- cerr << "max angle error: " << maxError
- << ", average error: " << avgError / numVecs
- << ", num tested vecs: " << numVecs << endl;
- }
-
- friend ostream& operator<< ( ostream& os, const cUnitVector& vec )
- { os << vec.mVec; return os; }
-#endif
-
-//protected: // !!!!
-
- unsigned short mVec;
- static float mUVAdjustment[0x2000];
- static Vector mTmpVec;
-};
-
-#endif // _3D_VECTOR_H
-
-
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef _3D_UNITVEC_H +#define _3D_UNITVEC_H + + +#define UNITVEC_DECLARE_STATICS \ + float cUnitVector::mUVAdjustment[0x2000]; \ + Vector cUnitVector::mTmpVec; + +// upper 3 bits +#define SIGN_MASK 0xe000 +#define XSIGN_MASK 0x8000 +#define YSIGN_MASK 0x4000 +#define ZSIGN_MASK 0x2000 + +// middle 6 bits - xbits +#define TOP_MASK 0x1f80 + +// lower 7 bits - ybits +#define BOTTOM_MASK 0x007f + +// unitcomp.cpp : A Unit Vector to 16-bit word conversion +// algorithm based on work of Rafael Baptista ([email protected]) +// Accuracy improved by O.D. ([email protected]) +// Used with Permission. + +// a compressed unit vector. reasonable fidelty for unit +// vectors in a 16 bit package. Good enough for surface normals +// we hope. +class cUnitVector // : public c3dMathObject +{ +public: + cUnitVector() { mVec = 0; } + cUnitVector( const Vector& vec ) + { + packVector( vec ); + } + cUnitVector( unsigned short val ) { mVec = val; } + + cUnitVector& operator=( const Vector& vec ) + { packVector( vec ); return *this; } + + operator Vector() + { + unpackVector( mTmpVec ); + return mTmpVec; + } + + void packVector( const Vector& vec ) + { + // convert from Vector to cUnitVector + + Assert( vec.IsValid()); + Vector tmp = vec; + + // input vector does not have to be unit length + // Assert( tmp.length() <= 1.001f ); + + mVec = 0; + if ( tmp.x < 0 ) { mVec |= XSIGN_MASK; tmp.x = -tmp.x; } + if ( tmp.y < 0 ) { mVec |= YSIGN_MASK; tmp.y = -tmp.y; } + if ( tmp.z < 0 ) { mVec |= ZSIGN_MASK; tmp.z = -tmp.z; } + + // project the normal onto the plane that goes through + // X0=(1,0,0),Y0=(0,1,0),Z0=(0,0,1). + // on that plane we choose an (projective!) coordinate system + // such that X0->(0,0), Y0->(126,0), Z0->(0,126),(0,0,0)->Infinity + + // a little slower... old pack was 4 multiplies and 2 adds. + // This is 2 multiplies, 2 adds, and a divide.... + float w = 126.0f / ( tmp.x + tmp.y + tmp.z ); + long xbits = (long)( tmp.x * w ); + long ybits = (long)( tmp.y * w ); + + Assert( xbits < 127 ); + Assert( xbits >= 0 ); + Assert( ybits < 127 ); + Assert( ybits >= 0 ); + + // Now we can be sure that 0<=xp<=126, 0<=yp<=126, 0<=xp+yp<=126 + // however for the sampling we want to transform this triangle + // into a rectangle. + if ( xbits >= 64 ) + { + xbits = 127 - xbits; + ybits = 127 - ybits; + } + + // now we that have xp in the range (0,127) and yp in + // the range (0,63), we can pack all the bits together + mVec |= ( xbits << 7 ); + mVec |= ybits; + } + + void unpackVector( Vector& vec ) + { + // if we do a straightforward backward transform + // we will get points on the plane X0,Y0,Z0 + // however we need points on a sphere that goes through + // these points. Therefore we need to adjust x,y,z so + // that x^2+y^2+z^2=1 by normalizing the vector. We have + // already precalculated the amount by which we need to + // scale, so all we do is a table lookup and a + // multiplication + + // get the x and y bits + long xbits = (( mVec & TOP_MASK ) >> 7 ); + long ybits = ( mVec & BOTTOM_MASK ); + + // map the numbers back to the triangle (0,0)-(0,126)-(126,0) + if (( xbits + ybits ) >= 127 ) + { + xbits = 127 - xbits; + ybits = 127 - ybits; + } + + // do the inverse transform and normalization + // costs 3 extra multiplies and 2 subtracts. No big deal. + float uvadj = mUVAdjustment[mVec & ~SIGN_MASK]; + vec.x = uvadj * (float) xbits; + vec.y = uvadj * (float) ybits; + vec.z = uvadj * (float)( 126 - xbits - ybits ); + + // set all the sign bits + if ( mVec & XSIGN_MASK ) vec.x = -vec.x; + if ( mVec & YSIGN_MASK ) vec.y = -vec.y; + if ( mVec & ZSIGN_MASK ) vec.z = -vec.z; + + Assert( vec.IsValid()); + } + + static void initializeStatics() + { + for ( int idx = 0; idx < 0x2000; idx++ ) + { + long xbits = idx >> 7; + long ybits = idx & BOTTOM_MASK; + + // map the numbers back to the triangle (0,0)-(0,127)-(127,0) + if (( xbits + ybits ) >= 127 ) + { + xbits = 127 - xbits; + ybits = 127 - ybits; + } + + // convert to 3D vectors + float x = (float)xbits; + float y = (float)ybits; + float z = (float)( 126 - xbits - ybits ); + + // calculate the amount of normalization required + mUVAdjustment[idx] = 1.0f / sqrtf( y*y + z*z + x*x ); + Assert( _finite( mUVAdjustment[idx])); + + //cerr << mUVAdjustment[idx] << "\t"; + //if ( xbits == 0 ) cerr << "\n"; + } + } + +#if 0 + void test() + { + #define TEST_RANGE 4 + #define TEST_RANDOM 100 + #define TEST_ANGERROR 1.0 + + float maxError = 0; + float avgError = 0; + int numVecs = 0; + + {for ( int x = -TEST_RANGE; x < TEST_RANGE; x++ ) + { + for ( int y = -TEST_RANGE; y < TEST_RANGE; y++ ) + { + for ( int z = -TEST_RANGE; z < TEST_RANGE; z++ ) + { + if (( x + y + z ) == 0 ) continue; + + Vector vec( (float)x, (float)y, (float)z ); + Vector vec2; + + vec.normalize(); + packVector( vec ); + unpackVector( vec2 ); + + float ang = vec.dot( vec2 ); + ang = (( fabs( ang ) > 0.99999f ) ? 0 : (float)acos(ang)); + + if (( ang > TEST_ANGERROR ) | ( !_finite( ang ))) + { + cerr << "error: " << ang << endl; + cerr << "orig vec: " << vec.x << ",\t" + << vec.y << ",\t" << vec.z << "\tmVec: " + << mVec << endl; + cerr << "quantized vec2: " << vec2.x + << ",\t" << vec2.y << ",\t" + << vec2.z << endl << endl; + } + avgError += ang; + numVecs++; + if ( maxError < ang ) maxError = ang; + } + } + }} + + for ( int w = 0; w < TEST_RANDOM; w++ ) + { + Vector vec( genRandom(), genRandom(), genRandom()); + Vector vec2; + vec.normalize(); + + packVector( vec ); + unpackVector( vec2 ); + + float ang =vec.dot( vec2 ); + ang = (( ang > 0.999f ) ? 0 : (float)acos(ang)); + + if (( ang > TEST_ANGERROR ) | ( !_finite( ang ))) + { + cerr << "error: " << ang << endl; + cerr << "orig vec: " << vec.x << ",\t" + << vec.y << ",\t" << vec.z << "\tmVec: " + << mVec << endl; + cerr << "quantized vec2: " << vec2.x << ",\t" + << vec2.y << ",\t" + << vec2.z << endl << endl; + } + avgError += ang; + numVecs++; + if ( maxError < ang ) maxError = ang; + } + + { for ( int x = 0; x < 50; x++ ) + { + Vector vec( (float)x, 25.0f, 0.0f ); + Vector vec2; + + vec.normalize(); + packVector( vec ); + unpackVector( vec2 ); + + float ang = vec.dot( vec2 ); + ang = (( fabs( ang ) > 0.999f ) ? 0 : (float)acos(ang)); + + if (( ang > TEST_ANGERROR ) | ( !_finite( ang ))) + { + cerr << "error: " << ang << endl; + cerr << "orig vec: " << vec.x << ",\t" + << vec.y << ",\t" << vec.z << "\tmVec: " + << mVec << endl; + cerr << " quantized vec2: " << vec2.x << ",\t" + << vec2.y << ",\t" << vec2.z << endl << endl; + } + + avgError += ang; + numVecs++; + if ( maxError < ang ) maxError = ang; + }} + + cerr << "max angle error: " << maxError + << ", average error: " << avgError / numVecs + << ", num tested vecs: " << numVecs << endl; + } + + friend ostream& operator<< ( ostream& os, const cUnitVector& vec ) + { os << vec.mVec; return os; } +#endif + +//protected: // !!!! + + unsigned short mVec; + static float mUVAdjustment[0x2000]; + static Vector mTmpVec; +}; + +#endif // _3D_VECTOR_H + + |