BVB Source Codes

CRYENGINE Show SerializeBits.h Source code

Return Download CRYENGINE: download SerializeBits.h Source code - Download CRYENGINE Source code - Type:.h
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #ifndef __SERIALIZE_BITS__H__
  4. #define __SERIALIZE_BITS__H__
  5.  
  6. #if _MSC_VER > 1000
  7.         #pragma once
  8. #endif
  9.  
  10. class CBitArray
  11. {
  12. public:
  13.         /* This is a naive implementation, but actually packs bits without padding, unlike CryNetwork */
  14.         CBitArray(TSerialize* m_ser);
  15.  
  16.         void          ResetForWrite();
  17.         void          ResetForRead();
  18.  
  19.         bool          IsReading() { return m_isReading; }
  20.         bool          IsWriting() { return m_isReading == false; }
  21.  
  22.         int           NumberOfBitsPushed();
  23.         void          PushBit(int bit);
  24.         int           PopBit();
  25.         void          ReadBits(unsigned char* out, int numBits);
  26.         void          WriteBits(const unsigned char* in, int numBits);
  27.         inline uint32 bitsneeded(uint32 v);
  28.  
  29.         inline void   SerializeInt(int* v, int min, int max);
  30.         inline void   SerializeUInt(unsigned int* v, unsigned int min, unsigned int max);
  31.         void          SerializeFloat(float* data, float min, float max, int totalNumBits, int reduceRange = 0);
  32.         inline void   SerializeEntity(EntityId& id);
  33.  
  34.         inline void   Serialize(bool& v);
  35.         inline void   Serialize(uint32& v, uint32 min = 0, uint32 max = 0xffffffff);
  36.         inline void   Serialize(int32& v, int min, int max);
  37.         inline void   Serialize(int16& v, int min, int max);
  38.         inline void   Serialize(uint16& v, uint16 min = 0, uint16 max = 0xffff);
  39.         inline void   Serialize(unsigned char& v, int min, int max);
  40.         inline void   Serialize(float& f, float min, float max, int totalNumBits, int reduceRange = 0);
  41.         inline void   Serialize(Vec3& v, float min, float max, int numBitsPerElem, int reduceRange = 0);
  42.         inline void   Serialize(Quat& v);
  43.  
  44.         void          WriteToSerializer();
  45.  
  46. private:
  47.         template<class INT> void SerializeInt_T(INT* v, INT min, INT max);
  48.  
  49. public:
  50.         enum { maxBytes = 1 << 13 };
  51.         int           m_bytePos;
  52.         int           m_bitPos;
  53.         int           m_numberBytes;
  54.         bool          m_isReading;
  55.         int           m_multiplier;
  56.         TSerialize*   m_ser;
  57.         unsigned char m_readByte;
  58.         unsigned char m_data[maxBytes];
  59. };
  60.  
  61. /*
  62.    =========================================================================================================
  63.    Implementation
  64.    =========================================================================================================
  65.  */
  66.  
  67. /* This is a naive implementation */
  68. NO_INLINE_WEAK CBitArray::CBitArray(TSerialize* ser)
  69. {
  70.         m_ser = ser;
  71.         if (ser->IsReading())
  72.         {
  73.                 ResetForRead();
  74.         }
  75.         else
  76.         {
  77.                 ResetForWrite();
  78.         }
  79. }
  80.  
  81. NO_INLINE_WEAK void CBitArray::ResetForWrite()
  82. {
  83.         m_bytePos = -1;
  84.         m_bitPos = 7;
  85.         m_multiplier = 1;
  86.         m_numberBytes = 0;
  87.         m_isReading = false;
  88. }
  89.  
  90. NO_INLINE_WEAK void CBitArray::ResetForRead()
  91. {
  92.         m_bitPos = 7;
  93.         m_bytePos = -1;
  94.         m_isReading = true;
  95. }
  96.  
  97. NO_INLINE_WEAK void CBitArray::PushBit(int bit)
  98. {
  99. #if !defined(_RELEASE)
  100.         if (m_bytePos >= maxBytes)
  101.         {
  102.                 CryFatalError("CBitArray ran out of room, maxBytes: %d, will need to be increased, or break up serialisation into separate CBitArray", maxBytes);
  103.         }
  104. #endif
  105.         m_bitPos++;
  106.         if (m_bitPos == 8)
  107.         {
  108.                 m_multiplier = 1;
  109.                 m_bitPos = 0;
  110.                 m_bytePos++;
  111.                 assert(m_bytePos < maxBytes);
  112.                 PREFAST_ASSUME(m_bytePos < maxBytes);
  113.                 m_data[m_bytePos] = 0;
  114.                 m_numberBytes++;
  115.         }
  116.         assert((unsigned int)m_bytePos < (unsigned int)maxBytes);
  117.         PREFAST_ASSUME((unsigned int)m_bytePos < (unsigned int)maxBytes);
  118.         m_data[m_bytePos] |= m_multiplier * (bit & 1);  // Use multiplier because variable bit shift on consoles is really slow
  119.         m_multiplier = m_multiplier << 1;
  120. }
  121.  
  122. NO_INLINE_WEAK int CBitArray::NumberOfBitsPushed()
  123. {
  124.         return m_bytePos * 8 + m_bitPos + 1;
  125. }
  126.  
  127. NO_INLINE_WEAK int CBitArray::PopBit()  /* from the front */
  128. {
  129.         m_bitPos++;
  130.         if (m_bitPos == 8)
  131.         {
  132.                 m_bitPos = 0;
  133.                 m_bytePos++;
  134.                 CRY_ASSERT(m_ser->IsReading());
  135.                 m_ser->Value("bitarray", m_readByte); // read a byte
  136.         }
  137.         unsigned char ret = m_readByte & 1;
  138.         m_readByte = m_readByte >> 1;
  139.         return ret;
  140. }
  141.  
  142. NO_INLINE_WEAK void CBitArray::ReadBits(unsigned char* out, int numBits)
  143. {
  144.         unsigned char byte;
  145.         while (numBits >= 8)
  146.         {
  147.                 byte = PopBit();
  148.                 byte |= PopBit() << 1;
  149.                 byte |= PopBit() << 2;
  150.                 byte |= PopBit() << 3;
  151.                 byte |= PopBit() << 4;
  152.                 byte |= PopBit() << 5;
  153.                 byte |= PopBit() << 6;
  154.                 byte |= PopBit() << 7;
  155.                 *out = byte;
  156.                 out++;
  157.                 numBits = numBits - 8;
  158.         }
  159.         switch (numBits)
  160.         {
  161.         case 0:
  162.                 break;
  163.         case 1:
  164.                 *out = PopBit();
  165.                 break;
  166.         case 2:
  167.                 byte = PopBit();
  168.                 byte |= PopBit() << 1;
  169.                 *out = byte;
  170.                 break;
  171.         case 3:
  172.                 byte = PopBit();
  173.                 byte |= PopBit() << 1;
  174.                 byte |= PopBit() << 2;
  175.                 *out = byte;
  176.                 break;
  177.         case 4:
  178.                 byte = PopBit();
  179.                 byte |= PopBit() << 1;
  180.                 byte |= PopBit() << 2;
  181.                 byte |= PopBit() << 3;
  182.                 *out = byte;
  183.                 break;
  184.         case 5:
  185.                 byte = PopBit();
  186.                 byte |= PopBit() << 1;
  187.                 byte |= PopBit() << 2;
  188.                 byte |= PopBit() << 3;
  189.                 byte |= PopBit() << 4;
  190.                 *out = byte;
  191.                 break;
  192.         case 6:
  193.                 byte = PopBit();
  194.                 byte |= PopBit() << 1;
  195.                 byte |= PopBit() << 2;
  196.                 byte |= PopBit() << 3;
  197.                 byte |= PopBit() << 4;
  198.                 byte |= PopBit() << 5;
  199.                 *out = byte;
  200.                 break;
  201.         case 7:
  202.                 byte = PopBit();
  203.                 byte |= PopBit() << 1;
  204.                 byte |= PopBit() << 2;
  205.                 byte |= PopBit() << 3;
  206.                 byte |= PopBit() << 4;
  207.                 byte |= PopBit() << 5;
  208.                 byte |= PopBit() << 6;
  209.                 *out = byte;
  210.                 break;
  211.         }
  212. }
  213.  
  214. NO_INLINE_WEAK void CBitArray::WriteBits(const unsigned char* in, int numBits)
  215. {
  216.         unsigned char v;
  217.         while (numBits >= 8)
  218.         {
  219.                 v = *in;
  220.                 PushBit((v >> 0) & 1);
  221.                 PushBit((v >> 1) & 1);
  222.                 PushBit((v >> 2) & 1);
  223.                 PushBit((v >> 3) & 1);
  224.                 PushBit((v >> 4) & 1);
  225.                 PushBit((v >> 5) & 1);
  226.                 PushBit((v >> 6) & 1);
  227.                 PushBit((v >> 7) & 1);
  228.                 numBits = numBits - 8;
  229.                 in++;
  230.         }
  231.         v = *in;
  232.         switch (numBits)
  233.         {
  234.         case 0:
  235.                 break;
  236.         case 1:
  237.                 PushBit((v >> 0) & 1);
  238.                 break;
  239.         case 2:
  240.                 PushBit((v >> 0) & 1);
  241.                 PushBit((v >> 1) & 1);
  242.                 break;
  243.         case 3:
  244.                 PushBit((v >> 0) & 1);
  245.                 PushBit((v >> 1) & 1);
  246.                 PushBit((v >> 2) & 1);
  247.                 break;
  248.         case 4:
  249.                 PushBit((v >> 0) & 1);
  250.                 PushBit((v >> 1) & 1);
  251.                 PushBit((v >> 2) & 1);
  252.                 PushBit((v >> 3) & 1);
  253.                 break;
  254.         case 5:
  255.                 PushBit((v >> 0) & 1);
  256.                 PushBit((v >> 1) & 1);
  257.                 PushBit((v >> 2) & 1);
  258.                 PushBit((v >> 3) & 1);
  259.                 PushBit((v >> 4) & 1);
  260.                 break;
  261.         case 6:
  262.                 PushBit((v >> 0) & 1);
  263.                 PushBit((v >> 1) & 1);
  264.                 PushBit((v >> 2) & 1);
  265.                 PushBit((v >> 3) & 1);
  266.                 PushBit((v >> 4) & 1);
  267.                 PushBit((v >> 5) & 1);
  268.                 break;
  269.         case 7:
  270.                 PushBit((v >> 0) & 1);
  271.                 PushBit((v >> 1) & 1);
  272.                 PushBit((v >> 2) & 1);
  273.                 PushBit((v >> 3) & 1);
  274.                 PushBit((v >> 4) & 1);
  275.                 PushBit((v >> 5) & 1);
  276.                 PushBit((v >> 6) & 1);
  277.                 break;
  278.         }
  279. }
  280.  
  281. inline uint32 CBitArray::bitsneeded(uint32 v)
  282. {
  283.         // See bit twiddling hacks
  284.         static const int MultiplyDeBruijnBitPosition[32] =
  285.         {
  286.                 0, 9,  1,  10, 13, 21, 2,  29, 11, 14, 16, 18, 22, 25, 3, 30,
  287.                 8, 12, 20, 28, 15, 17, 24, 7,  19, 27, 23, 6,  26, 5,  4, 31
  288.         };
  289.  
  290.         v |= v >> 1; // first round down to one less than a power of 2
  291.         v |= v >> 2;
  292.         v |= v >> 4;
  293.         v |= v >> 8;
  294.         v |= v >> 16;
  295.  
  296.         return 1 + MultiplyDeBruijnBitPosition[(uint32)(v * 0x07C4ACDDU) >> 27];
  297. }
  298.  
  299. template<class INT>
  300. NO_INLINE_WEAK void CBitArray::SerializeInt_T(INT* v, INT min, INT max)
  301. {
  302.         INT range = max - min;
  303.         INT nbits = bitsneeded(range);
  304.         unsigned char c;
  305.  
  306.         if (IsReading())
  307.         {
  308.                 INT multiplier = 1;
  309.                 *v = 0;
  310.                 while (nbits > 8)
  311.                 {
  312.                         ReadBits(&c, 8);
  313.                         *v |= multiplier * c;   // Note: there is no need for endian swapping with this method
  314.                         multiplier = multiplier * 256;
  315.                         nbits = nbits - 8;
  316.                 }
  317.                 ReadBits(&c, nbits);
  318.                 *v |= multiplier * c;
  319.                 *v = *v + min;
  320.         }
  321.         else
  322.         {
  323.                 INT tmp = std::min(*v - min, (INT)0);
  324.                 if (tmp > range) tmp = range;
  325.                 while (nbits > 8)
  326.                 {
  327.                         c = tmp & 0xff;
  328.                         WriteBits(&c, 8);   // Note: there is no need for endian swapping with this method
  329.                         tmp = tmp >> 8;
  330.                         nbits = nbits - 8;
  331.                 }
  332.                 c = tmp & 0xff;
  333.                 WriteBits(&c, nbits);
  334.         }
  335. }
  336.  
  337. inline void CBitArray::Serialize(bool& v)
  338. {
  339.         int tmp = v ? 1 : 0;
  340.         SerializeInt_T<int>(&tmp, 0, 1);
  341.         v = (tmp != 0);
  342. }
  343.  
  344. inline void CBitArray::SerializeInt(int* v, int min, int max)
  345. {
  346.         SerializeInt_T<int>(v, min, max);
  347. }
  348.  
  349. inline void CBitArray::SerializeUInt(unsigned int* v, unsigned int min, unsigned int max)
  350. {
  351.         SerializeInt_T<unsigned int>(v, min, max);
  352. }
  353.  
  354. inline void CBitArray::Serialize(uint32& v, uint32 min, uint32 max)
  355. {
  356.         unsigned int tmp = v;
  357.         SerializeUInt(&tmp, min, max);
  358.         v = (uint32)tmp;
  359. }
  360.  
  361. inline void CBitArray::Serialize(int32& v, int min, int max)
  362. {
  363.         int tmp = v;
  364.         SerializeInt(&tmp, min, max);
  365.         v = (int32)tmp;
  366. }
  367.  
  368. inline void CBitArray::Serialize(int16& v, int min, int max)
  369. {
  370.         int tmp = v;
  371.         SerializeInt(&tmp, min, max);
  372.         v = (int16)tmp;
  373. }
  374.  
  375. inline void CBitArray::Serialize(uint16& v, uint16 min, uint16 max)
  376. {
  377.         unsigned int tmp = v;
  378.         SerializeUInt(&tmp, min, max);
  379.         v = (uint16)tmp;
  380. }
  381.  
  382. inline void CBitArray::Serialize(unsigned char& v, int min, int max)
  383. {
  384.         int tmp = v;
  385.         SerializeInt(&tmp, min, max);
  386.         v = (unsigned char)tmp;
  387. }
  388.  
  389. inline void CBitArray::Serialize(float& v, float min, float max, int totalNumBits, int reduceRange)
  390. {
  391.         SerializeFloat(&v, min, max, totalNumBits, reduceRange);
  392. }
  393.  
  394. inline void CBitArray::Serialize(Vec3& v, float min, float max, int numBitsPerElem, int reduceRange)
  395. {
  396.         SerializeFloat(&v.x, min, max, numBitsPerElem, reduceRange);
  397.         SerializeFloat(&v.y, min, max, numBitsPerElem, reduceRange);
  398.         SerializeFloat(&v.z, min, max, numBitsPerElem, reduceRange);
  399. }
  400.  
  401. inline void CBitArray::Serialize(Quat& q)
  402. {
  403.         // Should this compression migratate to Cry_Quat.h ?
  404.         float quat[4];
  405.         if (IsWriting())
  406.         {
  407.                 uint32 out = 0;
  408.                 uint32 i;
  409.                 float scale = 1.0f;
  410.  
  411.                 quat[0] = q.w;
  412.                 quat[1] = q.v.x;
  413.                 quat[2] = q.v.y;
  414.                 quat[3] = q.v.z;
  415.  
  416.                 uint32 largest = 0;
  417.                 for (i = 1; i < 4; i++)
  418.                 {
  419.                         if (fabsf(quat[i]) > fabsf(quat[largest]))
  420.                                 largest = i;
  421.                 }
  422.  
  423.                 // Scale the quat so that reconstruction always deals with positive value
  424.                 scale = (float)__fsel(quat[largest], 1.f, -1.f);
  425.  
  426.                 out |= largest; // first 2 bits denote which is the largest
  427.  
  428.                 uint32 entry = 0;
  429.                 uint32 multiply = 4;
  430.                 for (i = 0; i < 4; i++)
  431.                 {
  432.                         if (i != largest)
  433.                         {
  434.                                 // Encode each remaining value in 10 bits, using range 0-1022. NB, range is chosen so zero is reproduced correctly
  435.                                 int val = (int)((((scale * quat[i]) + 0.7071f) * (1022.f / 1.4142f)) + 0.5f);
  436.                                 if (val < 0) val = 0;
  437.                                 if (val > 1022) val = 1022;
  438.                                 out |= val * multiply;
  439.                                 multiply *= 1024;
  440.                                 entry++;
  441.                         }
  442.                 }
  443.                 Serialize(out);
  444.         }
  445.         else // Reading
  446.         {
  447.                 uint32 in;
  448.                 Serialize(in);
  449.  
  450.                 static int idx[4][3] = {
  451.                         { 1, 2, 3 }, { 0, 2, 3 }, { 0, 1, 3 }, { 0, 1, 2 }
  452.                 };
  453.                 int mv = in & 3;
  454.                 int* indices = idx[mv];
  455.                 uint32 c0 = (in >> 2) & 1023;
  456.                 uint32 c1 = (in >> 12) & 1023;
  457.                 uint32 c2 = (in >> 22) & 1023;
  458.                 float outDatai0 = (c0 * (1.4142f / 1022.f)) - 0.7071f;
  459.                 float outDatai1 = (c1 * (1.4142f / 1022.f)) - 0.7071f;
  460.                 float outDatai2 = (c2 * (1.4142f / 1022.f)) - 0.7071f;
  461.                 float sumOfSqs = 1.f - outDatai0 * outDatai0;
  462.                 quat[indices[0]] = outDatai0;
  463.                 sumOfSqs -= outDatai1 * outDatai1;
  464.                 quat[indices[1]] = outDatai1;
  465.                 sumOfSqs -= outDatai2 * outDatai2;
  466.                 quat[indices[2]] = outDatai2;
  467.                 sumOfSqs = (float)__fsel(sumOfSqs, sumOfSqs, 0.0f);
  468.                 quat[mv] = sqrtf(sumOfSqs);
  469.  
  470.                 q.w = quat[0];
  471.                 q.v.x = quat[1];
  472.                 q.v.y = quat[2];
  473.                 q.v.z = quat[3];
  474.         }
  475. }
  476.  
  477. inline void CBitArray::SerializeFloat(float* data, float min, float max, int totalNumBits, int reduceRange)
  478. {
  479.         int range = (1 << totalNumBits) - 1 - reduceRange;
  480.  
  481.         if (IsReading())
  482.         {
  483.                 int n;
  484.                 SerializeInt(&n, 0, range);
  485.                 *data = ((float)n) * (max - min) / (float)(range) + min;
  486.         }
  487.         else
  488.         {
  489.                 float f = clamp_tpl(*data, min, max);
  490.                 int n = (int)(((float)range) / (max - min) * (f - min));
  491.                 SerializeInt(&n, 0, range);
  492.         }
  493. }
  494.  
  495. inline void CBitArray::SerializeEntity(EntityId& entId)
  496. {
  497.         INetContext* pContext = gEnv->pGameFramework->GetNetContext();
  498.         if (IsReading())
  499.         {
  500.                 SNetObjectID netId;
  501.                 Serialize(netId.id);
  502.                 if (pContext)
  503.                 {
  504.                         pContext->Resaltify(netId);
  505.                         entId = pContext->GetEntityID(netId);
  506.                 }
  507.                 else
  508.                 {
  509.                         entId = 0;
  510.                         GameWarning("brk: can't decode entid, pContext==NULL!");
  511.                 }
  512.         }
  513.         else
  514.         {
  515.                 SNetObjectID netId;
  516.                 if (pContext)
  517.                 {
  518.                         netId = pContext->GetNetID(entId, false);
  519.                 }
  520.                 else
  521.                 {
  522.                         GameWarning("brk: can't send entid, pContext==NULL!");
  523.                 }
  524.                 Serialize(netId.id);
  525.         }
  526. }
  527.  
  528. NO_INLINE_WEAK void CBitArray::WriteToSerializer()
  529. {
  530.         CRY_ASSERT(IsReading() == 0);
  531.  
  532.         for (int i = 0; i < m_numberBytes; i++)
  533.         {
  534.                 m_ser->Value("bitarray", m_data[i]);
  535.         }
  536. }
  537.  
  538. #endif
  539.  
downloadSerializeBits.h Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top