BVB Source Codes

CRYENGINE Show VolumeObjectDataCreate.cpp Source code

Return Download CRYENGINE: download VolumeObjectDataCreate.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4.  
  5. #include "VolumeObjectDataCreate.h"
  6.  
  7. #include <vector>
  8. #include <math.h>
  9.  
  10. #pragma warning(disable: 4244)
  11.  
  12. namespace
  13. {
  14. //////////////////////////////////////////////////////////////////////////
  15. // Coherent noise function over 1, 2 or 3 dimensions
  16.  
  17. #define B  0x100
  18. #define BM 0xff
  19. #define N  0x1000
  20. #define NP 12     /* 2^N */
  21. #define NM 0xfff
  22.  
  23. #define s_curve(t)      (t * t * (3. - 2. * t))
  24. #define lerp(t, a, b)   (a + t * (b - a))
  25. #define setup(i, b0, b1, r0, r1) \
  26.   t = vec[i] + N;                \
  27.   b0 = ((int)t) & BM;            \
  28.   b1 = (b0 + 1) & BM;            \
  29.   r0 = t - (int)t;               \
  30.   r1 = r0 - 1.;
  31. #define at2(rx, ry)     (rx * q[0] + ry * q[1])
  32. #define at3(rx, ry, rz) (rx * q[0] + ry * q[1] + rz * q[2])
  33.  
  34. void init(void);
  35. //double noise1(double);
  36. //double noise2(double *);
  37. double noise3(double*);
  38. //void normalize2(double *);
  39. void   normalize3(double*);
  40.  
  41. //double PerlinNoise1D(double,double,double,int);
  42. //double PerlinNoise2D(double,double,double,double,int);
  43. double PerlinNoise3D(double, double, double, double, double, int);
  44.  
  45. static int pp[B + B + 2];
  46. //static double g1[B + B + 2];
  47. //static double g2[B + B + 2][2];
  48. static double g3[B + B + 2][3];
  49. static int start = 1;
  50.  
  51. //double noise1(double arg)
  52. //{
  53. //      int bx0, bx1;
  54. //      double rx0, rx1, sx, t, u, v, vec[1];
  55.  
  56. //      vec[0] = arg;
  57. //      if (start) {
  58. //              start = 0;
  59. //              init();
  60. //      }
  61.  
  62. //      setup(0,bx0,bx1,rx0,rx1);
  63.  
  64. //      sx = s_curve(rx0);
  65. //      u = rx0 * g1[ p[ bx0 ] ];
  66. //      v = rx1 * g1[ p[ bx1 ] ];
  67.  
  68. //      return(lerp(sx, u, v));
  69. //}
  70.  
  71. //double noise2(double vec[2])
  72. //{
  73. //      int bx0, bx1, by0, by1, b00, b10, b01, b11;
  74. //      double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
  75. //      int i, j;
  76.  
  77. //      if (start) {
  78. //              start = 0;
  79. //              init();
  80. //      }
  81.  
  82. //      setup(0, bx0,bx1, rx0,rx1);
  83. //      setup(1, by0,by1, ry0,ry1);
  84.  
  85. //      i = p[ bx0 ];
  86. //      j = p[ bx1 ];
  87.  
  88. //      b00 = p[ i + by0 ];
  89. //      b10 = p[ j + by0 ];
  90. //      b01 = p[ i + by1 ];
  91. //      b11 = p[ j + by1 ];
  92.  
  93. //      sx = s_curve(rx0);
  94. //      sy = s_curve(ry0);
  95.  
  96. //      q = g2[ b00 ] ; u = at2(rx0,ry0);
  97. //      q = g2[ b10 ] ; v = at2(rx1,ry0);
  98. //      a = lerp(sx, u, v);
  99.  
  100. //      q = g2[ b01 ] ; u = at2(rx0,ry1);
  101. //      q = g2[ b11 ] ; v = at2(rx1,ry1);
  102. //      b = lerp(sx, u, v);
  103.  
  104. //      return lerp(sy, a, b);
  105. //}
  106.  
  107. double noise3(double vec[3])
  108. {
  109.         int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
  110.         double rx0, rx1, ry0, ry1, rz0, rz1, * q, sy, sz, a, b, c, d, t, u, v;
  111.         int i, j;
  112.  
  113.         if (start)
  114.         {
  115.                 start = 0;
  116.                 init();
  117.         }
  118.  
  119.         setup(0, bx0, bx1, rx0, rx1);
  120.         setup(1, by0, by1, ry0, ry1);
  121.         setup(2, bz0, bz1, rz0, rz1);
  122.  
  123.         i = pp[bx0];
  124.         j = pp[bx1];
  125.  
  126.         b00 = pp[i + by0];
  127.         b10 = pp[j + by0];
  128.         b01 = pp[i + by1];
  129.         b11 = pp[j + by1];
  130.  
  131.         t = s_curve(rx0);
  132.         sy = s_curve(ry0);
  133.         sz = s_curve(rz0);
  134.  
  135.         q = g3[b00 + bz0];
  136.         u = at3(rx0, ry0, rz0);
  137.         q = g3[b10 + bz0];
  138.         v = at3(rx1, ry0, rz0);
  139.         a = lerp(t, u, v);
  140.  
  141.         q = g3[b01 + bz0];
  142.         u = at3(rx0, ry1, rz0);
  143.         q = g3[b11 + bz0];
  144.         v = at3(rx1, ry1, rz0);
  145.         b = lerp(t, u, v);
  146.  
  147.         c = lerp(sy, a, b);
  148.  
  149.         q = g3[b00 + bz1];
  150.         u = at3(rx0, ry0, rz1);
  151.         q = g3[b10 + bz1];
  152.         v = at3(rx1, ry0, rz1);
  153.         a = lerp(t, u, v);
  154.  
  155.         q = g3[b01 + bz1];
  156.         u = at3(rx0, ry1, rz1);
  157.         q = g3[b11 + bz1];
  158.         v = at3(rx1, ry1, rz1);
  159.         b = lerp(t, u, v);
  160.  
  161.         d = lerp(sy, a, b);
  162.  
  163.         return lerp(sz, c, d);
  164. }
  165.  
  166. //void normalize2(double v[2])
  167. //{
  168. //      double s;
  169.  
  170. //      s = sqrt(v[0] * v[0] + v[1] * v[1]);
  171. //      v[0] = v[0] / s;
  172. //      v[1] = v[1] / s;
  173. //}
  174.  
  175. void normalize3(double v[3])
  176. {
  177.         double s;
  178.  
  179.         s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
  180.         v[0] = v[0] / s;
  181.         v[1] = v[1] / s;
  182.         v[2] = v[2] / s;
  183. }
  184.  
  185. void init(void)
  186. {
  187.         int i, j, k;
  188.  
  189.         for (i = 0; i < B; i++)
  190.         {
  191.                 pp[i] = i;
  192.                 //g1[i] = (double)((cry_rand() % (B + B)) - B) / B;
  193.  
  194.                 //for (j = 0 ; j < 2 ; j++)
  195.                 //      g2[i][j] = (double)((cry_rand() % (B + B)) - B) / B;
  196.                 //normalize2(g2[i]);
  197.  
  198.                 for (j = 0; j < 3; j++)
  199.                         g3[i][j] = cry_random(-1.0f, 1.0f);
  200.                 normalize3(g3[i]);
  201.         }
  202.  
  203.         while (--i)
  204.         {
  205.                 k = pp[i];
  206.                 pp[i] = pp[j = cry_random(0, B - 1)];
  207.                 pp[j] = k;
  208.         }
  209.  
  210.         for (i = 0; i < B + 2; i++)
  211.         {
  212.                 pp[B + i] = pp[i];
  213.                 //g1[B + i] = g1[i];
  214.                 //for (j = 0 ; j < 2 ; j++)
  215.                 //      g2[B + i][j] = g2[i][j];
  216.                 for (j = 0; j < 3; j++)
  217.                         g3[B + i][j] = g3[i][j];
  218.         }
  219. }
  220.  
  221. /* --- My harmonic summing functions - PDB --------------------------*/
  222.  
  223. /*
  224.    In what follows "alpha" is the weight when the sum is formed.
  225.    Typically it is 2, As this approaches 1 the function is noisier.
  226.    "beta" is the harmonic scaling/spacing, typically 2.
  227.  */
  228.  
  229. //double PerlinNoise1D(double x,double alpha,double beta,int n)
  230. //{
  231. //      int i;
  232. //      double val,sum = 0;
  233. //      double p,scale = 1;
  234.  
  235. //      p = x;
  236. //      for (i=0;i<n;i++) {
  237. //              val = noise1(p);
  238. //              sum += val / scale;
  239. //              scale *= alpha;
  240. //              p *= beta;
  241. //      }
  242. //      return(sum);
  243. //}
  244.  
  245. //double PerlinNoise2D(double x,double y,double alpha,double beta,int n)
  246. //{
  247. //      int i;
  248. //      double val,sum = 0;
  249. //      double p[2],scale = 1;
  250.  
  251. //      p[0] = x;
  252. //      p[1] = y;
  253. //      for (i=0;i<n;i++) {
  254. //              val = noise2(p);
  255. //              sum += val / scale;
  256. //              scale *= alpha;
  257. //              p[0] *= beta;
  258. //              p[1] *= beta;
  259. //      }
  260. //      return(sum);
  261. //}
  262.  
  263. double PerlinNoise3D(double x, double y, double z, double alpha, double beta, int n)
  264. {
  265.         int i;
  266.         double val, sum = 0;
  267.         double p[3], scale = 1;
  268.  
  269.         p[0] = x;
  270.         p[1] = y;
  271.         p[2] = z;
  272.         for (i = 0; i < n; i++)
  273.         {
  274.                 val = noise3(p);
  275.                 sum += val / scale;
  276.                 scale *= alpha;
  277.                 p[0] *= beta;
  278.                 p[1] *= beta;
  279.                 p[2] *= beta;
  280.         }
  281.         return(sum);
  282. }
  283.  
  284. #undef B
  285. #undef BM
  286. #undef N
  287. #undef NP
  288. #undef NM
  289.  
  290. //////////////////////////////////////////////////////////////////////////
  291.  
  292. struct VolumeParticle
  293. {
  294.         Vec3  p;
  295.         float r;
  296.  
  297.         VolumeParticle()
  298.                 : p(0, 0, 0)
  299.                 , r(0)
  300.         {
  301.         }
  302. };
  303.  
  304. typedef std::vector<VolumeParticle> VolumeDesc;
  305.  
  306. //////////////////////////////////////////////////////////////////////////
  307.  
  308. bool ReadVolumeDescription(const char* pFilePath, VolumeDesc& volDesc, float& globalDensity)
  309. {
  310.         volDesc.clear();
  311.         globalDensity = 1;
  312.  
  313.         XmlNodeRef root(gEnv->pSystem->LoadXmlFromFile(pFilePath));
  314.         if (root)
  315.         {
  316.                 int numSprites(root->getChildCount());
  317.                 if (numSprites > 0)
  318.                 {
  319.                         root->getAttr("Density", globalDensity);
  320.                         globalDensity = clamp_tpl(globalDensity, 0.0f, 1.0f);
  321.  
  322.                         volDesc.reserve(numSprites);
  323.                         for (int i(0); i < numSprites; ++i)
  324.                         {
  325.                                 XmlNodeRef child(root->getChild(i));
  326.                                 if (child)
  327.                                 {
  328.                                         VolumeParticle vp;
  329.                                         child->getAttr("Pos", vp.p);
  330.                                         child->getAttr("Radius", vp.r);
  331.                                         volDesc.push_back(vp);
  332.                                 }
  333.                         }
  334.                 }
  335.         }
  336.  
  337.         return !volDesc.empty();
  338. }
  339.  
  340. //////////////////////////////////////////////////////////////////////////
  341.  
  342. void CalcBoundingBox(const VolumeDesc& volDesc, AABB& bbox)
  343. {
  344.         bbox.Reset();
  345.  
  346.         if (volDesc.empty())
  347.                 return;
  348.  
  349.         for (size_t i = 0; i < volDesc.size(); ++i)
  350.                 bbox.Add(volDesc[i].p, volDesc[i].r);
  351. }
  352.  
  353. //////////////////////////////////////////////////////////////////////////
  354.  
  355. void CalcTightBounds(const AABB& bbox, AABB& tightBounds, float& scale)
  356. {
  357.         float max = bbox.max.x - bbox.min.x;
  358.  
  359.         if (bbox.max.y - bbox.min.y > max)
  360.                 max = bbox.max.y - bbox.min.y;
  361.  
  362.         if (bbox.max.z - bbox.min.z > max)
  363.                 max = bbox.max.z - bbox.min.z;
  364.  
  365.         tightBounds.min.x = -(bbox.max.x - bbox.min.x) / max;
  366.         tightBounds.max.x = (bbox.max.x - bbox.min.x) / max;
  367.  
  368.         tightBounds.min.y = -(bbox.max.y - bbox.min.y) / max;
  369.         tightBounds.max.y = (bbox.max.y - bbox.min.y) / max;
  370.  
  371.         tightBounds.min.z = -(bbox.max.z - bbox.min.z) / max;
  372.         tightBounds.max.z = (bbox.max.z - bbox.min.z) / max;
  373.  
  374.         scale = max * 0.5f;
  375. }
  376.  
  377. //////////////////////////////////////////////////////////////////////////
  378.  
  379. void AdjustBoundingBox(AABB& bbox)
  380. {
  381.         float max = bbox.max.x - bbox.min.x;
  382.  
  383.         if (bbox.max.y - bbox.min.y > max)
  384.                 max = bbox.max.y - bbox.min.y;
  385.  
  386.         if (bbox.max.z - bbox.min.z > max)
  387.                 max = bbox.max.z - bbox.min.z;
  388.  
  389.         float adj = (max - (bbox.max.x - bbox.min.x)) * 0.5f;
  390.         bbox.min.x -= adj;
  391.         bbox.max.x += adj;
  392.  
  393.         adj = (max - (bbox.max.y - bbox.min.y)) * 0.5f;
  394.         bbox.min.y -= adj;
  395.         bbox.max.y += adj;
  396.  
  397.         adj = (max - (bbox.max.z - bbox.min.z)) * 0.5f;
  398.         bbox.min.z -= adj;
  399.         bbox.max.z += adj;
  400. }
  401.  
  402. //////////////////////////////////////////////////////////////////////////
  403.  
  404. inline uint8 TrilinearFilteredLookup(const SVolumeDataSrcB& density, const float lx, const float ly, const float lz)
  405. {
  406.         if (lx < 0 || ly < 0 || lz < 0)
  407.                 return 0;
  408.  
  409.         int x = (int) lx;
  410.         int y = (int) ly;
  411.         int z = (int) lz;
  412.  
  413.         if (x > (int)density.m_width - 2 || y > (int)density.m_height - 2 || z > (int)density.m_depth - 2)
  414.                 return 0;
  415.  
  416.         const uint8* src = &density[density.Idx(x, y, z)];
  417.  
  418.         int lerpX = (int) ((lx - x) * 256.0f);
  419.         int lerpY = (int) ((ly - y) * 256.0f);
  420.         int lerpZ = (int) ((lz - z) * 256.0f);
  421.  
  422.         int _s000 = src[0];
  423.         int _s001 = src[1];
  424.         int _s010 = src[density.m_width];
  425.         int _s011 = src[1 + density.m_width];
  426.  
  427.         src += density.m_slice;
  428.  
  429.         int _s100 = src[0];
  430.         int _s101 = src[1];
  431.         int _s110 = src[density.m_width];
  432.         int _s111 = src[1 + density.m_width];
  433.  
  434.         int s00 = (_s000 << 8) + (_s001 - _s000) * lerpX;
  435.         int s01 = (_s010 << 8) + (_s011 - _s010) * lerpX;
  436.         int s0 = ((s00 << 8) + (s01 - s00) * lerpY) >> 8;
  437.  
  438.         int s10 = (_s100 << 8) + (_s101 - _s100) * lerpX;
  439.         int s11 = (_s110 << 8) + (_s111 - _s110) * lerpX;
  440.         int s1 = ((s10 << 8) + (s11 - s10) * lerpY) >> 8;
  441.  
  442.         return ((s0 << 8) + (s1 - s0) * lerpZ) >> 16;
  443. }
  444.  
  445. inline int sat(int f)
  446. {
  447.         return (f < 0) ? 0 : ((f > 255) ? 255 : f);
  448. }
  449.  
  450. void Voxelize(const VolumeDesc& volDesc, float globalDensity, const AABB& bbox, SVolumeDataSrcB& trg)
  451. {
  452.         SVolumeDataSrcB tmp(trg.m_width + 2, trg.m_height + 2, trg.m_depth + 2);
  453.  
  454.         // clear temporary volume
  455.         for (size_t i(0); i < tmp.size(); ++i)
  456.                 tmp[i] = 0;
  457.  
  458.         // rasterize spheres
  459.         for (size_t i = 0; i < volDesc.size(); ++i)
  460.         {
  461.                 const VolumeParticle& vp(volDesc[i]);
  462.  
  463.                 int sz = (int) floor((float) (trg.m_depth - 1) * ((vp.p.z - vp.r) - bbox.min.z) / (bbox.max.z - bbox.min.z));
  464.                 int ez = (int) ceil((float) (trg.m_depth - 1) * ((vp.p.z + vp.r) - bbox.min.z) / (bbox.max.z - bbox.min.z));
  465.  
  466.                 int sy = (int) floor((float) (trg.m_height - 1) * ((vp.p.y - vp.r) - bbox.min.y) / (bbox.max.y - bbox.min.y));
  467.                 int ey = (int) ceil((float) (trg.m_height - 1) * ((vp.p.y + vp.r) - bbox.min.y) / (bbox.max.y - bbox.min.y));
  468.  
  469.                 int sx = (int) floor((float) (trg.m_width - 1) * ((vp.p.x - vp.r) - bbox.min.x) / (bbox.max.x - bbox.min.x));
  470.                 int ex = (int) ceil((float) (trg.m_width - 1) * ((vp.p.x + vp.r) - bbox.min.x) / (bbox.max.x - bbox.min.x));
  471.  
  472.                 float stepZ = (bbox.max.z - bbox.min.z) / (float) trg.m_depth;
  473.                 float wz = vp.p.z - (bbox.min.z + ((float) sz + 0.5f) * stepZ);
  474.  
  475.                 for (int z = sz; z <= ez; ++z, wz -= stepZ)
  476.                 {
  477.                         float dz2 = wz * wz;
  478.  
  479.                         float stepY = (bbox.max.y - bbox.min.y) / (float) trg.m_height;
  480.                         float wy = vp.p.y - (bbox.min.y + ((float) sy + 0.5f) * stepY);
  481.  
  482.                         for (int y = sy; y <= ey; ++y, wy -= stepY)
  483.                         {
  484.                                 float dy2 = wy * wy;
  485.  
  486.                                 float stepX = (bbox.max.x - bbox.min.x) / (float) trg.m_width;
  487.                                 float wx = vp.p.x - (bbox.min.x + ((float) sx + 0.5f) * stepX);
  488.  
  489.                                 size_t idx = tmp.Idx(sx + 1, y + 1, z + 1);
  490.                                 for (int x = sx; x <= ex; ++x, wx -= stepX, ++idx)
  491.                                 {
  492.                                         float dx2 = wx * wx;
  493.                                         float d = sqrt_tpl(dx2 + dy2 + dz2);
  494.                                         float v = max(1.0f - d / vp.r, 0.0f) * globalDensity;
  495.                                         tmp[idx] = max(tmp[idx], (uint8) (v * 255.0f));
  496.                                 }
  497.                         }
  498.                 }
  499.         }
  500.  
  501.         // perturb volume using Perlin noise
  502.         {
  503.                 float stepGx = 5.0f / (float) trg.m_width;
  504.                 float stepGy = 5.0f / (float) trg.m_height;
  505.                 float stepGz = 5.0f / (float) trg.m_depth;
  506.  
  507.                 const float origBias = 0.25f;
  508.                 const float origFillDens = 1.2f;
  509.  
  510.                 const uint8 bias = (uint8) (origBias * 256.0f);
  511.                 const uint32 biasNorm = (uint32) (256.0f * 256.0f * (origFillDens / (1.0f - origBias)));
  512.  
  513.                 size_t idx = 0;
  514.  
  515.                 float nz = 0;
  516.                 float gz = 0;
  517.                 for (unsigned int z = 0; z < trg.m_depth; ++z, nz += 1.0f, gz += stepGz)
  518.                 {
  519.                         float ny = 0;
  520.                         float gy = 0;
  521.                         for (unsigned int y = 0; y < trg.m_height; ++y, ny += 1.0f, gy += stepGy)
  522.                         {
  523.                                 float nx = 0;
  524.                                 float gx = 0;
  525.                                 for (unsigned int x = 0; x < trg.m_width; ++x, nx += 1.0f, gx += stepGx, ++idx)
  526.                                 {
  527.                                         float gtx = (float)nx + 5.0f * PerlinNoise3D(gx, gy, gz, 2.0f, 2.1525f, 5);
  528.                                         float gty = (float)ny + 5.0f * PerlinNoise3D(gx + 21.132f, gy, gz, 2.0f, 2.1525f, 5);
  529.                                         float gtz = (float)nz + 5.0f * PerlinNoise3D(gx, gy + 3.412f, gz, 2.0f, 2.1525f, 5);
  530.  
  531.                                         //float val = (float) TrilinearFilteredLookup(tmp, gtx + 1.0f, gty + 1.0f, gtz + 1.0f) / 255.0f;
  532.                                         //trg[idx] = (uint8) (saturate(saturate(val - origBias) / (1.0f - origBias) * origFillDens) * 255.0f);
  533.  
  534.                                         uint8 val = TrilinearFilteredLookup(tmp, gtx + 1.0f, gty + 1.0f, gtz + 1.0f);
  535.                                         trg[idx] = sat(sat(val - bias) * biasNorm >> 16);
  536.  
  537.                                         //trg[idx] = (uint8) TrilinearFilteredLookup(tmp, gtx + 1.0f, gty + 1.0f, gtz + 1.0f);
  538.                                 }
  539.                         }
  540.                 }
  541.         }
  542.  
  543.         //// low pass filter
  544.         //{
  545.         //      {
  546.         //              size_t srcIdx = 0;
  547.         //              for (unsigned int z = 0; z < trg.m_depth; ++z)
  548.         //              {
  549.         //                      for (unsigned int y = 0; y < trg.m_height; ++y)
  550.         //                      {
  551.         //                              size_t dstIdx = tmp.Idx(1, y+1, z+1);
  552.         //                              for (unsigned int x = 0; x < trg.m_width; ++x, ++srcIdx, ++dstIdx)
  553.         //                                      tmp[dstIdx] = trg[srcIdx];
  554.         //                      }
  555.         //              }
  556.         //      }
  557.         //      {
  558.         //              size_t dstIdx = 0;
  559.         //              for (unsigned int z = 0; z < trg.m_depth; ++z)
  560.         //              {
  561.         //                      for (unsigned int y = 0; y < trg.m_height; ++y)
  562.         //                      {
  563.         //                              const uint8* src = &tmp[tmp.Idx(1, y+1, z+1)];
  564.         //                              for (unsigned int x = 0; x < trg.m_width; ++x, ++dstIdx, ++src)
  565.         //                              {
  566.         //                                      const uint8* srcRow1 = src - tmp.m_slice - 1;
  567.         //                                      const uint8* srcRow0 = srcRow1 - tmp.m_width;
  568.         //                                      const uint8* srcRow2 = srcRow1 + tmp.m_width;
  569.  
  570.         //                                      uint32 sum = 0;
  571.         //                                      sum += srcRow0[0] + srcRow0[1] + srcRow0[2];
  572.         //                                      sum += srcRow1[0] + (srcRow1[1] << 1) + srcRow1[2];
  573.         //                                      sum += srcRow2[0] + srcRow2[1] + srcRow2[2];
  574.  
  575.         //                                      srcRow0 += tmp.m_slice;
  576.         //                                      srcRow1 += tmp.m_slice;
  577.         //                                      srcRow2 += tmp.m_slice;
  578.  
  579.         //                                      sum += srcRow0[0] + (srcRow0[1] << 1) + srcRow0[2];
  580.         //                                      sum += (srcRow1[0] << 1) + (srcRow1[1] << 4) + (srcRow1[2] << 1);
  581.         //                                      sum += srcRow2[0] + (srcRow2[1] << 1) + srcRow2[2];
  582.  
  583.         //                                      srcRow0 += tmp.m_slice;
  584.         //                                      srcRow1 += tmp.m_slice;
  585.         //                                      srcRow2 += tmp.m_slice;
  586.  
  587.         //                                      sum += srcRow0[0] + srcRow0[1] + srcRow0[2];
  588.         //                                      sum += srcRow1[0] + (srcRow1[1] << 1) + srcRow1[2];
  589.         //                                      sum += srcRow2[0] + srcRow2[1] + srcRow2[2];
  590.  
  591.         //                                      const uint32 weight = 65536 / 48;
  592.         //                                      sum *= weight;
  593.         //                                      sum >>= 16;
  594.  
  595.         //                                      trg[dstIdx] = sum;
  596.         //                              }
  597.         //                      }
  598.         //              }
  599.         //      }
  600.         //}
  601. }
  602.  
  603. //////////////////////////////////////////////////////////////////////////
  604. /*
  605.    void DumpAsRAW(SVolumeDataSrcB& v, const char* name)
  606.    {
  607.     FILE* f(fopen(name, "wb"));
  608.  
  609.     if (f)
  610.     {
  611.       for (unsigned int y = 0; y < 64; ++y)
  612.       {
  613.         for (unsigned int z = 0; z < 64; ++z)
  614.         {
  615.           for (unsigned int x = 0; x < 64; ++x)
  616.           {
  617.             uint8 val = v[v.Idx(x,y,z)];
  618.  
  619.             fwrite(&val, 1, 1, f);
  620.           }
  621.         }
  622.       }
  623.       fclose(f);
  624.     }
  625.    }
  626.  */
  627. //////////////////////////////////////////////////////////////////////////
  628.  
  629. inline void PerPixelFilteredLookup(uint8* pShadow, const uint8* pDensity, const int s00, const int s01,
  630.                                    const int s10, const int s11, const int lerpX, const int lerpY, const int shadowStrength)
  631. {
  632.         int _s00 = pShadow[s00];
  633.         int _s01 = pShadow[s01];
  634.         int _s10 = pShadow[s10];
  635.         int _s11 = pShadow[s11];
  636.  
  637.         int s0 = (_s00 << 8) + (_s01 - _s00) * lerpX;
  638.         int s1 = (_s10 << 8) + (_s11 - _s10) * lerpX;
  639.         int s = ((s0 << 8) + (s1 - s0) * lerpY) >> 8;
  640.         //int d = *pDensity * 103; // 103 = 0.4 * 256.0
  641.         int d = *pDensity * shadowStrength;
  642.  
  643.         // todo: store data 1-
  644.         //*pShadow = fastround_positive(s * (1.0f - 0.2f * d));
  645.         *pShadow = s * (65280 - d) >> 24;   // 65280 = 1.0 * 255 * 256
  646. }
  647.  
  648. //shadow is propagated from one slice to the next
  649. inline void PerSliceFilteredLookup(uint8* pShadow, const uint8* pDensity, const int duOffset, const int dvOffset,
  650.                                    const int s00, const int s01, const int s10, const int s11, const int lerpX, const int lerpY, const int shadowStrength)
  651. {
  652.         for (int v = 0; v < VOLUME_SHADOW_SIZE - 1; ++v)
  653.                 for (int u = 0; u < VOLUME_SHADOW_SIZE - 1; ++u)
  654.                 {
  655.                         int offset(duOffset * u + dvOffset * v);
  656.                         PerPixelFilteredLookup(&pShadow[offset], &pDensity[offset], s00, s01, s10, s11, lerpX, lerpY, shadowStrength);
  657.                 }
  658. }
  659.  
  660. inline void PerBlockFilteredLookup(uint8* pShadow, const uint8* pDensity, const int duOffset, const int dvOffset,
  661.                                    const int dwOffset, const int s00, const int s01, const int s10, const int s11, const int lerpX, const int lerpY, const int shadowStrength)
  662. {
  663.         for (int w = 1; w < VOLUME_SHADOW_SIZE; ++w)
  664.         {
  665.                 int offset(dwOffset * w);
  666.                 PerSliceFilteredLookup(&pShadow[offset], &pDensity[offset], duOffset, dvOffset, s00, s01, s10, s11, lerpX, lerpY, shadowStrength);
  667.         }
  668. }
  669.  
  670. } // anonymous namespace
  671.  
  672. bool CreateVolumeObject(const char* filePath, SVolumeDataSrcB& trg, AABB& tightBounds, float& scale)
  673. {
  674.         VolumeDesc volDesc;
  675.         float globalDensity(1);
  676.         if (ReadVolumeDescription(filePath, volDesc, globalDensity))
  677.         {
  678.                 AABB bbox;
  679.  
  680.                 CalcBoundingBox(volDesc, bbox);
  681.                 CalcTightBounds(bbox, tightBounds, scale);
  682.                 AdjustBoundingBox(bbox);
  683.                 Voxelize(volDesc, globalDensity, bbox, trg);
  684.                 //DumpAsRAW(trg, "E:\\TestDensity.raw");
  685.                 return true;
  686.         }
  687.  
  688.         return false;
  689. }
  690.  
  691. bool CreateVolumeShadow(const Vec3& lightDir, float shadowStrength, const SVolumeDataSrcB& density, SVolumeDataSrcB& shadows)
  692. {
  693.         for (size_t i(0); i < shadows.size(); ++i)
  694.                 shadows[i] = 255;
  695.  
  696.         if (density.m_width != VOLUME_SHADOW_SIZE || density.m_height != VOLUME_SHADOW_SIZE || density.m_depth != VOLUME_SHADOW_SIZE ||
  697.             shadows.m_width != VOLUME_SHADOW_SIZE || shadows.m_height != VOLUME_SHADOW_SIZE || shadows.m_depth != VOLUME_SHADOW_SIZE)
  698.         {
  699.                 assert(!"CreateVolumeShadow() -- density and/or shadow volume has invalid dimension!");
  700.                 return false;
  701.         }
  702.  
  703.         float sun[3] = { lightDir.x, lightDir.y, lightDir.z };
  704.  
  705.         int majAxis = 0;
  706.         {
  707.                 float abssun[3] = { fabsf(sun[0]), fabsf(sun[1]), fabsf(sun[2]) };
  708.  
  709.                 if (abssun[1] > abssun[0])
  710.                         majAxis = 1;
  711.                 if (abssun[2] > abssun[majAxis])
  712.                         majAxis = 2;
  713.  
  714.                 // project direction onto the -1..1 cube sides
  715.                 float fInv = 1.0f / abssun[majAxis];
  716.  
  717.                 sun[0] *= fInv;
  718.                 sun[1] *= fInv;
  719.                 sun[2] *= fInv;
  720.         }
  721.  
  722.         int du[3] = { 0 };
  723.         int dv[3] = { 0 };
  724.         int dw[3] = { 0 };
  725.  
  726.         int w = 0;
  727.  
  728.         if (sun[majAxis] > 0)
  729.         {
  730.                 dw[majAxis] = 1;
  731.         }
  732.         else
  733.         {
  734.                 dw[majAxis] = -1;
  735.                 w = VOLUME_SHADOW_SIZE - 1;
  736.         }
  737.  
  738.         int secAxis = (majAxis + 1) % 3;
  739.         int thirdAxis = (majAxis + 2) % 3;
  740.  
  741.         du[secAxis] = 1;
  742.         dv[thirdAxis] = 1;
  743.  
  744.         int duOffset = du[0] + (du[1] + du[2] * VOLUME_SHADOW_SIZE) * VOLUME_SHADOW_SIZE;
  745.         int dvOffset = dv[0] + (dv[1] + dv[2] * VOLUME_SHADOW_SIZE) * VOLUME_SHADOW_SIZE;
  746.         int dwOffset = dw[0] + (dw[1] + dw[2] * VOLUME_SHADOW_SIZE) * VOLUME_SHADOW_SIZE;
  747.  
  748.         float lerpX = sun[secAxis];
  749.         float lerpY = sun[thirdAxis];
  750.  
  751.         //if(sun[majAxis]>0)
  752.         {
  753.                 lerpX = -lerpX;
  754.                 lerpY = -lerpY;
  755.         }
  756.  
  757.         int prevSliceOffset = -dwOffset;
  758.         int offset = -w * dwOffset;
  759.  
  760.         if (lerpX < 0)
  761.         {
  762.                 lerpX += 1.0f;
  763.                 prevSliceOffset -= duOffset;
  764.                 offset += duOffset;
  765.         }
  766.  
  767.         if (lerpY < 0)
  768.         {
  769.                 lerpY += 1.0f;
  770.                 prevSliceOffset -= dvOffset;
  771.                 offset += dvOffset;
  772.         }
  773.  
  774.         PerBlockFilteredLookup(&shadows[offset], &density[offset], duOffset, dvOffset, dwOffset,
  775.                                prevSliceOffset, duOffset + prevSliceOffset, dvOffset + prevSliceOffset, duOffset + dvOffset + prevSliceOffset,
  776.                                (int) (lerpX * 256.0f), (int) (lerpY * 256.0f), (int) (clamp_tpl(shadowStrength, 0.0f, 1.0f) * 256.0f));
  777.  
  778.         return true;
  779. }
  780.  
  781. bool CreateDownscaledVolumeObject(const SVolumeDataSrcB& src, SVolumeDataSrcB& trg)
  782. {
  783.         if (src.m_width != 2 * trg.m_width || src.m_height != 2 * trg.m_height || src.m_depth != 2 * trg.m_height)
  784.         {
  785.                 for (size_t i(0); i < trg.size(); ++i)
  786.                         trg[i] = 255;
  787.  
  788.                 assert(!"CreateDownscaledVolumeObject() -- src and/or trg volume has invalid dimension!");
  789.                 return false;
  790.         }
  791.  
  792.         for (unsigned int z = 0; z < trg.m_depth; ++z)
  793.         {
  794.                 for (unsigned int y = 0; y < trg.m_height; ++y)
  795.                 {
  796.                         for (unsigned int x = 0; x < trg.m_width; ++x)
  797.                         {
  798.                                 trg[trg.Idx(x, y, z)] = (uint8) (0.125f * (src[src.Idx(2 * x, 2 * y, 2 * z)] +
  799.                                                                            src[src.Idx(2 * x + 1, 2 * y, 2 * z)] +
  800.                                                                            src[src.Idx(2 * x, 2 * y + 1, 2 * z)] +
  801.                                                                            src[src.Idx(2 * x + 1, 2 * y + 1, 2 * z)] +
  802.                                                                            src[src.Idx(2 * x, 2 * y, 2 * z + 1)] +
  803.                                                                            src[src.Idx(2 * x + 1, 2 * y, 2 * z + 1)] +
  804.                                                                            src[src.Idx(2 * x, 2 * y + 1, 2 * z + 1)] +
  805.                                                                            src[src.Idx(2 * x + 1, 2 * y + 1, 2 * z + 1)]));
  806.                         }
  807.                 }
  808.         }
  809.  
  810.         return true;
  811. }
  812.  
  813. //////////////////////////////////////////////////////////////////////////
  814.  
  815. namespace
  816. {
  817. typedef std::vector<Vec3>  Points;
  818. typedef std::vector<uint8> PointIndexCache;
  819.  
  820. bool IsPowerOfTwo(unsigned int x)
  821. {
  822.         int cnt = 0;
  823.         while (x > 0)
  824.         {
  825.                 cnt += x & 1;
  826.                 x >>= 1;
  827.         }
  828.         return cnt == 1;
  829. }
  830.  
  831. bool GeneratePoints(const SVolumeDataSrcB& src, Points& pts)
  832. {
  833.         struct SPointGenerator
  834.         {
  835.         public:
  836.                 SPointGenerator(const SVolumeDataSrcB& src, unsigned int size, Points& pts)
  837.                         : m_src(src)
  838.                         , m_pts(pts)
  839.                         , m_cache()
  840.                 {
  841.                         size_t cacheSize = (src.m_width * src.m_height * src.m_depth + 7) >> 3;
  842.                         m_cache.resize(cacheSize);
  843.  
  844.                         for (size_t i = 0; i < cacheSize; ++i)
  845.                                 m_cache[i] = 0;
  846.  
  847.                         if (Traverse(0, 0, 0, size))
  848.                                 PushPts(0, 0, 0, size);
  849.                 }
  850.  
  851.         private:
  852.                 void PushPt(unsigned int x, unsigned int y, unsigned int z)
  853.                 {
  854.                         size_t idx = m_src.Idx(x, y, z);
  855.                         if ((m_cache[idx >> 3] & (1 << (idx & 7))) == 0)
  856.                         {
  857.                                 Vec3 p;
  858.                                 p.x = 2.0f * ((float) x / (float) m_src.m_width) - 1.0f;
  859.                                 p.y = 2.0f * ((float) y / (float) m_src.m_height) - 1.0f;
  860.                                 p.z = 2.0f * ((float) z / (float) m_src.m_depth) - 1.0f;
  861.                                 assert(fabs(p.x) <= 1.0f && fabs(p.y) <= 1.0f && fabs(p.z) <= 1.0f);
  862.                                 m_pts.push_back(p);
  863.                                 m_cache[idx >> 3] |= 1 << (idx & 7);
  864.                         }
  865.                 }
  866.  
  867.                 void PushPts(unsigned int x, unsigned int y, unsigned int z, unsigned int size)
  868.                 {
  869.                         PushPt(x, y, z);
  870.                         PushPt(x + size, y, z);
  871.                         PushPt(x, y + size, z);
  872.                         PushPt(x + size, y + size, z);
  873.                         PushPt(x, y, z + size);
  874.                         PushPt(x + size, y, z + size);
  875.                         PushPt(x, y + size, z + size);
  876.                         PushPt(x + size, y + size, z + size);
  877.                 }
  878.  
  879.                 bool Traverse(unsigned int x, unsigned int y, unsigned int z, unsigned int size)
  880.                 {
  881.                         if (size == 1)
  882.                         {
  883.                                 bool isSolid = false;
  884.  
  885.                                 unsigned int zs = max((int) z - 1, 0);
  886.                                 unsigned int ze = min(z + 2, m_src.m_depth);
  887.                                 for (; zs < ze; ++zs)
  888.                                 {
  889.                                         unsigned int ys = max((int)y - 1, 0);
  890.                                         unsigned int ye = min(y + 2, m_src.m_height);
  891.                                         for (; ys < ye; ++ys)
  892.                                         {
  893.                                                 unsigned int xs = max((int)x - 1, 0);
  894.                                                 unsigned int xe = min(x + 2, m_src.m_width);
  895.                                                 for (; xs < xe; ++xs)
  896.                                                 {
  897.                                                         isSolid |= m_src[m_src.Idx(xs, ys, zs)] != 0;
  898.                                                         if (isSolid)
  899.                                                                 return true;
  900.                                                 }
  901.                                         }
  902.                                 }
  903.                                 return false;
  904.                         }
  905.  
  906.                         unsigned int ns = size >> 1;
  907.  
  908.                         bool isSolid[8];
  909.                         isSolid[0] = Traverse(x, y, z, ns);
  910.                         isSolid[1] = Traverse(x + ns, y, z, ns);
  911.                         isSolid[2] = Traverse(x, y + ns, z, ns);
  912.                         isSolid[3] = Traverse(x + ns, y + ns, z, ns);
  913.                         isSolid[4] = Traverse(x, y, z + ns, ns);
  914.                         isSolid[5] = Traverse(x + ns, y, z + ns, ns);
  915.                         isSolid[6] = Traverse(x, y + ns, z + ns, ns);
  916.                         isSolid[7] = Traverse(x + ns, y + ns, z + ns, ns);
  917.  
  918.                         bool mergeSubtrees = isSolid[0];
  919.                         for (int i = 1; i < 8; ++i)
  920.                                 mergeSubtrees &= isSolid[i];
  921.  
  922.                         if (!mergeSubtrees)
  923.                         {
  924.                                 if (isSolid[0])
  925.                                         PushPts(x, y, z, ns);
  926.                                 if (isSolid[1])
  927.                                         PushPts(x + ns, y, z, ns);
  928.                                 if (isSolid[2])
  929.                                         PushPts(x, y + ns, z, ns);
  930.                                 if (isSolid[3])
  931.                                         PushPts(x + ns, y + ns, z, ns);
  932.                                 if (isSolid[4])
  933.                                         PushPts(x, y, z + ns, ns);
  934.                                 if (isSolid[5])
  935.                                         PushPts(x + ns, y, z + ns, ns);
  936.                                 if (isSolid[6])
  937.                                         PushPts(x, y + ns, z + ns, ns);
  938.                                 if (isSolid[7])
  939.                                         PushPts(x + ns, y + ns, z + ns, ns);
  940.                         }
  941.  
  942.                         return mergeSubtrees;
  943.                 }
  944.  
  945.         private:
  946.                 const SVolumeDataSrcB& m_src;
  947.                 Points&                m_pts;
  948.                 PointIndexCache        m_cache;
  949.         };
  950.  
  951.         if (src.m_width != src.m_height || src.m_width != src.m_depth || src.m_height != src.m_depth)
  952.                 return false;
  953.  
  954.         unsigned int size = src.m_width;
  955.  
  956.         if (!IsPowerOfTwo(size))
  957.                 return false;
  958.  
  959.         SPointGenerator gen(src, size, pts);
  960.  
  961.         return true;
  962. }
  963.  
  964. void* qhmalloc(size_t s)
  965. {
  966.         return new uint8[s];
  967. }
  968.  
  969. void qhfree(void* p)
  970. {
  971.         delete[] (uint8*) p;
  972. }
  973.  
  974. } // anonymous namespace
  975.  
  976. bool CreateVolumeDataHull(const SVolumeDataSrcB& src, SVolumeDataHull& hull)
  977. {
  978.         Points pts;
  979.         if (GeneratePoints(src, pts))
  980.         {
  981.                 Vec3* pPts = &pts[0];
  982.                 size_t numPts = pts.size();
  983.  
  984.                 // compute convex hull
  985.                 index_t* pIndices = 0;
  986.                 int numTris = gEnv->pPhysicalWorld->GetPhysUtils()->qhull(pPts, (int) numPts, pIndices, qhmalloc);
  987.  
  988.                 if (pIndices)
  989.                 {
  990.                         // map used vertices
  991.                         typedef std::map<int, int> Vtx2Vtx;
  992.                         Vtx2Vtx v2v;
  993.                         for (int i = 0, idx = 0; i < numTris; ++i)
  994.                         {
  995.                                 if (v2v.find(pIndices[idx]) == v2v.end())
  996.                                         v2v.insert(Vtx2Vtx::value_type(pIndices[idx], -1));
  997.                                 ++idx;
  998.  
  999.                                 if (v2v.find(pIndices[idx]) == v2v.end())
  1000.                                         v2v.insert(Vtx2Vtx::value_type(pIndices[idx], -1));
  1001.                                 ++idx;
  1002.  
  1003.                                 if (v2v.find(pIndices[idx]) == v2v.end())
  1004.                                         v2v.insert(Vtx2Vtx::value_type(pIndices[idx], -1));
  1005.                                 ++idx;
  1006.                         }
  1007.                         // generate new indices
  1008.                         int newIdx = 0;
  1009.                         {
  1010.                                 Vtx2Vtx::iterator it = v2v.begin();
  1011.                                 Vtx2Vtx::iterator itEnd = v2v.end();
  1012.                                 for (; it != itEnd; ++it, ++newIdx)
  1013.                                         (*it).second = newIdx;
  1014.                         }
  1015.                         // write used vertices
  1016.                         {
  1017.                                 hull.m_numPts = newIdx;
  1018.                                 SAFE_DELETE_ARRAY(hull.m_pPts);
  1019.                                 hull.m_pPts = new SVF_P3F_C4B_T2F[newIdx];
  1020.  
  1021.                                 Vtx2Vtx::iterator it = v2v.begin();
  1022.                                 Vtx2Vtx::iterator itEnd = v2v.end();
  1023.                                 for (size_t i = 0; it != itEnd; ++it, ++i)
  1024.                                 {
  1025.                                         assert((*it).second == i);
  1026.                                         hull.m_pPts[i].xyz = pPts[(*it).first];
  1027.                                 }
  1028.                         }
  1029.                         // write remapped indices
  1030.                         {
  1031.                                 hull.m_numTris = numTris;
  1032.                                 SAFE_DELETE_ARRAY(hull.m_pIdx);
  1033.                                 hull.m_pIdx = new vtx_idx[numTris * 3];
  1034.  
  1035.                                 for (int i = 0; i < numTris * 3; ++i)
  1036.                                 {
  1037.                                         assert(v2v.find(pIndices[i]) != v2v.end());
  1038.                                         hull.m_pIdx[i] = v2v[pIndices[i]];
  1039.                                 }
  1040.                         }
  1041.                         // free temp hull index array
  1042.                         qhfree(pIndices);
  1043.                 }
  1044.                 else
  1045.                 {
  1046.                         hull.m_numPts = 0;
  1047.                         hull.m_numTris = 0;
  1048.  
  1049.                         SAFE_DELETE_ARRAY(hull.m_pPts);
  1050.                         SAFE_DELETE_ARRAY(hull.m_pIdx);
  1051.                 }
  1052.  
  1053.                 return true;
  1054.         }
  1055.         return false;
  1056. }
  1057. #undef lerp
  1058.  
downloadVolumeObjectDataCreate.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