BVB Source Codes

CRYENGINE Show GeomCacheDecoder.cpp Source code

Return Download CRYENGINE: download GeomCacheDecoder.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // ------------------------------------------------------------------------
  4. //  File name:   GeomCacheDecoder.cpp
  5. //  Created:     23/8/2012 by Axel Gneiting
  6. //  Description: Decodes geom cache data
  7. // -------------------------------------------------------------------------
  8. //
  9. ////////////////////////////////////////////////////////////////////////////
  10.  
  11. #include "StdAfx.h"
  12.  
  13. #if defined(USE_GEOM_CACHES)
  14.  
  15.         #include "GeomCacheDecoder.h"
  16.         #include "GeomCache.h"
  17.         #include "GeomCacheRenderNode.h"
  18.         #include "GeomCachePredictors.h"
  19.         #include <CrySystem/ZLib/IZlibDecompressor.h>
  20.         #include <CrySystem/ZLib/ILZ4Decompressor.h>
  21.  
  22. namespace GeomCacheDecoder
  23. {
  24. // This namespace will provide the different vertex decode function permutations to avoid dynamic branching
  25. const uint kNumPermutations = 2 * 2 * 2 * 3;
  26.  
  27. GeomCacheFile::Color FixedPointColorLerp(int32 a, int32 b, const int32 lerpFactor)
  28. {
  29.         return a + (((b - a) * lerpFactor) >> 16);
  30. }
  31.  
  32. inline uint GetDecodeVerticesPerm(const bool bMotionBlur, const GeomCacheFile::EStreams constantStreamMask, const GeomCacheFile::EStreams animatedStreamMask)
  33. {
  34.         uint permutation = 0;
  35.  
  36.         permutation += bMotionBlur ? (2 * 2 * 3) : 0;
  37.         permutation += (constantStreamMask& GeomCacheFile::eStream_Positions) ? (2 * 3) : 0;
  38.         permutation += (constantStreamMask& GeomCacheFile::eStream_Texcoords) ? 3 : 0;
  39.         permutation += (constantStreamMask& GeomCacheFile::eStream_Colors) ? 1 : 0;
  40.         permutation += (animatedStreamMask& GeomCacheFile::eStream_Colors) ? 2 : 0;
  41.  
  42.         return permutation;
  43. }
  44.  
  45.         #if CRY_PLATFORM_WINDOWS || CRY_PLATFORM_DURANGO || CRY_PLATFORM_ORBIS
  46.                 #define vec4f_swizzle(v, p, q, r, s) (_mm_shuffle_ps((v), (v), ((s) << 6 | (r) << 4 | (q) << 2 | (p))))
  47.  
  48. void ConvertToTangentAndBitangentVec4f(const __m128 interpolated, const __m128 floor, __m128& tangent, __m128& bitangent)
  49. {
  50.         const __m128 comparedAgainstW = _mm_setr_ps(FLT_MIN, FLT_MIN, FLT_MIN, 0.0f);
  51.         const __m128 flipSignMask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
  52.         const __m128 twos = _mm_setr_ps(2.0f, 2.0f, 2.0f, 0.0f);
  53.  
  54.         // (interpolated.w < 0.0f) != (floor.w < 0.0f) => flip sign of quaternions in registers
  55.         const __m128 cmp = _mm_xor_ps(_mm_cmplt_ps(interpolated, comparedAgainstW), _mm_cmplt_ps(floor, comparedAgainstW));
  56.         const __m128 signCmp = vec4f_swizzle(cmp, 3, 3, 3, 3);
  57.         const __m128 xyzw = _mm_xor_ps(interpolated, _mm_and_ps(signCmp, flipSignMask));
  58.         const __m128 wSignBit = _mm_and_ps(_mm_castsi128_ps(_mm_setr_epi32(0, 0, 0, 0x80000000)), xyzw);
  59.  
  60.         // Calculate tangent & bitangent
  61.         const __m128 xxxx = vec4f_swizzle(xyzw, 0, 0, 0, 0);
  62.         const __m128 yyyy = vec4f_swizzle(xyzw, 1, 1, 1, 1);
  63.         const __m128 wwww = vec4f_swizzle(xyzw, 3, 3, 3, 3);
  64.         const __m128 wzyx = vec4f_swizzle(xyzw, 3, 2, 1, 0);
  65.         const __m128 zwxy = vec4f_swizzle(xyzw, 2, 3, 0, 1);
  66.  
  67.         // tangent = (2 * (x * x + w * w) - 1, 2 * (y * x + z * w), 2 * (z * x - y * w), sign(w))
  68.         __m128 wwnw = _mm_xor_ps(wwww, _mm_castsi128_ps(_mm_setr_epi32(0, 0, 0x80000000, 0)));   // -> (w, w, -w, w)
  69.         tangent = _mm_add_ps(_mm_mul_ps(_mm_add_ps(_mm_mul_ps(xyzw, xxxx), _mm_mul_ps(wzyx, wwnw)), twos), _mm_setr_ps(-1.0f, 0.0f, 0.0f, 1.0f));
  70.         tangent = _mm_or_ps(wSignBit, tangent);
  71.  
  72.         // bitangent = (2 * (x * y - z * w), 2 * (y * y + w * w) - 1, 2 * (z * y + x * w), sign(w))
  73.         __m128 nwww = _mm_xor_ps(wwww, _mm_castsi128_ps(_mm_setr_epi32(0x80000000, 0, 0, 0)));   // -> (-w, w, w, w)
  74.         bitangent = _mm_add_ps(_mm_mul_ps(_mm_add_ps(_mm_mul_ps(xyzw, yyyy), _mm_mul_ps(zwxy, nwww)), twos), _mm_setr_ps(0.0f, -1.0f, 0.0f, 1.0f));
  75.         bitangent = _mm_or_ps(wSignBit, bitangent);
  76. }
  77.  
  78. // Even on Durango and Orbis we don't use _mm_dp_ps because it's slower than the _mm_hadd_ps way (_mm_dp_ps is a microcoded instruction).
  79. ILINE __m128 _mm_dp_ps_emu(const __m128& a, const __m128& b)
  80. {
  81.         __m128 tmp1 = _mm_mul_ps(a, b);
  82.         __m128 tmp2 = _mm_hadd_ps(tmp1, tmp1);
  83.         return _mm_hadd_ps(tmp2, tmp2);
  84. }
  85.  
  86. __m128i _mm_cvtepi16_epi32_emu(const __m128i& a)
  87. {
  88.                 #if CRY_PLATFORM_DURANGO || CRY_PLATFORM_ORBIS
  89.         return _mm_cvtepi16_epi32(a);
  90.                 #else
  91.         // 5 instructions (unpack, and, cmp, and, or). Idea is to fill 0xFFFF in the hi-word if the sign bit of the lo-word 1.
  92.         const __m128i signBitsMask = _mm_set1_epi32(0x00008000);
  93.         const __m128i hiWordBitMask = _mm_set1_epi32(0xFFFF0000);
  94.  
  95.         // Unsigned conversion, upper word will be 0x0000 even if sign bit is set
  96.         const __m128i unpacked = _mm_unpacklo_epi16(a, _mm_set1_epi16(0));
  97.  
  98.         // Mask out sign bits
  99.         const __m128i signBitsMasked = _mm_castps_si128(_mm_and_ps(_mm_castsi128_ps(unpacked), _mm_castsi128_ps(signBitsMask)));
  100.  
  101.         // Sets dwords to 0xFFFFFFFF if sign bit is 1
  102.         const __m128i cmpBits = _mm_cmpeq_epi32(signBitsMasked, signBitsMask);
  103.  
  104.         // Mask dwords to 0xFFFF0000 if sign bit was set
  105.         const __m128i signExtendBits = _mm_and_si128(hiWordBitMask, cmpBits);
  106.  
  107.         // Finally sign extend with 0xFFFF0000 if sign bit was set
  108.         return _mm_or_si128(unpacked, signExtendBits);
  109.                 #endif
  110. }
  111.         #endif
  112.  
  113. void DecodeAndInterpolateTangents(const uint numVertices, const float lerpFactor, const GeomCacheFile::QTangent* __restrict pFloorQTangents,
  114.                                   const GeomCacheFile::QTangent* __restrict pCeilQTangents, strided_pointer<SPipTangents> pTangents)
  115. {
  116.         #if CRY_PLATFORM_WINDOWS || CRY_PLATFORM_DURANGO || CRY_PLATFORM_ORBIS
  117.         const uint numVerticesPerIteration = 2;
  118.         const uint numSIMDIterations = numVertices / numVerticesPerIteration;
  119.  
  120.         const float kMultiplier = float((2 << (GeomCacheFile::kTangentQuatPrecision - 1)) - 1);
  121.         const __m128 convertFromUint16FactorPacked = _mm_set1_ps(1.0f / kMultiplier);
  122.         const __m128 lerpFactorPacked = _mm_set1_ps(lerpFactor);
  123.         const __m128i zero = _mm_setzero_si128();
  124.         const __m128 flipSignMask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
  125.         const __m128 scaleToInt16Factor = _mm_setr_ps(32767.0f, 32767.0f, 32767.0f, 32767.0f);
  126.  
  127.         __m128i* pFloorQTangents128 = (__m128i*)&pFloorQTangents[0];
  128.         __m128i* pCeilQTangents128 = (__m128i*)&pCeilQTangents[0];
  129.         __m128i* pTangents128 = (__m128i*)pTangents.data;
  130.  
  131.         for (unsigned int i = 0, j = 0; i < numSIMDIterations; ++i, j += 2)
  132.         {
  133.                 const __m128i floorQTangents = _mm_load_si128(pFloorQTangents128 + i);
  134.                 const __m128i ceilQTangents = _mm_load_si128(pCeilQTangents128 + i);
  135.  
  136.                 // Unpack to lo/hi qTangents and convert to float [-1, 1]
  137.                 __m128 floorLo = _mm_mul_ps(_mm_cvtepi32_ps(_mm_cvtepi16_epi32_emu(floorQTangents)), convertFromUint16FactorPacked);
  138.                 __m128 floorHi = _mm_mul_ps(_mm_cvtepi32_ps(_mm_cvtepi16_epi32_emu(_mm_shuffle_epi32(floorQTangents, _MM_SHUFFLE(1, 0, 3, 2)))), convertFromUint16FactorPacked);
  139.                 __m128 ceilLo = _mm_mul_ps(_mm_cvtepi32_ps(_mm_cvtepi16_epi32_emu(ceilQTangents)), convertFromUint16FactorPacked);
  140.                 __m128 ceilHi = _mm_mul_ps(_mm_cvtepi32_ps(_mm_cvtepi16_epi32_emu(_mm_shuffle_epi32(ceilQTangents, _MM_SHUFFLE(1, 0, 3, 2)))), convertFromUint16FactorPacked);
  141.  
  142.                 // Need to flip sign of the ceil quaternion if the dot product of floor and ceil < 0
  143.                 __m128 dotLo = _mm_dp_ps_emu(floorLo, ceilLo);
  144.                 __m128 dotCmpLo = _mm_cmplt_ps(dotLo, _mm_castsi128_ps(zero));
  145.                 __m128 flipSignLo = _mm_and_ps(dotCmpLo, flipSignMask);
  146.                 ceilLo = _mm_xor_ps(ceilLo, flipSignLo);
  147.  
  148.                 __m128 dotHi = _mm_dp_ps_emu(floorHi, ceilHi);
  149.                 __m128 dotCmpHi = _mm_cmplt_ps(dotHi, _mm_castsi128_ps(zero));
  150.                 __m128 flipSignHi = _mm_and_ps(dotCmpHi, flipSignMask);
  151.                 ceilHi = _mm_xor_ps(ceilHi, flipSignHi);
  152.  
  153.                 // Interpolate the quaternions
  154.                 __m128 interpolatedLo = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(ceilLo, floorLo), lerpFactorPacked), floorLo);
  155.                 __m128 interpolatedHi = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(ceilHi, floorHi), lerpFactorPacked), floorHi);
  156.  
  157.                 // Normalize
  158.                 interpolatedLo = _mm_mul_ps(_mm_rsqrt_ps(_mm_dp_ps_emu(interpolatedLo, interpolatedLo)), interpolatedLo);
  159.                 interpolatedHi = _mm_mul_ps(_mm_rsqrt_ps(_mm_dp_ps_emu(interpolatedHi, interpolatedHi)), interpolatedHi);
  160.  
  161.                 // Convert to tangent/bitangent pairs
  162.                 __m128 tangentLo, bitangentLo, tangentHi, bitangentHi;
  163.                 ConvertToTangentAndBitangentVec4f(interpolatedLo, floorLo, tangentLo, bitangentLo);
  164.                 ConvertToTangentAndBitangentVec4f(interpolatedHi, floorHi, tangentHi, bitangentHi);
  165.  
  166.                 // Scale and convert to int
  167.                 __m128i tangentIntLo = _mm_cvtps_epi32(_mm_mul_ps(tangentLo, scaleToInt16Factor));
  168.                 __m128i bitangentIntLo = _mm_cvtps_epi32(_mm_mul_ps(bitangentLo, scaleToInt16Factor));
  169.                 __m128i tangentIntHi = _mm_cvtps_epi32(_mm_mul_ps(tangentHi, scaleToInt16Factor));
  170.                 __m128i bitangentIntHi = _mm_cvtps_epi32(_mm_mul_ps(bitangentHi, scaleToInt16Factor));
  171.  
  172.                 // Pack
  173.                 __m128i tangentBitangentLo = _mm_packs_epi32(tangentIntLo, bitangentIntLo);
  174.                 __m128i tangentBitangentHi = _mm_packs_epi32(tangentIntHi, bitangentIntHi);
  175.  
  176.                 // And finally store
  177.                 _mm_store_si128(pTangents128 + j, tangentBitangentLo);
  178.                 _mm_store_si128(pTangents128 + j + 1, tangentBitangentHi);
  179.         }
  180.  
  181.         const uint scalarStart = numSIMDIterations * numVerticesPerIteration;
  182.         #else
  183.         const uint scalarStart = 0;
  184.         #endif
  185.         for (unsigned int i = scalarStart; i < numVertices; ++i)
  186.         {
  187.                 const Quat decodedFloorQTangent = DecodeQTangent(pFloorQTangents[i]);
  188.                 const Quat decodedCeilQTangent = DecodeQTangent(pCeilQTangents[i]);
  189.  
  190.                 Quat interpolatedQTangent = Quat::CreateNlerp(decodedFloorQTangent, decodedCeilQTangent, lerpFactor);
  191.  
  192.                 if ((interpolatedQTangent.w < 0.0f) != (decodedFloorQTangent.w < 0.0f))
  193.                 {
  194.                         interpolatedQTangent = -interpolatedQTangent;
  195.                 }
  196.  
  197.                 ConvertToTangentAndBitangent(interpolatedQTangent, pTangents[i]);
  198.         }
  199. }
  200.  
  201. template<bool bConstantColors, bool bAnimatedColors, bool bConstantTexcoords>
  202. void DecodeAndInterpolateColorAndTexcoords(SGeomCacheRenderMeshUpdateContext& updateContext, const uint index,
  203.                                            const SGeomCacheStaticMeshData& staticMeshData, uint32 fpLerpFactor, const float lerpFactor,
  204.                                            const GeomCacheFile::Color* __restrict pFloorReds, const GeomCacheFile::Color* __restrict pCeilReds,
  205.                                            const GeomCacheFile::Color* __restrict pFloorGreens, const GeomCacheFile::Color* __restrict pCeilGreens,
  206.                                            const GeomCacheFile::Color* __restrict pFloorBlues, const GeomCacheFile::Color* __restrict pCeilBlues,
  207.                                            const GeomCacheFile::Color* __restrict pFloorAlphas, const GeomCacheFile::Color* __restrict pCeilAlphas,
  208.                                            const GeomCacheFile::Texcoords* __restrict pFloorTexcoords, const GeomCacheFile::Texcoords* __restrict pCeilTexcoords)
  209. {
  210.         if (!bConstantColors && !bAnimatedColors)
  211.         {
  212.                 updateContext.m_pColors[index].dcolor = 0xFFFFFFFF;
  213.         }
  214.         else if (bConstantColors)
  215.         {
  216.                 updateContext.m_pColors[index].bcolor[0] = staticMeshData.m_colors[index].bcolor[0];
  217.                 updateContext.m_pColors[index].bcolor[1] = staticMeshData.m_colors[index].bcolor[1];
  218.                 updateContext.m_pColors[index].bcolor[2] = staticMeshData.m_colors[index].bcolor[2];
  219.                 updateContext.m_pColors[index].bcolor[3] = staticMeshData.m_colors[index].bcolor[3];
  220.         }
  221.         else if (bAnimatedColors)
  222.         {
  223.                 updateContext.m_pColors[index].bcolor[0] = FixedPointColorLerp(pFloorBlues[index], pCeilBlues[index], fpLerpFactor);
  224.                 updateContext.m_pColors[index].bcolor[1] = FixedPointColorLerp(pFloorGreens[index], pCeilGreens[index], fpLerpFactor);
  225.                 updateContext.m_pColors[index].bcolor[2] = FixedPointColorLerp(pFloorReds[index], pCeilReds[index], fpLerpFactor);
  226.                 updateContext.m_pColors[index].bcolor[3] = FixedPointColorLerp(pFloorAlphas[index], pCeilAlphas[index], fpLerpFactor);
  227.         }
  228.  
  229.         if (bConstantTexcoords)
  230.         {
  231.                 updateContext.m_pTexcoords[index] = staticMeshData.m_texcoords[index];
  232.         }
  233.         else
  234.         {
  235.                 updateContext.m_pTexcoords[index] = Vec2::CreateLerp(DecodeTexcoord(pFloorTexcoords[index]), DecodeTexcoord(pCeilTexcoords[index]), lerpFactor);
  236.         }
  237. }
  238.  
  239. template<uint Permutation>
  240. void DecodeMeshVerticesBranchless(SGeomCacheRenderMeshUpdateContext& updateContext,
  241.                                   const SGeomCacheStaticMeshData& staticMeshData, const char* pFloorFrameDataPtr,
  242.                                   const char* pCeilFrameDataPtr, const float lerpFactor)
  243. {
  244.         const unsigned int numVertices = staticMeshData.m_numVertices;
  245.         const int32 fpLerpFactor = int32(lerpFactor * 65535.0f);
  246.  
  247.         const bool bMotionBlur = Permutation % (2 * 2 * 2 * 3) >= (2 * 2 * 3);
  248.         const bool bConstantPositions = Permutation % (2 * 2 * 3) >= (2 * 3);
  249.         const bool bConstantTexcoords = (Permutation % (2 * 3)) >= 3;
  250.         const bool bConstantColors = (Permutation % 3) == 1;
  251.         const bool bAnimatedColors = (Permutation % 3) == 2;
  252.  
  253.         const Vec3& aabbMin = staticMeshData.m_aabb.min;
  254.         const Vec3 aabbSize = staticMeshData.m_aabb.GetSize();
  255.  
  256.         const GeomCacheFile::Position* __restrict pFloorPositions = bConstantPositions ? NULL :
  257.                                                                     reinterpret_cast<const GeomCacheFile::Position*>(pFloorFrameDataPtr);
  258.         const GeomCacheFile::Position* __restrict pCeilPositions = bConstantPositions ? NULL :
  259.                                                                    reinterpret_cast<const GeomCacheFile::Position*>(pCeilFrameDataPtr);
  260.         pFloorFrameDataPtr += bConstantPositions ? 0 : ((numVertices * sizeof(GeomCacheFile::Position) + 15) & ~15);
  261.         pCeilFrameDataPtr += bConstantPositions ? 0 : ((numVertices * sizeof(GeomCacheFile::Position) + 15) & ~15);
  262.  
  263.         const GeomCacheFile::Texcoords* __restrict pFloorTexcoords = bConstantTexcoords ? NULL :
  264.                                                                      reinterpret_cast<const GeomCacheFile::Texcoords*>(pFloorFrameDataPtr);
  265.         const GeomCacheFile::Texcoords* __restrict pCeilTexcoords = bConstantTexcoords ? NULL :
  266.                                                                     reinterpret_cast<const GeomCacheFile::Texcoords*>(pCeilFrameDataPtr);
  267.         pFloorFrameDataPtr += bConstantTexcoords ? 0 : ((numVertices * sizeof(GeomCacheFile::Texcoords) + 15) & ~15);
  268.         pCeilFrameDataPtr += bConstantTexcoords ? 0 : ((numVertices * sizeof(GeomCacheFile::Texcoords) + 15) & ~15);
  269.  
  270.         const GeomCacheFile::QTangent* __restrict pFloorQTangents = (bConstantPositions && bConstantTexcoords) ? NULL :
  271.                                                                     reinterpret_cast<const GeomCacheFile::QTangent*>(pFloorFrameDataPtr);
  272.         const GeomCacheFile::QTangent* __restrict pCeilQTangents = (bConstantPositions && bConstantTexcoords) ? NULL :
  273.                                                                    reinterpret_cast<const GeomCacheFile::QTangent*>(pCeilFrameDataPtr);
  274.         pFloorFrameDataPtr += (bConstantPositions && bConstantTexcoords) ? 0 : ((numVertices * sizeof(GeomCacheFile::QTangent) + 15) & ~15);
  275.         pCeilFrameDataPtr += (bConstantPositions && bConstantTexcoords) ? 0 : ((numVertices * sizeof(GeomCacheFile::QTangent) + 15) & ~15);
  276.  
  277.         const GeomCacheFile::Color* __restrict pFloorReds = !bAnimatedColors ? NULL :
  278.                                                             reinterpret_cast<const GeomCacheFile::Color*>(pFloorFrameDataPtr);
  279.         const GeomCacheFile::Color* __restrict pCeilReds = !bAnimatedColors ? NULL :
  280.                                                            reinterpret_cast<const GeomCacheFile::Color*>(pCeilFrameDataPtr);
  281.         pFloorFrameDataPtr += !bAnimatedColors ? 0 : ((numVertices * sizeof(GeomCacheFile::Color) + 15) & ~15);
  282.         pCeilFrameDataPtr += !bAnimatedColors ? 0 : ((numVertices * sizeof(GeomCacheFile::Color) + 15) & ~15);
  283.  
  284.         const GeomCacheFile::Color* __restrict pFloorGreens = !bAnimatedColors ? NULL :
  285.                                                               reinterpret_cast<const GeomCacheFile::Color*>(pFloorFrameDataPtr);
  286.         const GeomCacheFile::Color* __restrict pCeilGreens = !bAnimatedColors ? NULL :
  287.                                                              reinterpret_cast<const GeomCacheFile::Color*>(pCeilFrameDataPtr);
  288.         pFloorFrameDataPtr += !bAnimatedColors ? 0 : ((numVertices * sizeof(GeomCacheFile::Color) + 15) & ~15);
  289.         pCeilFrameDataPtr += !bAnimatedColors ? 0 : ((numVertices * sizeof(GeomCacheFile::Color) + 15) & ~15);
  290.  
  291.         const GeomCacheFile::Color* __restrict pFloorBlues = !bAnimatedColors ? NULL :
  292.                                                              reinterpret_cast<const GeomCacheFile::Color*>(pFloorFrameDataPtr);
  293.         const GeomCacheFile::Color* __restrict pCeilBlues = !bAnimatedColors ? NULL :
  294.                                                             reinterpret_cast<const GeomCacheFile::Color*>(pCeilFrameDataPtr);
  295.         pFloorFrameDataPtr += !bAnimatedColors ? 0 : ((numVertices * sizeof(GeomCacheFile::Color) + 15) & ~15);
  296.         pCeilFrameDataPtr += !bAnimatedColors ? 0 : ((numVertices * sizeof(GeomCacheFile::Color) + 15) & ~15);
  297.  
  298.         const GeomCacheFile::Color* __restrict pFloorAlphas = !bAnimatedColors ? NULL :
  299.                                                               reinterpret_cast<const GeomCacheFile::Color*>(pFloorFrameDataPtr);
  300.         const GeomCacheFile::Color* __restrict pCeilAlphas = !bAnimatedColors ? NULL :
  301.                                                              reinterpret_cast<const GeomCacheFile::Color*>(pCeilFrameDataPtr);
  302.         pFloorFrameDataPtr += !bAnimatedColors ? 0 : ((numVertices * sizeof(GeomCacheFile::Color) + 15) & ~15);
  303.         pCeilFrameDataPtr += !bAnimatedColors ? 0 : ((numVertices * sizeof(GeomCacheFile::Color) + 15) & ~15);
  304.  
  305.         const Vec3 posConvertFactor = Vec3(1.0f / float((2 << (staticMeshData.m_positionPrecision[0] - 1)) - 1),
  306.                                            1.0f / float((2 << (staticMeshData.m_positionPrecision[1] - 1)) - 1),
  307.                                            1.0f / float((2 << (staticMeshData.m_positionPrecision[2] - 1)) - 1));
  308.  
  309.         #if CRY_PLATFORM_WINDOWS || CRY_PLATFORM_DURANGO || CRY_PLATFORM_ORBIS
  310.         const uint numVerticesPerIteration = 8;
  311.         const uint numPackedFloatsPerIteration = (numVerticesPerIteration * sizeof(Vec3)) / 16;
  312.         const uint numPackedUInt16PerIteration = (numVerticesPerIteration * sizeof(Vec3_tpl<uint16> )) / 16;
  313.         const uint numFloatsPerIteration = numVerticesPerIteration * (sizeof(Vec3) / sizeof(float));
  314.         const uint numFloatsPerPack = 4;
  315.         const uint numSIMDIterations = numVertices / numVerticesPerIteration;
  316.  
  317.         float* pPrevPositionsF = updateContext.m_prevPositions.size() > 0 ? (float*)&updateContext.m_prevPositions[0] : NULL;
  318.         float* pStaticPositionsF = staticMeshData.m_positions.size() > 0 ? (float*)&staticMeshData.m_positions[0] : NULL;
  319.         float* pVelocitiesF = (float*)&updateContext.m_pVelocities[0];
  320.         __m128i* pFloorPositions128 = (__m128i*)&pFloorPositions[0];
  321.         __m128i* pCeilPositions128 = (__m128i*)&pCeilPositions[0];
  322.  
  323.         const __m128 lerpFactorPacked = _mm_set1_ps(lerpFactor);
  324.  
  325.         __m128 convertFromUint16FactorPacked[numPackedFloatsPerIteration];
  326.         convertFromUint16FactorPacked[0] = _mm_setr_ps(posConvertFactor.x, posConvertFactor.y, posConvertFactor.z, posConvertFactor.x);
  327.         convertFromUint16FactorPacked[1] = _mm_setr_ps(posConvertFactor.y, posConvertFactor.z, posConvertFactor.x, posConvertFactor.y);
  328.         convertFromUint16FactorPacked[2] = _mm_setr_ps(posConvertFactor.z, posConvertFactor.x, posConvertFactor.y, posConvertFactor.z);
  329.         convertFromUint16FactorPacked[3] = _mm_setr_ps(posConvertFactor.x, posConvertFactor.y, posConvertFactor.z, posConvertFactor.x);
  330.         convertFromUint16FactorPacked[4] = _mm_setr_ps(posConvertFactor.y, posConvertFactor.z, posConvertFactor.x, posConvertFactor.y);
  331.         convertFromUint16FactorPacked[5] = _mm_setr_ps(posConvertFactor.z, posConvertFactor.x, posConvertFactor.y, posConvertFactor.z);
  332.  
  333.         __m128 aabbMinPacked[numPackedFloatsPerIteration];
  334.         aabbMinPacked[0] = _mm_setr_ps(aabbMin.x, aabbMin.y, aabbMin.z, aabbMin.x);
  335.         aabbMinPacked[1] = _mm_setr_ps(aabbMin.y, aabbMin.z, aabbMin.x, aabbMin.y);
  336.         aabbMinPacked[2] = _mm_setr_ps(aabbMin.z, aabbMin.x, aabbMin.y, aabbMin.z);
  337.         aabbMinPacked[3] = _mm_setr_ps(aabbMin.x, aabbMin.y, aabbMin.z, aabbMin.x);
  338.         aabbMinPacked[4] = _mm_setr_ps(aabbMin.y, aabbMin.z, aabbMin.x, aabbMin.y);
  339.         aabbMinPacked[5] = _mm_setr_ps(aabbMin.z, aabbMin.x, aabbMin.y, aabbMin.z);
  340.  
  341.         __m128 aabbSizePacked[numPackedFloatsPerIteration];
  342.         aabbSizePacked[0] = _mm_setr_ps(aabbSize.x, aabbSize.y, aabbSize.z, aabbSize.x);
  343.         aabbSizePacked[1] = _mm_setr_ps(aabbSize.y, aabbSize.z, aabbSize.x, aabbSize.y);
  344.         aabbSizePacked[2] = _mm_setr_ps(aabbSize.z, aabbSize.x, aabbSize.y, aabbSize.z);
  345.         aabbSizePacked[3] = _mm_setr_ps(aabbSize.x, aabbSize.y, aabbSize.z, aabbSize.x);
  346.         aabbSizePacked[4] = _mm_setr_ps(aabbSize.y, aabbSize.z, aabbSize.x, aabbSize.y);
  347.         aabbSizePacked[5] = _mm_setr_ps(aabbSize.z, aabbSize.x, aabbSize.y, aabbSize.z);
  348.  
  349.         __m128 newPositions[numPackedFloatsPerIteration];
  350.         __m128 oldPositions[numPackedFloatsPerIteration];
  351.  
  352.         for (unsigned int i = 0; i < numSIMDIterations; ++i)
  353.         {
  354.                 const uint floatOffset = i * numFloatsPerIteration;
  355.  
  356.                 if (bMotionBlur && !bConstantPositions)
  357.                 {
  358.                         for (uint j = 0; j < numPackedFloatsPerIteration; ++j)
  359.                         {
  360.                                 oldPositions[j] = _mm_load_ps(&pPrevPositionsF[floatOffset + j * numFloatsPerPack]);
  361.                         }
  362.                 }
  363.  
  364.                 if (bConstantPositions)
  365.                 {
  366.                         for (uint j = 0; j < numFloatsPerIteration; ++j)
  367.                         {
  368.                                 const uint index = (i * numVerticesPerIteration) + j;
  369.                                 updateContext.m_pPositions[index] = staticMeshData.m_positions[index];
  370.                         }
  371.                 }
  372.                 else if (!bConstantPositions)
  373.                 {
  374.                         const __m128i zero = _mm_setzero_si128();
  375.  
  376.                         for (uint j = 0, k = 0; j < numPackedUInt16PerIteration; ++j, k += 2)
  377.                         {
  378.                                 const uint indexLo = k;
  379.                                 const uint indexHi = k + 1;
  380.  
  381.                                 __m128i floorPositions = _mm_load_si128(pFloorPositions128 + (i * numPackedUInt16PerIteration) + j);
  382.                                 __m128i ceilPositions = _mm_load_si128(pCeilPositions128 + (i * numPackedUInt16PerIteration) + j);
  383.  
  384.                                 // Unpack and convert to float [0, 1]
  385.                                 __m128 floorLo = _mm_mul_ps(_mm_cvtepi32_ps(_mm_unpacklo_epi16(floorPositions, zero)), convertFromUint16FactorPacked[indexLo]);
  386.                                 __m128 floorHi = _mm_mul_ps(_mm_cvtepi32_ps(_mm_unpackhi_epi16(floorPositions, zero)), convertFromUint16FactorPacked[indexHi]);
  387.                                 __m128 ceilLo = _mm_mul_ps(_mm_cvtepi32_ps(_mm_unpacklo_epi16(ceilPositions, zero)), convertFromUint16FactorPacked[indexLo]);
  388.                                 __m128 ceilHi = _mm_mul_ps(_mm_cvtepi32_ps(_mm_unpackhi_epi16(ceilPositions, zero)), convertFromUint16FactorPacked[indexHi]);
  389.  
  390.                                 // Convert to [aabbMin, aabbMax] range
  391.                                 floorLo = _mm_add_ps(_mm_mul_ps(floorLo, aabbSizePacked[indexLo]), aabbMinPacked[indexLo]);
  392.                                 floorHi = _mm_add_ps(_mm_mul_ps(floorHi, aabbSizePacked[indexHi]), aabbMinPacked[indexHi]);
  393.                                 ceilLo = _mm_add_ps(_mm_mul_ps(ceilLo, aabbSizePacked[indexLo]), aabbMinPacked[indexLo]);
  394.                                 ceilHi = _mm_add_ps(_mm_mul_ps(ceilHi, aabbSizePacked[indexHi]), aabbMinPacked[indexHi]);
  395.  
  396.                                 // Interpolate
  397.                                 newPositions[indexLo] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(ceilLo, floorLo), lerpFactorPacked), floorLo);
  398.                                 newPositions[indexHi] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(ceilHi, floorHi), lerpFactorPacked), floorHi);
  399.                         }
  400.  
  401.                         // Store to scratch & prev position array
  402.                         CRY_ALIGN(16) Vec3 positionScratch[numVerticesPerIteration];
  403.                         float* __restrict pPositionScratch128 = (float*)&positionScratch[0];
  404.                         for (uint j = 0; j < numPackedFloatsPerIteration; ++j)
  405.                         {
  406.                                 _mm_store_ps(pPositionScratch128 + j * numFloatsPerPack, newPositions[j]);
  407.                                 _mm_store_ps(&pPrevPositionsF[floatOffset + j * numFloatsPerPack], newPositions[j]);
  408.                         }
  409.  
  410.                         // Scatter to position vertex stream
  411.                         for (uint j = 0; j < numVerticesPerIteration; ++j)
  412.                         {
  413.                                 const uint index = (i * numVerticesPerIteration) + j;
  414.                                 updateContext.m_pPositions[index] = positionScratch[j];
  415.                         }
  416.                 }
  417.  
  418.                 for (uint j = 0; j < numVerticesPerIteration; ++j)
  419.                 {
  420.                         const uint index = (i * numVerticesPerIteration) + j;
  421.                         DecodeAndInterpolateColorAndTexcoords<bConstantColors, bAnimatedColors, bConstantTexcoords>(updateContext, index, staticMeshData, fpLerpFactor, lerpFactor,
  422.                                                                                                                     pFloorReds, pCeilReds, pFloorGreens, pCeilGreens, pFloorBlues, pCeilBlues, pFloorAlphas, pCeilAlphas, pFloorTexcoords, pCeilTexcoords);
  423.                 }
  424.  
  425.                 if (!bMotionBlur)
  426.                 {
  427.                         __m128 zero = _mm_setzero_ps();
  428.                         for (uint j = 0; j < numPackedFloatsPerIteration; ++j)
  429.                         {
  430.                                 _mm_store_ps(&pVelocitiesF[floatOffset + j * numFloatsPerPack], zero);
  431.                         }
  432.                 }
  433.                 else if (!bConstantPositions)
  434.                 {
  435.                         for (uint j = 0; j < numPackedFloatsPerIteration; ++j)
  436.                         {
  437.                                 __m128 motionVectors = _mm_sub_ps(oldPositions[j], newPositions[j]);
  438.                                 _mm_store_ps(&pVelocitiesF[floatOffset + j * numFloatsPerPack], motionVectors);
  439.                         }
  440.                 }
  441.         }
  442.  
  443.         const uint scalarStart = numSIMDIterations * numVerticesPerIteration;
  444.         #else
  445.         const uint scalarStart = 0;
  446.         #endif
  447.  
  448.         for (unsigned int i = scalarStart; i < numVertices; ++i)
  449.         {
  450.                 Vec3 newPosition;
  451.                 Vec3 oldPosition;
  452.  
  453.                 if (bMotionBlur && !bConstantPositions)
  454.                 {
  455.                         oldPosition = updateContext.m_prevPositions[i];
  456.                 }
  457.  
  458.                 if (bConstantPositions)
  459.                 {
  460.                         newPosition = staticMeshData.m_positions[i];
  461.                 }
  462.                 else if (!bConstantPositions)
  463.                 {
  464.                         newPosition = Vec3::CreateLerp(DecodePosition(aabbMin, aabbSize, pFloorPositions[i], posConvertFactor),
  465.                                                        DecodePosition(aabbMin, aabbSize, pCeilPositions[i], posConvertFactor), lerpFactor);
  466.                 }
  467.  
  468.                 Vec3 oldPos = updateContext.m_pPositions[i];
  469.                 updateContext.m_pPositions[i] = newPosition;
  470.                 updateContext.m_prevPositions[i] = newPosition;
  471.  
  472.                 DecodeAndInterpolateColorAndTexcoords<bConstantColors, bAnimatedColors, bConstantTexcoords>(updateContext, i, staticMeshData, fpLerpFactor, lerpFactor,
  473.                                                                                                             pFloorReds, pCeilReds, pFloorGreens, pCeilGreens, pFloorBlues, pCeilBlues, pFloorAlphas, pCeilAlphas, pFloorTexcoords, pCeilTexcoords);
  474.  
  475.                 if (!bMotionBlur)
  476.                 {
  477.                         updateContext.m_pVelocities[i] = Vec3(0.0f, 0.0f, 0.0f);
  478.                 }
  479.                 else if (!bConstantPositions)
  480.                 {
  481.                         updateContext.m_pVelocities[i] = oldPosition - newPosition;
  482.                 }
  483.         }
  484.  
  485.         if (bConstantPositions && bConstantTexcoords)
  486.         {
  487.                 for (unsigned int i = 0; i < numVertices; ++i)
  488.                 {
  489.                         updateContext.m_pTangents[i] = staticMeshData.m_tangents[i];
  490.                 }
  491.         }
  492.         else
  493.         {
  494.                 DecodeAndInterpolateTangents(numVertices, lerpFactor, pFloorQTangents, pCeilQTangents, updateContext.m_pTangents);
  495.         }
  496. }
  497.  
  498. uint32 GetMeshDataSize(const SGeomCacheStaticMeshData& staticMeshData)
  499. {
  500.         const unsigned int numVertices = staticMeshData.m_numVertices;
  501.  
  502.         const GeomCacheFile::EStreams constantStreamMask = staticMeshData.m_constantStreams;
  503.         const GeomCacheFile::EStreams animatedStreamMask = staticMeshData.m_animatedStreams;
  504.  
  505.         const bool bConstantPositions = (constantStreamMask& GeomCacheFile::eStream_Positions) != 0;
  506.         const bool bConstantTexcoords = (constantStreamMask& GeomCacheFile::eStream_Texcoords) != 0;
  507.         const bool bAnimatedColors = (animatedStreamMask& GeomCacheFile::eStream_Colors) != 0;
  508.  
  509.         uint32 offset = 0;
  510.         offset += bConstantPositions ? 0 : ((numVertices * sizeof(GeomCacheFile::Position) + 15) & ~15);
  511.         offset += bConstantTexcoords ? 0 : ((numVertices * sizeof(GeomCacheFile::Texcoords) + 15) & ~15);
  512.         offset += (bConstantPositions && bConstantTexcoords) ? 0 : ((numVertices * sizeof(GeomCacheFile::QTangent) + 15) & ~15);
  513.         offset += !bAnimatedColors ? 0 : (4 * ((numVertices * sizeof(GeomCacheFile::Color) + 15) & ~15));
  514.  
  515.         return offset;
  516. }
  517.  
  518. typedef void (* TDecodeVerticesBranchlessPtr)(SGeomCacheRenderMeshUpdateContext& updateContext,
  519.                                               const SGeomCacheStaticMeshData& staticMeshData, const char* pFloorFrameDataPtr,
  520.                                               const char* pCeilFrameDataPtr, const float lerpFactor);
  521.  
  522. TDecodeVerticesBranchlessPtr pDecodeFunctions[kNumPermutations];
  523.  
  524. template<unsigned int Permutation>
  525. struct PermutationInit
  526. {
  527.         // Need two variables, because GCC otherwise complains about too many recursions
  528.         static TDecodeVerticesBranchlessPtr m_pFunction1;
  529.         static TDecodeVerticesBranchlessPtr m_pFunction2;
  530. };
  531.  
  532. template<unsigned int Permutation>
  533. TDecodeVerticesBranchlessPtr PermutationInit<Permutation>::m_pFunction1 = pDecodeFunctions[Permutation - 1]
  534.                                                                             = PermutationInit<Permutation - 1>::m_pFunction1 = &DecodeMeshVerticesBranchless<Permutation - 1>;
  535. template<> TDecodeVerticesBranchlessPtr PermutationInit<0>::m_pFunction1 = &DecodeMeshVerticesBranchless<0>;
  536.  
  537. template<unsigned int Permutation>
  538. TDecodeVerticesBranchlessPtr PermutationInit<Permutation>::m_pFunction2 = pDecodeFunctions[Permutation - 1 + (kNumPermutations / 2)]
  539.                                                                             = PermutationInit<Permutation - 1>::m_pFunction2 = &DecodeMeshVerticesBranchless<Permutation - 1 + (kNumPermutations / 2)>;
  540. template<> TDecodeVerticesBranchlessPtr PermutationInit<0>::m_pFunction2 = &DecodeMeshVerticesBranchless<(kNumPermutations / 2)>;
  541.  
  542. // This forces the instantiation of PermutationInit<kNumPermutations / 2>::m_pFunction
  543. // and therefore recursively initializes pDecodeFunctions with the DecodeVertices<N> permutations
  544. template struct PermutationInit<kNumPermutations / 2>;
  545.  
  546. void DecodeIFrame(const CGeomCache* pGeomCache, char* pData)
  547. {
  548.         // Skip header
  549.         pData += sizeof(GeomCacheFile::SFrameHeader);
  550.         const std::vector<SGeomCacheStaticMeshData>& staticMeshData = pGeomCache->GetStaticMeshData();
  551.  
  552.         const uint numMeshes = staticMeshData.size();
  553.         for (uint i = 0; i < numMeshes; ++i)
  554.         {
  555.                 const SGeomCacheStaticMeshData& currentStaticMeshData = staticMeshData[i];
  556.  
  557.                 if (currentStaticMeshData.m_animatedStreams == 0)
  558.                 {
  559.                         continue;
  560.                 }
  561.  
  562.                 const GeomCacheFile::SMeshFrameHeader* pFrameHeader = reinterpret_cast<GeomCacheFile::SMeshFrameHeader*>(pData);
  563.                 pData += sizeof(GeomCacheFile::SMeshFrameHeader);
  564.  
  565.                 const GeomCacheFile::EStreams streamMask = currentStaticMeshData.m_animatedStreams;
  566.                 const bool bUsePrediction = currentStaticMeshData.m_bUsePredictor;
  567.                 const uint numVertices = currentStaticMeshData.m_numVertices;
  568.  
  569.                 if (streamMask & GeomCacheFile::eStream_Positions)
  570.                 {
  571.                         if (bUsePrediction)
  572.                         {
  573.                                 GeomCacheFile::Position* pPositions = reinterpret_cast<GeomCacheFile::Position*>(pData);
  574.                                 GeomCachePredictors::ParallelogramPredictor<GeomCacheFile::Position, false>(numVertices, pPositions, pPositions, currentStaticMeshData.m_predictorData);
  575.                         }
  576.  
  577.                         pData += ((sizeof(GeomCacheFile::Position) * numVertices) + 15) & ~15;
  578.                 }
  579.  
  580.                 if (streamMask & GeomCacheFile::eStream_Texcoords)
  581.                 {
  582.                         if (bUsePrediction)
  583.                         {
  584.                                 GeomCacheFile::Texcoords* pTexcoords = reinterpret_cast<GeomCacheFile::Texcoords*>(pData);
  585.                                 GeomCachePredictors::ParallelogramPredictor<GeomCacheFile::Texcoords, false>(numVertices, pTexcoords, pTexcoords, currentStaticMeshData.m_predictorData);
  586.                         }
  587.  
  588.                         pData += ((sizeof(GeomCacheFile::Texcoords) * numVertices) + 15) & ~15;
  589.                 }
  590.  
  591.                 if (streamMask & GeomCacheFile::eStream_QTangents)
  592.                 {
  593.                         if (bUsePrediction)
  594.                         {
  595.                                 GeomCacheFile::QTangent* pQTangents = reinterpret_cast<GeomCacheFile::QTangent*>(pData);
  596.                                 GeomCachePredictors::QTangentPredictor<false>(numVertices, pQTangents, pQTangents, currentStaticMeshData.m_predictorData);
  597.                         }
  598.  
  599.                         pData += ((sizeof(GeomCacheFile::QTangent) * numVertices) + 15) & ~15;
  600.                 }
  601.  
  602.                 if (streamMask & GeomCacheFile::eStream_Colors)
  603.                 {
  604.                         if (bUsePrediction)
  605.                         {
  606.                                 GeomCacheFile::Color* pReds = reinterpret_cast<GeomCacheFile::Color*>(pData);
  607.                                 pData += ((sizeof(GeomCacheFile::Color) * numVertices) + 15) & ~15;
  608.                                 GeomCacheFile::Color* pGreens = reinterpret_cast<GeomCacheFile::Color*>(pData);
  609.                                 pData += ((sizeof(GeomCacheFile::Color) * numVertices) + 15) & ~15;
  610.                                 GeomCacheFile::Color* pBlues = reinterpret_cast<GeomCacheFile::Color*>(pData);
  611.                                 pData += ((sizeof(GeomCacheFile::Color) * numVertices) + 15) & ~15;
  612.                                 GeomCacheFile::Color* pAlphas = reinterpret_cast<GeomCacheFile::Color*>(pData);
  613.                                 pData += ((sizeof(GeomCacheFile::Color) * numVertices) + 15) & ~15;
  614.  
  615.                                 GeomCachePredictors::ColorPredictor<false>(numVertices, pReds, pReds, currentStaticMeshData.m_predictorData);
  616.                                 GeomCachePredictors::ColorPredictor<false>(numVertices, pGreens, pGreens, currentStaticMeshData.m_predictorData);
  617.                                 GeomCachePredictors::ColorPredictor<false>(numVertices, pBlues, pBlues, currentStaticMeshData.m_predictorData);
  618.                                 GeomCachePredictors::ColorPredictor<false>(numVertices, pAlphas, pAlphas, currentStaticMeshData.m_predictorData);
  619.                         }
  620.                         else
  621.                         {
  622.                                 pData += 4 * ((sizeof(GeomCacheFile::Color) * numVertices) + 15) & ~15;
  623.                         }
  624.                 }
  625.         }
  626. }
  627.  
  628. void DecodeBFrame(const CGeomCache* pGeomCache, char* pData, char* pPrevFramesData[2], char* pFloorIndexFrameData, char* pCeilIndexFrameData)
  629. {
  630.         // Skip header
  631.         size_t offset = sizeof(GeomCacheFile::SFrameHeader);
  632.         const std::vector<SGeomCacheStaticMeshData>& staticMeshData = pGeomCache->GetStaticMeshData();
  633.  
  634.         const uint numMeshes = staticMeshData.size();
  635.         for (uint i = 0; i < numMeshes; ++i)
  636.         {
  637.                 const SGeomCacheStaticMeshData& currentStaticMeshData = staticMeshData[i];
  638.  
  639.                 if (currentStaticMeshData.m_animatedStreams == 0)
  640.                 {
  641.                         continue;
  642.                 }
  643.  
  644.                 const GeomCacheFile::SMeshFrameHeader* pFrameHeader = reinterpret_cast<GeomCacheFile::SMeshFrameHeader*>(pData + offset);
  645.                 offset += sizeof(GeomCacheFile::SMeshFrameHeader);
  646.  
  647.                 if ((pFrameHeader->m_flags & GeomCacheFile::eFrameFlags_Hidden) != 0)
  648.                 {
  649.                         offset += GetMeshDataSize(currentStaticMeshData);
  650.                         continue;
  651.                 }
  652.  
  653.                 const GeomCacheFile::EStreams streamMask = currentStaticMeshData.m_animatedStreams;
  654.                 const uint numVertices = currentStaticMeshData.m_numVertices;
  655.  
  656.                 if (streamMask & GeomCacheFile::eStream_Positions)
  657.                 {
  658.                         GeomCacheFile::Position* pPositions = reinterpret_cast<GeomCacheFile::Position*>(pData + offset);
  659.                         GeomCachePredictors::STemporalPredictorData<GeomCacheFile::Position> predictorData;
  660.                         predictorData.m_numElements = numVertices;
  661.                         predictorData.m_pPrevFrames[0] = reinterpret_cast<GeomCacheFile::Position*>(pPrevFramesData[0] + offset);
  662.                         predictorData.m_pPrevFrames[1] = reinterpret_cast<GeomCacheFile::Position*>(pPrevFramesData[1] + offset);
  663.                         predictorData.m_pFloorFrame = reinterpret_cast<GeomCacheFile::Position*>(pFloorIndexFrameData + offset);
  664.                         predictorData.m_pCeilFrame = reinterpret_cast<GeomCacheFile::Position*>(pCeilIndexFrameData + offset);
  665.  
  666.                         typedef Vec3_tpl<uint32> I;
  667.                         GeomCachePredictors::InterpolateMotionDeltaPredictor<I, GeomCacheFile::Position, false>
  668.                           (pFrameHeader->m_positionStreamPredictorControl, predictorData, pPositions, pPositions);
  669.  
  670.                         offset += ((sizeof(GeomCacheFile::Position) * numVertices) + 15) & ~15;
  671.                 }
  672.  
  673.                 if (streamMask & GeomCacheFile::eStream_Texcoords)
  674.                 {
  675.                         GeomCacheFile::Texcoords* pTexcoords = reinterpret_cast<GeomCacheFile::Texcoords*>(pData + offset);
  676.                         GeomCachePredictors::STemporalPredictorData<GeomCacheFile::Texcoords> predictorData;
  677.                         predictorData.m_numElements = numVertices;
  678.                         predictorData.m_pPrevFrames[0] = reinterpret_cast<GeomCacheFile::Texcoords*>(pPrevFramesData[0] + offset);
  679.                         predictorData.m_pPrevFrames[1] = reinterpret_cast<GeomCacheFile::Texcoords*>(pPrevFramesData[1] + offset);
  680.                         predictorData.m_pFloorFrame = reinterpret_cast<GeomCacheFile::Texcoords*>(pFloorIndexFrameData + offset);
  681.                         predictorData.m_pCeilFrame = reinterpret_cast<GeomCacheFile::Texcoords*>(pCeilIndexFrameData + offset);
  682.  
  683.                         typedef Vec2_tpl<uint32> I;
  684.                         GeomCachePredictors::InterpolateMotionDeltaPredictor<I, GeomCacheFile::Texcoords, false>
  685.                           (pFrameHeader->m_texcoordStreamPredictorControl, predictorData, pTexcoords, pTexcoords);
  686.  
  687.                         offset += ((sizeof(GeomCacheFile::Texcoords) * numVertices) + 15) & ~15;
  688.                 }
  689.  
  690.                 if (streamMask & GeomCacheFile::eStream_QTangents)
  691.                 {
  692.                         GeomCacheFile::QTangent* pQTangents = reinterpret_cast<GeomCacheFile::QTangent*>(pData + offset);
  693.                         GeomCachePredictors::STemporalPredictorData<GeomCacheFile::QTangent> predictorData;
  694.                         predictorData.m_numElements = numVertices;
  695.                         predictorData.m_pPrevFrames[0] = reinterpret_cast<GeomCacheFile::QTangent*>(pPrevFramesData[0] + offset);
  696.                         predictorData.m_pPrevFrames[1] = reinterpret_cast<GeomCacheFile::QTangent*>(pPrevFramesData[1] + offset);
  697.                         predictorData.m_pFloorFrame = reinterpret_cast<GeomCacheFile::QTangent*>(pFloorIndexFrameData + offset);
  698.                         predictorData.m_pCeilFrame = reinterpret_cast<GeomCacheFile::QTangent*>(pCeilIndexFrameData + offset);
  699.  
  700.                         typedef Vec4_tpl<uint32> I;
  701.                         GeomCachePredictors::InterpolateMotionDeltaPredictor<I, GeomCacheFile::QTangent, false>
  702.                           (pFrameHeader->m_qTangentStreamPredictorControl, predictorData, pQTangents, pQTangents);
  703.  
  704.                         offset += ((sizeof(GeomCacheFile::QTangent) * numVertices) + 15) & ~15;
  705.                 }
  706.  
  707.                 if (streamMask & GeomCacheFile::eStream_Colors)
  708.                 {
  709.                         GeomCachePredictors::STemporalPredictorData<GeomCacheFile::Color> predictorData;
  710.                         typedef uint16 I;
  711.  
  712.                         GeomCacheFile::Color* pReds = reinterpret_cast<GeomCacheFile::Color*>(pData + offset);
  713.                         predictorData.m_numElements = numVertices;
  714.                         predictorData.m_pPrevFrames[0] = reinterpret_cast<GeomCacheFile::Color*>(pPrevFramesData[0] + offset);
  715.                         predictorData.m_pPrevFrames[1] = reinterpret_cast<GeomCacheFile::Color*>(pPrevFramesData[1] + offset);
  716.                         predictorData.m_pFloorFrame = reinterpret_cast<GeomCacheFile::Color*>(pFloorIndexFrameData + offset);
  717.                         predictorData.m_pCeilFrame = reinterpret_cast<GeomCacheFile::Color*>(pCeilIndexFrameData + offset);
  718.  
  719.                         GeomCachePredictors::InterpolateMotionDeltaPredictor<I, GeomCacheFile::Color, false>
  720.                           (pFrameHeader->m_colorStreamPredictorControl[0], predictorData, pReds, pReds);
  721.  
  722.                         offset += ((sizeof(GeomCacheFile::Color) * numVertices) + 15) & ~15;
  723.  
  724.                         GeomCacheFile::Color* pGreens = reinterpret_cast<GeomCacheFile::Color*>(pData + offset);
  725.                         predictorData.m_numElements = numVertices;
  726.                         predictorData.m_pPrevFrames[0] = reinterpret_cast<GeomCacheFile::Color*>(pPrevFramesData[0] + offset);
  727.                         predictorData.m_pPrevFrames[1] = reinterpret_cast<GeomCacheFile::Color*>(pPrevFramesData[1] + offset);
  728.                         predictorData.m_pFloorFrame = reinterpret_cast<GeomCacheFile::Color*>(pFloorIndexFrameData + offset);
  729.                         predictorData.m_pCeilFrame = reinterpret_cast<GeomCacheFile::Color*>(pCeilIndexFrameData + offset);
  730.  
  731.                         GeomCachePredictors::InterpolateMotionDeltaPredictor<I, GeomCacheFile::Color, false>
  732.                           (pFrameHeader->m_colorStreamPredictorControl[1], predictorData, pGreens, pGreens);
  733.  
  734.                         offset += ((sizeof(GeomCacheFile::Color) * numVertices) + 15) & ~15;
  735.  
  736.                         GeomCacheFile::Color* pBlues = reinterpret_cast<GeomCacheFile::Color*>(pData + offset);
  737.                         predictorData.m_numElements = numVertices;
  738.                         predictorData.m_pPrevFrames[0] = reinterpret_cast<GeomCacheFile::Color*>(pPrevFramesData[0] + offset);
  739.                         predictorData.m_pPrevFrames[1] = reinterpret_cast<GeomCacheFile::Color*>(pPrevFramesData[1] + offset);
  740.                         predictorData.m_pFloorFrame = reinterpret_cast<GeomCacheFile::Color*>(pFloorIndexFrameData + offset);
  741.                         predictorData.m_pCeilFrame = reinterpret_cast<GeomCacheFile::Color*>(pCeilIndexFrameData + offset);
  742.  
  743.                         GeomCachePredictors::InterpolateMotionDeltaPredictor<I, GeomCacheFile::Color, false>
  744.                           (pFrameHeader->m_colorStreamPredictorControl[2], predictorData, pBlues, pBlues);
  745.  
  746.                         offset += ((sizeof(GeomCacheFile::Color) * numVertices) + 15) & ~15;
  747.  
  748.                         GeomCacheFile::Color* pAlphas = reinterpret_cast<GeomCacheFile::Color*>(pData + offset);
  749.                         predictorData.m_numElements = numVertices;
  750.                         predictorData.m_pPrevFrames[0] = reinterpret_cast<GeomCacheFile::Color*>(pPrevFramesData[0] + offset);
  751.                         predictorData.m_pPrevFrames[1] = reinterpret_cast<GeomCacheFile::Color*>(pPrevFramesData[1] + offset);
  752.                         predictorData.m_pFloorFrame = reinterpret_cast<GeomCacheFile::Color*>(pFloorIndexFrameData + offset);
  753.                         predictorData.m_pCeilFrame = reinterpret_cast<GeomCacheFile::Color*>(pCeilIndexFrameData + offset);
  754.  
  755.                         GeomCachePredictors::InterpolateMotionDeltaPredictor<I, GeomCacheFile::Color, false>
  756.                           (pFrameHeader->m_colorStreamPredictorControl[3], predictorData, pAlphas, pAlphas);
  757.  
  758.                         offset += ((sizeof(GeomCacheFile::Color) * numVertices) + 15) & ~15;
  759.                 }
  760.         }
  761. }
  762.  
  763. bool PrepareFillMeshData(SGeomCacheRenderMeshUpdateContext& updateContext, const SGeomCacheStaticMeshData& staticMeshData,
  764.                          const char*& pFloorFrameMeshData, const char*& pCeilFrameMeshData, size_t& offsetToNextMesh, float& lerpFactor)
  765. {
  766.         const GeomCacheFile::SMeshFrameHeader* pFloorHeader = reinterpret_cast<const GeomCacheFile::SMeshFrameHeader* const>(pFloorFrameMeshData);
  767.         const GeomCacheFile::SMeshFrameHeader* pCeilHeader = reinterpret_cast<const GeomCacheFile::SMeshFrameHeader* const>(pCeilFrameMeshData);
  768.  
  769.         pFloorFrameMeshData += sizeof(GeomCacheFile::SMeshFrameHeader);
  770.         pCeilFrameMeshData += sizeof(GeomCacheFile::SMeshFrameHeader);
  771.  
  772.         const bool bFloorFrameHidden = (pFloorHeader->m_flags & GeomCacheFile::eFrameFlags_Hidden) != 0;
  773.         const bool bCeilFrameHidden = (pCeilHeader->m_flags & GeomCacheFile::eFrameFlags_Hidden) != 0;
  774.  
  775.         offsetToNextMesh = GetMeshDataSize(staticMeshData);
  776.  
  777.         if (bFloorFrameHidden && bCeilFrameHidden)
  778.         {
  779.                 return false;
  780.         }
  781.         else if (bFloorFrameHidden)
  782.         {
  783.                 lerpFactor = 1.0f;
  784.         }
  785.         else if (bCeilFrameHidden)
  786.         {
  787.                 lerpFactor = 0.0f;
  788.         }
  789.  
  790.         if (Cry3DEngineBase::m_pCVars->e_GeomCacheLerpBetweenFrames == 0)
  791.         {
  792.                 pCeilFrameMeshData = pFloorFrameMeshData;
  793.                 lerpFactor = 0.0f;
  794.         }
  795.  
  796.         return true;
  797. }
  798.  
  799. void FillMeshDataFromDecodedFrame(const bool bMotionBlur, SGeomCacheRenderMeshUpdateContext& updateContext,
  800.                                   const SGeomCacheStaticMeshData& staticMeshData, const char* pFloorFrameMeshData, const char* pCeilFrameMeshData, float lerpFactor)
  801. {
  802.         // Fetch indices from static data
  803.         const uint numIndices = staticMeshData.m_indices.size();
  804.         for (uint i = 0; i < numIndices; ++i)
  805.         {
  806.                 updateContext.m_pIndices[i] = staticMeshData.m_indices[i];
  807.         }
  808.  
  809.         const uint permutation = GetDecodeVerticesPerm(bMotionBlur, staticMeshData.m_constantStreams, staticMeshData.m_animatedStreams);
  810.         TDecodeVerticesBranchlessPtr pDecodeFunction = pDecodeFunctions[permutation];
  811.         (*pDecodeFunction)(updateContext, staticMeshData, pFloorFrameMeshData, pCeilFrameMeshData, lerpFactor);
  812. }
  813.  
  814. Vec3 DecodePosition(const Vec3& aabbMin, const Vec3& aabbSize, const GeomCacheFile::Position& inPosition, const Vec3& convertFactor)
  815. {
  816.         return Vec3(aabbMin.x + ((float)inPosition.x * convertFactor.x) * aabbSize.x,
  817.                     aabbMin.y + ((float)inPosition.y * convertFactor.y) * aabbSize.y,
  818.                     aabbMin.z + ((float)inPosition.z * convertFactor.z) * aabbSize.z);
  819. }
  820.  
  821. Vec2 DecodeTexcoord(const GeomCacheFile::Texcoords& inTexcoords)
  822. {
  823.         const float convertFromInt16Factor = 1.0f / 32767.0f;
  824.  
  825.         return Vec2((float)inTexcoords.x * convertFromInt16Factor * GeomCacheFile::kTexcoordRange,
  826.                     (float)inTexcoords.y * convertFromInt16Factor * GeomCacheFile::kTexcoordRange);
  827. }
  828.  
  829. Quat DecodeQTangent(const GeomCacheFile::QTangent& inQTangent)
  830. {
  831.         const float kMultiplier = float((2 << (GeomCacheFile::kTangentQuatPrecision - 1)) - 1);
  832.         const float convertFromInt16Factor = 1.0f / kMultiplier;
  833.  
  834.         return Quat((float)inQTangent.w * convertFromInt16Factor, (float)inQTangent.x * convertFromInt16Factor,
  835.                     (float)inQTangent.y * convertFromInt16Factor, (float)inQTangent.z * convertFromInt16Factor);
  836. }
  837.  
  838. void TransformAndConvertToTangentAndBitangent(const Quat& rotation, const Quat& inQTangent, SPipTangents& outTangents)
  839. {
  840.         int16 reflection = alias_cast<uint32>(inQTangent.w) & 0x80000000 ? -1 : +1;
  841.         Quat transformedQTangent = rotation * inQTangent;
  842.  
  843.         outTangents = SPipTangents(transformedQTangent, reflection);
  844. }
  845.  
  846. void ConvertToTangentAndBitangent(const Quat& inQTangent, SPipTangents& outTangents)
  847. {
  848.         int16 reflection = alias_cast<uint32>(inQTangent.w) & 0x80000000 ? -1 : +1;
  849.  
  850.         outTangents = SPipTangents(inQTangent, reflection);
  851. }
  852.  
  853. uint32 GetDecompressBufferSize(const char* const pStartBlock, const unsigned int numFrames)
  854. {
  855.         FUNCTION_PROFILER_3DENGINE;
  856.  
  857.         uint32 totalUncompressedSize = 0;
  858.         const char* pCurrentBlock = pStartBlock;
  859.  
  860.         const uint32 headersSize = ((sizeof(SGeomCacheFrameHeader) * numFrames) + 15) & ~15;
  861.  
  862.         for (unsigned int i = 0; i < numFrames; ++i)
  863.         {
  864.                 const GeomCacheFile::SCompressedBlockHeader* pBlockHeader = reinterpret_cast<const GeomCacheFile::SCompressedBlockHeader*>(pCurrentBlock);
  865.                 pCurrentBlock += sizeof(GeomCacheFile::SCompressedBlockHeader) + pBlockHeader->m_compressedSize;
  866.                 totalUncompressedSize += pBlockHeader->m_uncompressedSize;
  867.         }
  868.  
  869.         uint32 totalSize = headersSize + totalUncompressedSize;
  870.         if (totalSize % 16 != 0)
  871.         {
  872.                 CryFatalError("GetDecompressBufferSize mod 16 != 0");
  873.         }
  874.  
  875.         return totalSize;
  876. }
  877.  
  878. bool DecompressBlock(const GeomCacheFile::EBlockCompressionFormat compressionFormat, char* const pDest, const char* const pSource)
  879. {
  880.         FUNCTION_PROFILER_3DENGINE;
  881.  
  882.         const GeomCacheFile::SCompressedBlockHeader* const pBlockHeader = reinterpret_cast<const GeomCacheFile::SCompressedBlockHeader* const>(pSource);
  883.         const char* const pBlockData = reinterpret_cast<const char* const>(pSource + sizeof(GeomCacheFile::SCompressedBlockHeader));
  884.  
  885.         if (compressionFormat == GeomCacheFile::eBlockCompressionFormat_None)
  886.         {
  887.                 assert(pBlockHeader->m_compressedSize == pBlockHeader->m_uncompressedSize);
  888.                 memcpy(const_cast<char*>(pDest), pSource + sizeof(GeomCacheFile::SCompressedBlockHeader), pBlockHeader->m_uncompressedSize);
  889.         }
  890.         else if (compressionFormat == GeomCacheFile::eBlockCompressionFormat_Deflate)
  891.         {
  892.                 IZLibInflateStream* pInflateStream = GetISystem()->GetIZLibDecompressor()->CreateInflateStream();
  893.  
  894.                 pInflateStream->SetOutputBuffer(const_cast<char*>(pDest), pBlockHeader->m_uncompressedSize);
  895.                 pInflateStream->Input(pBlockData, pBlockHeader->m_compressedSize);
  896.                 pInflateStream->EndInput();
  897.                 EZInflateState state = pInflateStream->GetState();
  898.                 assert(state == eZInfState_Finished);
  899.                 pInflateStream->Release();
  900.  
  901.                 if (state == eZInfState_Error)
  902.                 {
  903.                         return false;
  904.                 }
  905.         }
  906.         else if (compressionFormat == GeomCacheFile::eBlockCompressionFormat_LZ4HC)
  907.         {
  908.                 ILZ4Decompressor* pDecompressor = GetISystem()->GetLZ4Decompressor();
  909.                 return pDecompressor->DecompressData(pBlockData, const_cast<char*>(pDest), pBlockHeader->m_uncompressedSize);
  910.         }
  911.         else
  912.         {
  913.                 return false;
  914.         }
  915.  
  916.         return true;
  917. }
  918.  
  919. bool DecompressBlocks(const GeomCacheFile::EBlockCompressionFormat compressionFormat, char* const pDest,
  920.                       const char* const pSource, const uint blockOffset, const uint numBlocks, const uint numHandleFrames)
  921. {
  922.         FUNCTION_PROFILER_3DENGINE;
  923.  
  924.         const char* pCurrentSource = pSource;
  925.         const uint32 headersSize = ((sizeof(SGeomCacheFrameHeader) * numHandleFrames) + 15) & ~15;
  926.         char* pCurrentDest = pDest + headersSize;
  927.  
  928.         for (uint i = 0; i < blockOffset; ++i)
  929.         {
  930.                 const GeomCacheFile::SCompressedBlockHeader* const pBlockHeader = reinterpret_cast<const GeomCacheFile::SCompressedBlockHeader* const>(pCurrentSource);
  931.                 pCurrentSource += sizeof(GeomCacheFile::SCompressedBlockHeader) + pBlockHeader->m_compressedSize;
  932.                 pCurrentDest += pBlockHeader->m_uncompressedSize;
  933.         }
  934.  
  935.         for (uint i = blockOffset; i < blockOffset + numBlocks; ++i)
  936.         {
  937.                 const GeomCacheFile::SCompressedBlockHeader* const pBlockHeader = reinterpret_cast<const GeomCacheFile::SCompressedBlockHeader* const>(pCurrentSource);
  938.  
  939.                 if (!DecompressBlock(compressionFormat, pCurrentDest, pCurrentSource))
  940.                 {
  941.                         return false;
  942.                 }
  943.  
  944.                 SGeomCacheFrameHeader* pHeader = reinterpret_cast<SGeomCacheFrameHeader*>(pDest + i * sizeof(SGeomCacheFrameHeader));
  945.                 pHeader->m_offset = static_cast<uint32>(pCurrentDest - pDest);
  946.                 pHeader->m_state = SGeomCacheFrameHeader::eFHS_Undecoded;
  947.  
  948.                 pCurrentSource += sizeof(GeomCacheFile::SCompressedBlockHeader) + pBlockHeader->m_compressedSize;
  949.                 pCurrentDest += pBlockHeader->m_uncompressedSize;
  950.         }
  951.  
  952.         return true;
  953. }
  954. }
  955.  
  956. #endif
  957.  
downloadGeomCacheDecoder.cpp 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