123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #ifndef __BITMSG_H__
- #define __BITMSG_H__
- /*
- ================================================
- idBitMsg operates on a sequence of individual bits. It handles byte ordering and
- avoids alignment errors. It allows concurrent writing and reading. The data set with Init
- is never free-d.
- ================================================
- */
- class idBitMsg {
- public:
- idBitMsg() { InitWrite( NULL, 0 ); }
- idBitMsg( byte * data, int length ) { InitWrite( data, length ); }
- idBitMsg( const byte * data, int length ) { InitRead( data, length ); }
- // both read & write
- void InitWrite( byte *data, int length );
- // read only
- void InitRead( const byte *data, int length );
- // get data for writing
- byte * GetWriteData();
- // get data for reading
- const byte * GetReadData() const;
- // get the maximum message size
- int GetMaxSize() const;
- // generate error if not set and message is overflowed
- void SetAllowOverflow( bool set );
- // returns true if the message was overflowed
- bool IsOverflowed() const;
- // size of the message in bytes
- int GetSize() const;
- // set the message size
- void SetSize( int size );
- // get current write bit
- int GetWriteBit() const;
- // set current write bit
- void SetWriteBit( int bit );
- // returns number of bits written
- int GetNumBitsWritten() const;
- // space left in bytes for writing
- int GetRemainingSpace() const;
- // space left in bits for writing
- int GetRemainingWriteBits() const;
- //------------------------
- // Write State
- //------------------------
- // save the write state
- void SaveWriteState( int &s, int &b, uint64 &t ) const;
- // restore the write state
- void RestoreWriteState( int s, int b, uint64 t );
- //------------------------
- // Reading
- //------------------------
- // bytes read so far
- int GetReadCount() const;
- // set the number of bytes and bits read
- void SetReadCount( int bytes );
- // get current read bit
- int GetReadBit() const;
- // set current read bit
- void SetReadBit( int bit );
- // returns number of bits read
- int GetNumBitsRead() const;
- // number of bytes left to read
- int GetRemainingData() const;
- // number of bits left to read
- int GetRemainingReadBits() const;
- // save the read state
- void SaveReadState( int &c, int &b ) const;
- // restore the read state
- void RestoreReadState( int c, int b );
- //------------------------
- // Writing
- //------------------------
- // begin writing
- void BeginWriting();
- // write up to the next byte boundary
- void WriteByteAlign();
- // write the specified number of bits
- void WriteBits( int value, int numBits );
- void WriteBool( bool c );
- void WriteChar( int8 c );
- void WriteByte( uint8 c );
- void WriteShort( int16 c );
- void WriteUShort( uint16 c );
- void WriteLong( int32 c );
- void WriteLongLong( int64 c );
- void WriteFloat( float f );
- void WriteFloat( float f, int exponentBits, int mantissaBits );
- void WriteAngle8( float f );
- void WriteAngle16( float f );
- void WriteDir( const idVec3 &dir, int numBits );
- void WriteString( const char *s, int maxLength = -1, bool make7Bit = true );
- void WriteData( const void *data, int length );
- void WriteNetadr( const netadr_t adr );
- void WriteUNorm8( float f ) { WriteByte( idMath::Ftob( f * 255.0f ) ); }
- void WriteUNorm16( float f ) { WriteUShort( idMath::Ftoi( f * 65535.0f ) ); }
- void WriteNorm16( float f ) { WriteShort( idMath::Ftoi( f * 32767.0f ) ); }
- void WriteDeltaChar( int8 oldValue, int8 newValue ) { WriteByte( newValue - oldValue ); }
- void WriteDeltaByte( uint8 oldValue, uint8 newValue ) { WriteByte( newValue - oldValue ); }
- void WriteDeltaShort( int16 oldValue, int16 newValue ) { WriteUShort( newValue - oldValue ); }
- void WriteDeltaUShort( uint16 oldValue, uint16 newValue ) { WriteUShort( newValue - oldValue ); }
- void WriteDeltaLong( int32 oldValue, int32 newValue ) { WriteLong( newValue - oldValue ); }
- void WriteDeltaFloat( float oldValue, float newValue ) { WriteFloat( newValue - oldValue ); }
- void WriteDeltaFloat( float oldValue, float newValue, int exponentBits, int mantissaBits ) { WriteFloat( newValue - oldValue, exponentBits, mantissaBits ); }
- bool WriteDeltaDict( const idDict &dict, const idDict *base );
- template< int _max_, int _numBits_ >
- void WriteQuantizedFloat( float value );
- template< int _max_, int _numBits_ >
- void WriteQuantizedUFloat( float value ); // Quantize a float to a variable number of bits (assumes unsigned, uses simple quantization)
- template< typename T >
- void WriteVectorFloat( const T & v ) { for ( int i = 0; i < v.GetDimension(); i++ ) { WriteFloat( v[i] ); } }
- template< typename T >
- void WriteVectorUNorm8( const T & v ) { for ( int i = 0; i < v.GetDimension(); i++ ) { WriteUNorm8( v[i] ); } }
- template< typename T >
- void WriteVectorUNorm16( const T & v ) { for ( int i = 0; i < v.GetDimension(); i++ ) { WriteUNorm16( v[i] ); } }
- template< typename T >
- void WriteVectorNorm16( const T & v ) { for ( int i = 0; i < v.GetDimension(); i++ ) { WriteNorm16( v[i] ); } }
- // Compress a vector to a variable number of bits (assumes signed, uses simple quantization)
- template< typename T, int _max_, int _numBits_ >
- void WriteQuantizedVector( const T & v ) { for ( int i = 0; i < v.GetDimension(); i++ ) { WriteQuantizedFloat< _max_, _numBits_ >( v[i] ); } }
- // begin reading.
- void BeginReading() const;
- // read up to the next byte boundary
- void ReadByteAlign() const;
- // read the specified number of bits
- int ReadBits( int numBits ) const;
- bool ReadBool() const;
- int ReadChar() const;
- int ReadByte() const;
- int ReadShort() const;
- int ReadUShort() const;
- int ReadLong() const;
- int64 ReadLongLong() const;
- float ReadFloat() const;
- float ReadFloat( int exponentBits, int mantissaBits ) const;
- float ReadAngle8() const;
- float ReadAngle16() const;
- idVec3 ReadDir( int numBits ) const;
- int ReadString( char *buffer, int bufferSize ) const;
- int ReadString( idStr & str ) const;
- int ReadData( void *data, int length ) const;
- void ReadNetadr( netadr_t *adr ) const;
- float ReadUNorm8() const { return ReadByte() / 255.0f; }
- float ReadUNorm16() const { return ReadUShort() / 65535.0f; }
- float ReadNorm16() const { return ReadShort() / 32767.0f; }
- int8 ReadDeltaChar( int8 oldValue ) const { return oldValue + ReadByte(); }
- uint8 ReadDeltaByte( uint8 oldValue ) const { return oldValue + ReadByte(); }
- int16 ReadDeltaShort( int16 oldValue ) const { return oldValue + ReadUShort(); }
- uint16 ReadDeltaUShort( uint16 oldValue ) const { return oldValue + ReadUShort(); }
- int32 ReadDeltaLong( int32 oldValue ) const { return oldValue + ReadLong(); }
- float ReadDeltaFloat( float oldValue ) const { return oldValue + ReadFloat(); }
- float ReadDeltaFloat( float oldValue, int exponentBits, int mantissaBits ) const { return oldValue + ReadFloat( exponentBits, mantissaBits ); }
- bool ReadDeltaDict( idDict &dict, const idDict *base ) const;
- template< int _max_, int _numBits_ >
- float ReadQuantizedFloat() const;
- template< int _max_, int _numBits_ >
- float ReadQuantizedUFloat() const;
- template< typename T >
- void ReadVectorFloat( T & v ) const { for ( int i = 0; i < v.GetDimension(); i++ ) { v[i] = ReadFloat(); } }
- template< typename T >
- void ReadVectorUNorm8( T & v ) const { for ( int i = 0; i < v.GetDimension(); i++ ) { v[i] = ReadUNorm8(); } }
- template< typename T >
- void ReadVectorUNorm16( T & v ) const { for ( int i = 0; i < v.GetDimension(); i++ ) { v[i] = ReadUNorm16(); } }
- template< typename T >
- void ReadVectorNorm16( T & v ) const { for ( int i = 0; i < v.GetDimension(); i++ ) { v[i] = ReadNorm16(); } }
- template< typename T, int _max_, int _numBits_ >
- void ReadQuantizedVector( T & v ) const { for ( int i = 0; i < v.GetDimension(); i++ ) { v[i] = ReadQuantizedFloat< _max_, _numBits_ >(); } }
- static int DirToBits( const idVec3 &dir, int numBits );
- static idVec3 BitsToDir( int bits, int numBits );
- void SetHasChanged( bool b ) { hasChanged = b; }
- bool HasChanged() const { return hasChanged; }
- private:
- byte * writeData; // pointer to data for writing
- const byte * readData; // pointer to data for reading
- int maxSize; // maximum size of message in bytes
- int curSize; // current size of message in bytes
- mutable int writeBit; // number of bits written to the last written byte
- mutable int readCount; // number of bytes read so far
- mutable int readBit; // number of bits read from the last read byte
- bool allowOverflow; // if false, generate error when the message is overflowed
- bool overflowed; // set true if buffer size failed (with allowOverflow set)
- bool hasChanged; // Hack
- mutable uint64 tempValue;
- private:
- bool CheckOverflow( int numBits );
- byte * GetByteSpace( int length );
- };
- /*
- ========================
- idBitMsg::InitWrite
- ========================
- */
- ID_INLINE void idBitMsg::InitWrite( byte *data, int length ) {
- writeData = data;
- readData = data;
- maxSize = length;
- curSize = 0;
- writeBit = 0;
- readCount = 0;
- readBit = 0;
- allowOverflow = false;
- overflowed = false;
-
- tempValue = 0;
- }
- /*
- ========================
- idBitMsg::InitRead
- ========================
- */
- ID_INLINE void idBitMsg::InitRead( const byte *data, int length ) {
- writeData = NULL;
- readData = data;
- maxSize = length;
- curSize = length;
- writeBit = 0;
- readCount = 0;
- readBit = 0;
- allowOverflow = false;
- overflowed = false;
- tempValue = 0;
- }
- /*
- ========================
- idBitMsg::GetWriteData
- ========================
- */
- ID_INLINE byte *idBitMsg::GetWriteData() {
- return writeData;
- }
- /*
- ========================
- idBitMsg::GetReadData
- ========================
- */
- ID_INLINE const byte *idBitMsg::GetReadData() const {
- return readData;
- }
- /*
- ========================
- idBitMsg::GetMaxSize
- ========================
- */
- ID_INLINE int idBitMsg::GetMaxSize() const {
- return maxSize;
- }
- /*
- ========================
- idBitMsg::SetAllowOverflow
- ========================
- */
- ID_INLINE void idBitMsg::SetAllowOverflow( bool set ) {
- allowOverflow = set;
- }
- /*
- ========================
- idBitMsg::IsOverflowed
- ========================
- */
- ID_INLINE bool idBitMsg::IsOverflowed() const {
- return overflowed;
- }
- /*
- ========================
- idBitMsg::GetSize
- ========================
- */
- ID_INLINE int idBitMsg::GetSize() const {
- return curSize + ( writeBit != 0 );
- }
- /*
- ========================
- idBitMsg::SetSize
- ========================
- */
- ID_INLINE void idBitMsg::SetSize( int size ) {
- assert( writeBit == 0 );
-
- if ( size > maxSize ) {
- curSize = maxSize;
- } else {
- curSize = size;
- }
- }
- /*
- ========================
- idBitMsg::GetWriteBit
- ========================
- */
- ID_INLINE int idBitMsg::GetWriteBit() const {
- return writeBit;
- }
- /*
- ========================
- idBitMsg::SetWriteBit
- ========================
- */
- ID_INLINE void idBitMsg::SetWriteBit( int bit ) {
- // see idBitMsg::WriteByteAlign
- assert( false );
- writeBit = bit & 7;
- if ( writeBit ) {
- writeData[curSize - 1] &= ( 1 << writeBit ) - 1;
- }
- }
- /*
- ========================
- idBitMsg::GetNumBitsWritten
- ========================
- */
- ID_INLINE int idBitMsg::GetNumBitsWritten() const {
- return ( curSize << 3 ) + writeBit;
- }
- /*
- ========================
- idBitMsg::GetRemainingSpace
- ========================
- */
- ID_INLINE int idBitMsg::GetRemainingSpace() const {
- return maxSize - GetSize();
- }
- /*
- ========================
- idBitMsg::GetRemainingWriteBits
- ========================
- */
- ID_INLINE int idBitMsg::GetRemainingWriteBits() const {
- return ( maxSize << 3 ) - GetNumBitsWritten();
- }
- /*
- ========================
- idBitMsg::SaveWriteState
- ========================
- */
- ID_INLINE void idBitMsg::SaveWriteState( int &s, int &b, uint64 &t ) const {
- s = curSize;
- b = writeBit;
- t = tempValue;
- }
- /*
- ========================
- idBitMsg::RestoreWriteState
- ========================
- */
- ID_INLINE void idBitMsg::RestoreWriteState( int s, int b, uint64 t ) {
- curSize = s;
- writeBit = b & 7;
- if ( writeBit ) {
- writeData[curSize] &= ( 1 << writeBit ) - 1;
- }
- tempValue = t;
- }
- /*
- ========================
- idBitMsg::GetReadCount
- ========================
- */
- ID_INLINE int idBitMsg::GetReadCount() const {
- return readCount;
- }
- /*
- ========================
- idBitMsg::SetReadCount
- ========================
- */
- ID_INLINE void idBitMsg::SetReadCount( int bytes ) {
- readCount = bytes;
- }
- /*
- ========================
- idBitMsg::GetReadBit
- ========================
- */
- ID_INLINE int idBitMsg::GetReadBit() const {
- return readBit;
- }
- /*
- ========================
- idBitMsg::SetReadBit
- ========================
- */
- ID_INLINE void idBitMsg::SetReadBit( int bit ) {
- readBit = bit & 7;
- }
- /*
- ========================
- idBitMsg::GetNumBitsRead
- ========================
- */
- ID_INLINE int idBitMsg::GetNumBitsRead() const {
- return ( ( readCount << 3 ) - ( ( 8 - readBit ) & 7 ) );
- }
- /*
- ========================
- idBitMsg::GetRemainingData
- ========================
- */
- ID_INLINE int idBitMsg::GetRemainingData() const {
- assert( writeBit == 0 );
- return curSize - readCount;
- }
- /*
- ========================
- idBitMsg::GetRemainingReadBits
- ========================
- */
- ID_INLINE int idBitMsg::GetRemainingReadBits() const {
- assert( writeBit == 0 );
- return ( curSize << 3 ) - GetNumBitsRead();
- }
- /*
- ========================
- idBitMsg::SaveReadState
- ========================
- */
- ID_INLINE void idBitMsg::SaveReadState( int &c, int &b ) const {
- assert( writeBit == 0 );
- c = readCount;
- b = readBit;
- }
- /*
- ========================
- idBitMsg::RestoreReadState
- ========================
- */
- ID_INLINE void idBitMsg::RestoreReadState( int c, int b ) {
- assert( writeBit == 0 );
- readCount = c;
- readBit = b & 7;
- }
- /*
- ========================
- idBitMsg::BeginWriting
- ========================
- */
- ID_INLINE void idBitMsg::BeginWriting() {
- curSize = 0;
- overflowed = false;
- writeBit = 0;
- tempValue = 0;
- }
- /*
- ========================
- idBitMsg::WriteByteAlign
- ========================
- */
- ID_INLINE void idBitMsg::WriteByteAlign() {
- // it is important that no uninitialized data slips in the msg stream,
- // because we use memcmp to decide if entities have changed and wether we should transmit them
- // this function has the potential to leave uninitialized bits into the stream,
- // however idBitMsg::WriteBits is properly initializing the byte to 0 so hopefully we are still safe
- // adding this extra check just in case
- curSize += writeBit != 0;
- assert( writeBit == 0 || ( ( writeData[curSize - 1] >> writeBit ) == 0 ) ); // had to early out writeBit == 0 because when writeBit == 0 writeData[curSize - 1] may be the previous byte written and trigger false positives
- writeBit = 0;
- tempValue = 0;
- }
- /*
- ========================
- idBitMsg::WriteBool
- ========================
- */
- ID_INLINE void idBitMsg::WriteBool( bool c ) {
- WriteBits( c, 1 );
- }
- /*
- ========================
- idBitMsg::WriteChar
- ========================
- */
- ID_INLINE void idBitMsg::WriteChar( int8 c ) {
- WriteBits( c, -8 );
- }
- /*
- ========================
- idBitMsg::WriteByte
- ========================
- */
- ID_INLINE void idBitMsg::WriteByte( uint8 c ) {
- WriteBits( c, 8 );
- }
- /*
- ========================
- idBitMsg::WriteShort
- ========================
- */
- ID_INLINE void idBitMsg::WriteShort( int16 c ) {
- WriteBits( c, -16 );
- }
- /*
- ========================
- idBitMsg::WriteUShort
- ========================
- */
- ID_INLINE void idBitMsg::WriteUShort( uint16 c ) {
- WriteBits( c, 16 );
- }
- /*
- ========================
- idBitMsg::WriteLong
- ========================
- */
- ID_INLINE void idBitMsg::WriteLong( int32 c ) {
- WriteBits( c, 32 );
- }
- /*
- ========================
- idBitMsg::WriteLongLong
- ========================
- */
- ID_INLINE void idBitMsg::WriteLongLong( int64 c ) {
- int a = c;
- int b = c >> 32;
- WriteBits( a, 32 );
- WriteBits( b, 32 );
- }
- /*
- ========================
- idBitMsg::WriteFloat
- ========================
- */
- ID_INLINE void idBitMsg::WriteFloat( float f ) {
- WriteBits( *reinterpret_cast<int *>(&f), 32 );
- }
- /*
- ========================
- idBitMsg::WriteFloat
- ========================
- */
- ID_INLINE void idBitMsg::WriteFloat( float f, int exponentBits, int mantissaBits ) {
- int bits = idMath::FloatToBits( f, exponentBits, mantissaBits );
- WriteBits( bits, 1 + exponentBits + mantissaBits );
- }
- /*
- ========================
- idBitMsg::WriteAngle8
- ========================
- */
- ID_INLINE void idBitMsg::WriteAngle8( float f ) {
- WriteByte( ANGLE2BYTE( f ) );
- }
- /*
- ========================
- idBitMsg::WriteAngle16
- ========================
- */
- ID_INLINE void idBitMsg::WriteAngle16( float f ) {
- WriteShort( ANGLE2SHORT(f) );
- }
- /*
- ========================
- idBitMsg::WriteDir
- ========================
- */
- ID_INLINE void idBitMsg::WriteDir( const idVec3 &dir, int numBits ) {
- WriteBits( DirToBits( dir, numBits ), numBits );
- }
- /*
- ========================
- idBitMsg::BeginReading
- ========================
- */
- ID_INLINE void idBitMsg::BeginReading() const {
- readCount = 0;
- readBit = 0;
-
- writeBit = 0;
- tempValue = 0;
- }
- /*
- ========================
- idBitMsg::ReadByteAlign
- ========================
- */
- ID_INLINE void idBitMsg::ReadByteAlign() const {
- readBit = 0;
- }
- /*
- ========================
- idBitMsg::ReadBool
- ========================
- */
- ID_INLINE bool idBitMsg::ReadBool() const {
- return ( ReadBits( 1 ) == 1 ) ? true : false;
- }
- /*
- ========================
- idBitMsg::ReadChar
- ========================
- */
- ID_INLINE int idBitMsg::ReadChar() const {
- return (signed char)ReadBits( -8 );
- }
- /*
- ========================
- idBitMsg::ReadByte
- ========================
- */
- ID_INLINE int idBitMsg::ReadByte() const {
- return (unsigned char)ReadBits( 8 );
- }
- /*
- ========================
- idBitMsg::ReadShort
- ========================
- */
- ID_INLINE int idBitMsg::ReadShort() const {
- return (short)ReadBits( -16 );
- }
- /*
- ========================
- idBitMsg::ReadUShort
- ========================
- */
- ID_INLINE int idBitMsg::ReadUShort() const {
- return (unsigned short)ReadBits( 16 );
- }
- /*
- ========================
- idBitMsg::ReadLong
- ========================
- */
- ID_INLINE int idBitMsg::ReadLong() const {
- return ReadBits( 32 );
- }
- /*
- ========================
- idBitMsg::ReadLongLong
- ========================
- */
- ID_INLINE int64 idBitMsg::ReadLongLong() const {
- int64 a = ReadBits( 32 );
- int64 b = ReadBits( 32 );
- int64 c = ( 0x00000000ffffffff & a ) | ( b << 32 );
- return c;
- }
- /*
- ========================
- idBitMsg::ReadFloat
- ========================
- */
- ID_INLINE float idBitMsg::ReadFloat() const {
- float value;
- *reinterpret_cast<int *>(&value) = ReadBits( 32 );
- return value;
- }
- /*
- ========================
- idBitMsg::ReadFloat
- ========================
- */
- ID_INLINE float idBitMsg::ReadFloat( int exponentBits, int mantissaBits ) const {
- int bits = ReadBits( 1 + exponentBits + mantissaBits );
- return idMath::BitsToFloat( bits, exponentBits, mantissaBits );
- }
- /*
- ========================
- idBitMsg::ReadAngle8
- ========================
- */
- ID_INLINE float idBitMsg::ReadAngle8() const {
- return BYTE2ANGLE( ReadByte() );
- }
- /*
- ========================
- idBitMsg::ReadAngle16
- ========================
- */
- ID_INLINE float idBitMsg::ReadAngle16() const {
- return SHORT2ANGLE( ReadShort() );
- }
- /*
- ========================
- idBitMsg::ReadDir
- ========================
- */
- ID_INLINE idVec3 idBitMsg::ReadDir( int numBits ) const {
- return BitsToDir( ReadBits( numBits ), numBits );
- }
- /*
- ========================
- idBitMsg::WriteQuantizedFloat
- ========================
- */
- template< int _max_, int _numBits_ >
- ID_INLINE void idBitMsg::WriteQuantizedFloat( float value ) {
- enum { storeMax = ( 1 << ( _numBits_ - 1 ) ) - 1 };
- if ( _max_ > storeMax ) {
- // Scaling down (scale should be < 1)
- const float scale = (float)storeMax / (float)_max_;
- WriteBits( idMath::ClampInt( -storeMax, storeMax, idMath::Ftoi( value * scale ) ), -_numBits_ );
- } else {
- // Scaling up (scale should be >= 1) (Preserve whole numbers when possible)
- enum { scale = storeMax / _max_ };
- WriteBits( idMath::ClampInt( -storeMax, storeMax, idMath::Ftoi( value * scale ) ), -_numBits_ );
- }
- }
- /*
- ========================
- idBitMsg::WriteQuantizedUFloat
- ========================
- */
- template< int _max_, int _numBits_ >
- ID_INLINE void idBitMsg::WriteQuantizedUFloat( float value ) {
- enum { storeMax = ( 1 << _numBits_ ) - 1 };
- if ( _max_ > storeMax ) {
- // Scaling down (scale should be < 1)
- const float scale = (float)storeMax / (float)_max_;
- WriteBits( idMath::ClampInt( 0, storeMax, idMath::Ftoi( value * scale ) ), _numBits_ );
- } else {
- // Scaling up (scale should be >= 1) (Preserve whole numbers when possible)
- enum { scale = storeMax / _max_ };
- WriteBits( idMath::ClampInt( 0, storeMax, idMath::Ftoi( value * scale ) ), _numBits_ );
- }
- }
- /*
- ========================
- idBitMsg::ReadQuantizedFloat
- ========================
- */
- template< int _max_, int _numBits_ >
- ID_INLINE float idBitMsg::ReadQuantizedFloat() const {
- enum { storeMax = ( 1 << ( _numBits_ - 1 ) ) - 1 };
- if ( _max_ > storeMax ) {
- // Scaling down (scale should be < 1)
- const float invScale = (float)_max_ / (float)storeMax;
- return (float)ReadBits( -_numBits_ ) * invScale;
- } else {
- // Scaling up (scale should be >= 1) (Preserve whole numbers when possible)
- // Scale will be a whole number.
- // We use a float to get rid of (potential divide by zero) which is handled above, but the compiler is dumb
- const float scale = storeMax / _max_;
- const float invScale = 1.0f / scale;
- return (float)ReadBits( -_numBits_ ) * invScale;
- }
- }
- /*
- ========================
- idBitMsg::ReadQuantizedUFloat
- ========================
- */
- template< int _max_, int _numBits_ >
- float idBitMsg::ReadQuantizedUFloat() const {
- enum { storeMax = ( 1 << _numBits_ ) - 1 };
- if ( _max_ > storeMax ) {
- // Scaling down (scale should be < 1)
- const float invScale = (float)_max_ / (float)storeMax;
- return (float)ReadBits( _numBits_ ) * invScale;
- } else {
- // Scaling up (scale should be >= 1) (Preserve whole numbers when possible)
- // Scale will be a whole number.
- // We use a float to get rid of (potential divide by zero) which is handled above, but the compiler is dumb
- const float scale = storeMax / _max_;
- const float invScale = 1.0f / scale;
- return (float)ReadBits( _numBits_ ) * invScale;
- }
- }
- /*
- ================
- WriteFloatArray
- Writes all the values from the array to the bit message.
- ================
- */
- template< class _arrayType_ >
- void WriteFloatArray( idBitMsg & message, const _arrayType_ & sourceArray ) {
- for( int i = 0; i < idTupleSize< _arrayType_ >::value; ++i ) {
- message.WriteFloat( sourceArray[i] );
- }
- }
- /*
- ================
- WriteFloatArrayDelta
- Writes _num_ values from the array to the bit message.
- ================
- */
- template< class _arrayType_ >
- void WriteDeltaFloatArray( idBitMsg & message, const _arrayType_ & oldArray, const _arrayType_ & newArray ) {
- for( int i = 0; i < idTupleSize< _arrayType_ >::value; ++i ) {
- message.WriteDeltaFloat( oldArray[i], newArray[i] );
- }
- }
- /*
- ================
- ReadFloatArray
- Reads _num_ values from the array to the bit message.
- ================
- */
- template< class _arrayType_ >
- _arrayType_ ReadFloatArray( const idBitMsg & message ) {
- _arrayType_ result;
- for( int i = 0; i < idTupleSize< _arrayType_ >::value; ++i ) {
- result[i] = message.ReadFloat();
- }
- return result;
- }
- /*
- ================
- ReadDeltaFloatArray
- Reads _num_ values from the array to the bit message.
- ================
- */
- template< class _arrayType_ >
- _arrayType_ ReadDeltaFloatArray( const idBitMsg & message, const _arrayType_ & oldArray ) {
- _arrayType_ result;
- for( int i = 0; i < idTupleSize< _arrayType_ >::value; ++i ) {
- result[i] = message.ReadDeltaFloat( oldArray[i] );
- }
- return result;
- }
- #endif /* !__BITMSG_H__ */
|