BVB Source Codes

CRYENGINE Show Voxelizer.cpp Source code

Return Download CRYENGINE: download Voxelizer.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. #include "Voxelizer.h"
  5. #include "HashComputer.h"
  6.  
  7. //#pragma optimize("", off)
  8. //#pragma inline_depth(0)
  9.  
  10. namespace MNM
  11. {
  12. Voxelizer::Voxelizer()
  13.         : m_volumeAABB(AABB::RESET)
  14.         , m_voxelConv(ZERO)
  15.         , m_voxelSize(ZERO)
  16.         , m_voxelSpaceSize(ZERO)
  17. #if DEBUG_MNM_ENABLED
  18.         , m_pDebugRawGeometry(nullptr)
  19. #endif // DEBUG_MNM_ENABLED
  20. {
  21. }
  22.  
  23. void Voxelizer::Reset()
  24. {
  25.         m_spanGrid.Reset(0, 0);
  26. }
  27.  
  28. void Voxelizer::Start(const AABB& volume, const Vec3& voxelSize)
  29. {
  30.         const Vec3 spaceAbs((volume.max - volume.min).abs());
  31.         const Vec3 voxelConv(1.0f / voxelSize.x, 1.0f / voxelSize.y, 1.0f / voxelSize.z);
  32.         m_voxelConv = voxelConv;
  33.  
  34.         m_voxelSpaceSize((int)((spaceAbs.x * voxelConv.x) + 0.5f), (int)((spaceAbs.y * voxelConv.y) + 0.5f), (int)((spaceAbs.z * voxelConv.z) + 0.5f));
  35.         m_spanGrid.Reset((size_t)m_voxelSpaceSize.x, (size_t)(m_voxelSpaceSize.y));
  36.  
  37.         m_volumeAABB = volume;
  38.         m_voxelSize = voxelSize;
  39. }
  40.  
  41. Vec3i GetVec3iFromVec3(const Vec3& vector)
  42. {
  43.         return Vec3i((int)vector.x, (int)vector.y, (int)vector.z);
  44. }
  45.  
  46. void Voxelizer::RasterizeTriangle(const Vec3 v0World, const Vec3 v1World, const Vec3 v2World)
  47. {
  48.         const Vec3 minTriangleBoundingBoxWorld(Minimize(v0World, v1World, v2World));
  49.         const Vec3 maxTriangleBoundingBoxWorld(Maximize(v0World, v1World, v2World));
  50.  
  51.         if (!Overlap::AABB_AABB(AABB(minTriangleBoundingBoxWorld, maxTriangleBoundingBoxWorld), m_volumeAABB))
  52.                 return;
  53.  
  54. #if DEBUG_MNM_ENABLED
  55.         if (m_pDebugRawGeometry)
  56.         {
  57.                 m_pDebugRawGeometry->emplace_back(v0World, v1World, v2World);
  58.         }
  59. #endif // DEBUG_MNM_ENABLED
  60.  
  61. #if 0 // see notes below, why it's disabled
  62.         // NOTE pavloi 2016.03.16: shift volume and triangle into Vec3(ZERO) to avoid
  63.         // issues, that happen, when same geometry results in different voxelization
  64.         // in overlapping parts of neighbor tiles.
  65.  
  66.         // NOTE pavloi 2016.06.09: I hoped, that the math will behave more stable this way.
  67.         // But it didn't really solved the issue - some test cases were fixed, but then some other broke.
  68.  
  69.         const Vec3 spaceMinWorld = m_volumeAABB.min;
  70.         const Vec3 spaceMin(ZERO);
  71. #else
  72.         const Vec3 spaceMinWorld(ZERO);
  73.         const Vec3 spaceMin = m_volumeAABB.min;
  74. #endif
  75.  
  76.         const Vec3 v0 = v0World - spaceMinWorld;
  77.         const Vec3 v1 = v1World - spaceMinWorld;
  78.         const Vec3 v2 = v2World - spaceMinWorld;
  79.  
  80.         const Vec3 minTriangleBoundingBox = minTriangleBoundingBoxWorld - spaceMinWorld;
  81.         const Vec3 maxTriangleBoundingBox = maxTriangleBoundingBoxWorld - spaceMinWorld;
  82.  
  83.         const Vec3 e0(v1 - v0);
  84.         const Vec3 e1(v2 - v1);
  85.         const Vec3 e2(v0 - v2);
  86.  
  87.         const Vec3 n = e2.Cross(e0);
  88.  
  89.         const bool backface = n.z < 0.0f;
  90.  
  91.         const Vec3 voxelSize = m_voxelSize;
  92.         const Vec3 voxelConv = m_voxelConv;
  93.         const Vec3i voxelSpaceSize = m_voxelSpaceSize;
  94.  
  95.         // The absolute value of the voxelMin vector represents the amount of voxels that
  96.         // can fit in the spaceMin to vertexMin vector.
  97.         const Vec3 voxelMin((minTriangleBoundingBox - spaceMin).CompMul(voxelConv));
  98.         // The absolute value of the voxelMin vector represents the amount of voxels that
  99.         // can fit in the spaceMin to vertexMax vector.
  100.         const Vec3 voxelMax((maxTriangleBoundingBox - spaceMin).CompMul(voxelConv));
  101.  
  102.         // Now we try to see how many voxels we actually need to compute. The volumeAABB can fit voxels with index
  103.         // that can vary from 0 to voxelSpaceSize - Vec3(1)
  104.         const Vec3i minVoxelIndex(Maximize<int>(GetVec3iFromVec3(voxelMin), Vec3i(0)));
  105.         const Vec3i maxVoxelIndex(Minimize<int>(GetVec3iFromVec3(voxelMax), voxelSpaceSize - Vec3i(1)));
  106.  
  107.         // This represent the voxel size vector
  108.         const Vec3 dp(voxelSize);
  109.  
  110.         // c is a vector pointing to the furthest edge of the voxel in the direction
  111.         // of the triangle normal.
  112.         const Vec3 c(n.x > 0.0f ? dp.x : 0.0f, n.y > 0.0f ? dp.y : 0.0f, n.z > 0.0f ? dp.z : 0.0f);
  113.         // (dp - c) is the vector pointing to the edge opposed to the one pointed by c
  114.         // Basically firstVericalLimitForTriangleRasterization and secondVerticalLimitForTriangleRasterization
  115.         // represents the length (amplified by the length of the normal) of the projection of the two
  116.         // vectors that starts from v0 and point to two opposite edges on the voxel placed in the origin.
  117.         // This creates a range of 2 values into which the calculation of the voxel vertical position needs
  118.         // to fall to be accepted
  119.         const float firstVericalLimitForTriangleRasterization = n.Dot(c - v0);
  120.         const float secondVerticalLimitForTriangleRasterization = n.Dot(dp - c - v0);
  121.  
  122.         // These bool values identify if the triangle points need to be considered in
  123.         // clockwise or counterclockwise order for the normal/distance calculation
  124.         // for the respective plane
  125.         const bool xycw = n.z < 0.0f;
  126.         const bool xzcw = n.y > 0.0f;
  127.         const bool yzcw = n.x < 0.0f;
  128.  
  129.         const bool zPlanar = minVoxelIndex.z == maxVoxelIndex.z;
  130.  
  131.         // ne0_xy means normal of the edge e0 on the xy plane. The normal points
  132.         // to the internal part of the triangle
  133.         Vec2 ne0_xy, ne0_xz, ne0_yz;
  134.         // de0_xy means distance from the edge0 on the xy plane
  135.         float de0_xy, de0_xz, de0_yz;
  136.         Evaluate2DEdge(ne0_xy, de0_xy, xycw, Vec2(e0.x, e0.y), Vec2(v0.x, v0.y), Vec2(dp.x, dp.y));
  137.  
  138.         if (!zPlanar)
  139.         {
  140.                 Evaluate2DEdge(ne0_xz, de0_xz, xzcw, Vec2(e0.x, e0.z), Vec2(v0.x, v0.z), Vec2(dp.x, dp.z));
  141.                 Evaluate2DEdge(ne0_yz, de0_yz, yzcw, Vec2(e0.y, e0.z), Vec2(v0.y, v0.z), Vec2(dp.y, dp.z));
  142.         }
  143.  
  144.         Vec2 ne1_xy, ne1_xz, ne1_yz;
  145.         float de1_xy, de1_xz, de1_yz;
  146.         Evaluate2DEdge(ne1_xy, de1_xy, xycw, Vec2(e1.x, e1.y), Vec2(v1.x, v1.y), Vec2(dp.x, dp.y));
  147.  
  148.         if (!zPlanar)
  149.         {
  150.                 Evaluate2DEdge(ne1_xz, de1_xz, xzcw, Vec2(e1.x, e1.z), Vec2(v1.x, v1.z), Vec2(dp.x, dp.z));
  151.                 Evaluate2DEdge(ne1_yz, de1_yz, yzcw, Vec2(e1.y, e1.z), Vec2(v1.y, v1.z), Vec2(dp.y, dp.z));
  152.         }
  153.  
  154.         Vec2 ne2_xy, ne2_xz, ne2_yz;
  155.         float de2_xy, de2_xz, de2_yz;
  156.         Evaluate2DEdge(ne2_xy, de2_xy, xycw, Vec2(e2.x, e2.y), Vec2(v2.x, v2.y), Vec2(dp.x, dp.y));
  157.  
  158.         if (!zPlanar)
  159.         {
  160.                 Evaluate2DEdge(ne2_xz, de2_xz, xzcw, Vec2(e2.x, e2.z), Vec2(v2.x, v2.z), Vec2(dp.x, dp.z));
  161.                 Evaluate2DEdge(ne2_yz, de2_yz, yzcw, Vec2(e2.y, e2.z), Vec2(v2.y, v2.z), Vec2(dp.y, dp.z));
  162.         }
  163.  
  164.         {
  165.                 for (int y = minVoxelIndex.y; y <= maxVoxelIndex.y; ++y)
  166.                 {
  167.                         const float minY = spaceMin.y + y * voxelSize.y;
  168.  
  169.                         if ((minY + dp.y < minTriangleBoundingBox.y) || (minY > maxTriangleBoundingBox.y))
  170.                                 continue;
  171.  
  172.                         for (int x = minVoxelIndex.x; x <= maxVoxelIndex.x; ++x)
  173.                         {
  174.                                 const float minX = spaceMin.x + x * voxelSize.x;
  175.  
  176.                                 if ((minX + dp.x < minTriangleBoundingBox.x) || (minX > maxTriangleBoundingBox.x))
  177.                                         continue;
  178.  
  179.                                 if (ne0_xy.Dot(Vec2(minX, minY)) + de0_xy < 0.0f)
  180.                                         continue;
  181.                                 if (ne1_xy.Dot(Vec2(minX, minY)) + de1_xy < 0.0f)
  182.                                         continue;
  183.                                 if (ne2_xy.Dot(Vec2(minX, minY)) + de2_xy < 0.0f)
  184.                                         continue;
  185.  
  186.                                 if (zPlanar)
  187.                                 {
  188.                                         m_spanGrid.AddVoxel(x, y, minVoxelIndex.z, backface);
  189.  
  190.                                         continue;
  191.                                 }
  192.  
  193.                                 bool wasPreviousVoxelBelowTheTriangle = true;
  194.  
  195.                                 for (int z = minVoxelIndex.z; z <= maxVoxelIndex.z; ++z)
  196.                                 {
  197.                                         const float minZ = spaceMin.z + z * voxelSize.z;
  198.  
  199.                                         if ((minZ + dp.z < minTriangleBoundingBox.z) || (minZ > maxTriangleBoundingBox.z))
  200.                                                 continue;
  201.  
  202.                                         // This projection value is amplified by the n length (it is not normalized)
  203.                                         float currentVoxelProjectedOnTriangleNormal = n.Dot(Vec3(minX, minY, minZ));
  204.  
  205.                                         // Here we check if the current voxel is containing the triangle
  206.                                         // in-between his height limits.
  207.                                         const float firstDistance = (currentVoxelProjectedOnTriangleNormal + firstVericalLimitForTriangleRasterization);
  208.                                         const float secondDistance = (currentVoxelProjectedOnTriangleNormal + secondVerticalLimitForTriangleRasterization);
  209.                                         const bool isVoxelAboveOrBelowTheTriangle = firstDistance * secondDistance > 0.0f;
  210.                                         if (isVoxelAboveOrBelowTheTriangle)
  211.                                         {
  212.                                                 // We start the voxelization process from the bottom of a tile to the top.
  213.                                                 // This allows us to consider the first voxel always below the triangle we are considering.
  214.                                                 // For small voxels and triangles with tiny slopes, due to numerical errors,
  215.                                                 // we could end up skipping the voxel that correctly rasterizes a particular point.
  216.                                                 // So if we pass directly from a situation in which we were below the triangle
  217.                                                 // and we are now above it, then we don't skip the voxel and we continue to check
  218.                                                 // if the other requirements are fulfilled.
  219.                                                 if (wasPreviousVoxelBelowTheTriangle)
  220.                                                 {
  221.                                                         const bool isTheCurrentVoxelAboveTheTriangle = firstDistance > 0.0f && secondDistance > 0.0f;
  222.                                                         if (isTheCurrentVoxelAboveTheTriangle)
  223.                                                         {
  224.                                                                 wasPreviousVoxelBelowTheTriangle = false;
  225.                                                         }
  226.                                                 }
  227.                                                 else
  228.                                                 {
  229.                                                         continue;
  230.                                                 }
  231.                                         }
  232.  
  233.                                         wasPreviousVoxelBelowTheTriangle = false;
  234.  
  235.                                         if (ne0_xz.Dot(Vec2(minX, minZ)) + de0_xz < 0.0f)
  236.                                                 continue;
  237.                                         if (ne1_xz.Dot(Vec2(minX, minZ)) + de1_xz < 0.0f)
  238.                                                 continue;
  239.                                         // cppcheck-suppress uninitvar
  240.                                         if (ne2_xz.Dot(Vec2(minX, minZ)) + de2_xz < 0.0f)
  241.                                                 continue;
  242.  
  243.                                         if (ne0_yz.Dot(Vec2(minY, minZ)) + de0_yz < 0.0f)
  244.                                                 continue;
  245.                                         if (ne1_yz.Dot(Vec2(minY, minZ)) + de1_yz < 0.0f)
  246.                                                 continue;
  247.                                         // cppcheck-suppress uninitvar
  248.                                         if (ne2_yz.Dot(Vec2(minY, minZ)) + de2_yz < 0.0f)
  249.                                                 continue;
  250.  
  251.                                         m_spanGrid.AddVoxel(x, y, z, backface);
  252.                                 }
  253.                         }
  254.                 }
  255.         }
  256. }
  257.  
  258. static const uint32 BoxTriIndices[] =
  259. {
  260.         2, 1, 0,
  261.         0, 3, 2,
  262.         3, 0, 7,
  263.         0, 4, 7,
  264.         0, 1, 5,
  265.         0, 5, 4,
  266.         1, 2, 5,
  267.         6, 5, 2,
  268.         7, 2, 3,
  269.         7, 6, 2,
  270.         7, 4, 5,
  271.         7, 5, 6
  272. };
  273.  
  274. static inline bool HasNoRotOrScale(const Matrix33& m)
  275. {
  276.         return ((m.m00 == 1.0f) && (m.m11 == 1.0f) && (m.m22 == 1.0f) &&
  277.                 (m.m01 == 0.0f) && (m.m02 == 0.0f) &&
  278.                 (m.m10 == 0.0f) && (m.m12 == 0.0f) &&
  279.                 (m.m20 == 0.0f) && (m.m21 == 0.0f));
  280. }
  281.  
  282. bool VoxelizeEntity(IPhysicalEntity& physicalEntity, pe_status_dynamics& statusDynamics, pe_status_pos& statusPosition)
  283. {
  284.         if (physicalEntity.GetType() == PE_WHEELEDVEHICLE)
  285.         {
  286.                 return false;
  287.         }
  288.  
  289.         bool considerMass = (physicalEntity.GetType() == PE_RIGID);
  290.         if (!considerMass)
  291.         {
  292.                 if (physicalEntity.GetStatus(&statusPosition))
  293.                 {
  294.                         considerMass = (statusPosition.iSimClass == SC_ACTIVE_RIGID) || (statusPosition.iSimClass == SC_SLEEPING_RIGID);
  295.                 }
  296.         }
  297.  
  298.         if (considerMass)
  299.         {
  300.                 if (!physicalEntity.GetStatus(&statusDynamics))
  301.                         return false;
  302.  
  303.                 if (statusDynamics.mass > 1e-6f)
  304.                         return false;
  305.         }
  306.  
  307.         return true;
  308. }
  309.  
  310. PREFAST_SUPPRESS_WARNING(6262)
  311. size_t WorldVoxelizer::ProcessGeometry(uint32 hashValueSeed /* = 0 */, uint32 hashTest /* = 0 */, uint32* hashValue /* = 0 */, NavigationMeshEntityCallback pEntityCallback /* = NULL */)
  312. {
  313.         size_t triCount = 0;
  314.  
  315.         const size_t MaxConsideredEntityCount = 2048;
  316.         IPhysicalEntity* entities[MaxConsideredEntityCount] = { 0 };
  317.         IPhysicalEntity** entityList = &entities[0];
  318.         int entityCount = gEnv->pPhysicalWorld->GetEntitiesInBox(m_volumeAABB.min, m_volumeAABB.max, entityList,
  319.                                                                  ent_static | ent_terrain | ent_sleeping_rigid | ent_rigid | ent_allocate_list | ent_addref_results, MaxConsideredEntityCount);
  320.  
  321.         pe_status_pos sp;
  322.         pe_status_dynamics dyn;
  323.  
  324.         Matrix34 worldTM;
  325.         sp.pMtx3x4 = &worldTM;
  326.  
  327.         HashComputer hash(hashValueSeed);
  328.         hash.Add((uint32)entityCount);
  329.  
  330.         const size_t MaxTerrainAABBCount = 16;
  331.         AABB terrainAABB[MaxTerrainAABBCount];
  332.         size_t terrainAABBCount = 0;
  333.  
  334.         uint32 flags = 0;   // not used yet
  335.         for (int i = 0; i < entityCount; ++i)
  336.         {
  337.                 IPhysicalEntity* entity = entityList[i];
  338.  
  339.                 if (pEntityCallback && pEntityCallback(*entity, flags) == false)
  340.                 {
  341.                         entity->Release();
  342.                         entityList[i] = NULL;
  343.                         continue;
  344.                 }
  345.  
  346.                 sp.ipart = 0;
  347.                 MARK_UNUSED sp.partid;
  348.  
  349.                 while (entity->GetStatus(&sp))
  350.                 {
  351.                         if (sp.pGeomProxy && (sp.flagsOR & geom_colltype_player))
  352.                         {
  353.                                 if (sp.pGeomProxy->GetType() == GEOM_HEIGHTFIELD)
  354.                                 {
  355.                                         const AABB aabb = ComputeTerrainAABB(sp.pGeomProxy);
  356.                                         if (terrainAABBCount < MaxTerrainAABBCount)
  357.                                                 terrainAABB[terrainAABBCount++] = aabb;
  358.  
  359.                                         if (aabb.GetSize().len2() > 0.0f)
  360.                                         {
  361.                                                 hash.Add(aabb.min);
  362.                                                 hash.Add(aabb.max);
  363.                                         }
  364.                                 }
  365.                                 else
  366.                                 {
  367.                                         hash.Add(sp.BBox[0]);
  368.                                         hash.Add(sp.BBox[1]);
  369.                                         hash.Add((uint32)sp.iSimClass);
  370.                                         hash.Add(worldTM);
  371.                                 }
  372.                         }
  373.  
  374.                         ++sp.ipart;
  375.                         MARK_UNUSED sp.partid;
  376.                 }
  377.                 MARK_UNUSED sp.ipart;
  378.         }
  379.  
  380.         hash.Complete();
  381.  
  382.         if (hashValue)
  383.                 *hashValue = hash.GetValue();
  384.  
  385.         // NOTE pavloi 2016.07.13: if external meshes present, this branch will almost always be executes
  386.         if (hashTest != hash.GetValue())
  387.         {
  388.                 terrainAABBCount = 0;
  389.  
  390.                 for (int i = 0; i < entityCount; ++i)
  391.                 {
  392.                         IPhysicalEntity* entity = entityList[i];
  393.                         if (!entity)
  394.                                 continue;
  395.  
  396.                         sp.ipart = 0;
  397.                         MARK_UNUSED sp.partid;
  398.  
  399.                         while (entity->GetStatus(&sp))
  400.                         {
  401.                                 if (sp.pGeomProxy && (sp.flagsOR & geom_colltype_player))
  402.                                 {
  403.                                         if (sp.pGeomProxy->GetType() == GEOM_HEIGHTFIELD)
  404.                                         {
  405.                                                 if (terrainAABBCount < MaxTerrainAABBCount)
  406.                                                 {
  407.                                                         const AABB& aabb = terrainAABB[terrainAABBCount++];
  408.  
  409.                                                         if (aabb.GetSize().len2() <= 0.0f)
  410.                                                         {
  411.                                                                 ++sp.ipart;
  412.                                                                 MARK_UNUSED sp.partid;
  413.  
  414.                                                                 continue;
  415.                                                         }
  416.                                                 }
  417.                                         }
  418.  
  419.                                         triCount += VoxelizeGeometry(sp.pGeomProxy, worldTM);
  420.                                 }
  421.  
  422.                                 ++sp.ipart;
  423.                                 MARK_UNUSED sp.partid;
  424.                         }
  425.                         MARK_UNUSED sp.ipart;
  426.                 }
  427.         }
  428.  
  429.         for (int i = 0; i < entityCount; ++i)
  430.         {
  431.                 if (entityList[i])
  432.                         entityList[i]->Release();
  433.         }
  434.  
  435.         if (entities != entityList)
  436.                 gEnv->pPhysicalWorld->GetPhysUtils()->DeletePointer(entityList);
  437.  
  438.         return triCount;
  439. }
  440.  
  441. struct PhysicsVolume
  442. {
  443.         PhysicsVolume()
  444.                 : area(NULL)
  445.                 , volume(0)
  446.         {
  447.         }
  448.  
  449.         PhysicsVolume(const IPhysicalEntity* _area, float _volume, const primitives::plane& _plane)
  450.                 : area(_area)
  451.                 , volume(_volume)
  452.                 , plane(_plane)
  453.         {
  454.         }
  455.  
  456.         bool operator<(const PhysicsVolume& other) const
  457.         {
  458.                 return volume < other.volume;
  459.         }
  460.  
  461.         const IPhysicalEntity* area;
  462.         float                  volume;
  463.         primitives::plane      plane;
  464. };
  465.  
  466. void WorldVoxelizer::CalculateWaterDepth()
  467. {
  468.         const size_t width = m_spanGrid.GetWidth();
  469.         const size_t height = m_spanGrid.GetHeight();
  470.         const float oceanLevel = gEnv->p3DEngine->GetWaterLevel();
  471.  
  472.         const size_t MaxAreaCount = 64;
  473.         IPhysicalEntity* areas[MaxAreaCount];
  474.  
  475.         IPhysicalEntity** areaList = &areas[0];
  476.         size_t areaCount = (size_t)gEnv->pPhysicalWorld->GetEntitiesInBox(m_volumeAABB.min, m_volumeAABB.max, areaList,
  477.                                                                           ent_areas | ent_allocate_list | ent_addref_results, MaxAreaCount);
  478.  
  479.         if (areaCount > MaxAreaCount)
  480.         {
  481.  
  482.                 assert(areas != &areaList[0]);
  483.                 memcpy(areas, areaList, sizeof(IPhysicalEntity*) * MaxAreaCount);
  484.                 for (size_t i = MaxAreaCount; i < areaCount; ++i)
  485.                 {
  486.                         if (areaList[i])
  487.                                 areaList[i]->Release();
  488.                 }
  489.  
  490.                 gEnv->pPhysicalWorld->GetPhysUtils()->DeletePointer(areaList);
  491.  
  492.                 areaList = areas;
  493.                 areaCount = MaxAreaCount;
  494.         }
  495.  
  496.         const size_t MaxConsiderVolumes = 16;
  497.  
  498.         size_t volumeCount = 0;
  499.         PhysicsVolume volumes[MaxConsiderVolumes];
  500.  
  501.         pe_params_buoyancy pb;
  502.         pe_params_area pa;
  503.  
  504.         for (size_t i = 0; i < areaCount; ++i)
  505.         {
  506.                 const IPhysicalEntity* area = areaList[i];
  507.  
  508.                 if (area->GetParams(&pb))
  509.                 {
  510.                         if ((pb.iMedium == 0) && !is_unused(pb.waterPlane.origin))
  511.                         {
  512.                                 if (volumeCount < MaxConsiderVolumes)
  513.                                 {
  514.                                         float volume = 0.0f;
  515.  
  516.                                         if (area->GetParams(&pa))
  517.                                         {
  518.                                                 if (pa.pGeom)
  519.                                                         volume = pa.pGeom->GetVolume();
  520.                                         }
  521.  
  522.                                         volumes[volumeCount++] = PhysicsVolume(area, volume, pb.waterPlane);
  523.                                 }
  524.                         }
  525.                 }
  526.         }
  527.  
  528.         const Vec3 spaceMin = m_volumeAABB.min;
  529.         if (volumeCount || spaceMin.z < oceanLevel)
  530.         {
  531.                 std::sort(&volumes[0], &volumes[0] + volumeCount);
  532.  
  533.                 const Vec3 voxelSize = m_voxelSize;
  534.                 const Vec3 voxelConv = m_voxelConv;
  535.  
  536.                 pe_status_contains_point scp;
  537.  
  538.                 for (size_t y = 0; y < height; ++y)
  539.                 {
  540.                         for (size_t x = 0; x < width; ++x)
  541.                         {
  542.                                 for (DynamicSpanGrid::Element* span = m_spanGrid[x + y * width]; span; span = span->next)
  543.                                 {
  544.                                         const Vec3 top = spaceMin + Vec3(x * voxelSize.x, y * voxelSize.y, span->top * voxelSize.z);
  545.                                         size_t depth = (top.z >= oceanLevel) ? 0 : (size_t)((oceanLevel - top.z) * voxelConv.z);
  546.  
  547.                                         scp.pt = top;
  548.                                         for (size_t i = 0; i < volumeCount; ++i)
  549.                                         {
  550.                                                 float vdepth = volumes[i].plane.n.z * (volumes[i].plane.n * (volumes[i].plane.origin - top));
  551.  
  552.                                                 if (volumes[i].area->GetStatus(&scp))
  553.                                                 {
  554.                                                         depth = (vdepth <= 0.0f) ? 0 : (size_t)(vdepth * voxelConv.z);
  555.                                                         break;
  556.                                                 }
  557.                                         }
  558.  
  559.                                         if (depth > DynamicSpanGrid::Element::MaxWaterDepth)
  560.                                                 depth = DynamicSpanGrid::Element::MaxWaterDepth;
  561.  
  562.                                         span->depth = depth;
  563.                                 }
  564.                         }
  565.                 }
  566.         }
  567.  
  568.         for (size_t i = 0; i < areaCount; ++i)
  569.         {
  570.                 if (areaList[i])
  571.                         areaList[i]->Release();
  572.         }
  573.  
  574.         if (areas != areaList)
  575.                 gEnv->pPhysicalWorld->GetPhysUtils()->DeletePointer(areaList);
  576. }
  577.  
  578. void WorldVoxelizer::VoxelizeGeometry(const Vec3* vertices, size_t triCount, const Matrix34& worldTM)
  579. {
  580.         if (HasNoRotOrScale(Matrix33(worldTM)))
  581.         {
  582.                 Vec3 offset = worldTM.GetTranslation();
  583.  
  584.                 if (offset.IsZero())
  585.                 {
  586.                         for (size_t i = 0; i < triCount; ++i)
  587.                                 RasterizeTriangle(vertices[i * 3 + 0],
  588.                                                   vertices[i * 3 + 1],
  589.                                                   vertices[i * 3 + 2]);
  590.                 }
  591.                 else
  592.                 {
  593.                         for (size_t i = 0; i < triCount; ++i)
  594.                                 RasterizeTriangle(vertices[i * 3 + 0] + offset,
  595.                                                   vertices[i * 3 + 1] + offset,
  596.                                                   vertices[i * 3 + 2] + offset);
  597.                 }
  598.         }
  599.         else
  600.         {
  601.                 for (size_t i = 0; i < triCount; ++i)
  602.                 {
  603.                         RasterizeTriangle(worldTM.TransformPoint(vertices[i * 3 + 0]),
  604.                                           worldTM.TransformPoint(vertices[i * 3 + 1]),
  605.                                           worldTM.TransformPoint(vertices[i * 3 + 2]));
  606.                 }
  607.         }
  608. }
  609.  
  610. void WorldVoxelizer::VoxelizeGeometry(const strided_pointer<Vec3>& vertices, const index_t* indices, size_t triCount, const Matrix34& worldTM)
  611. {
  612.         if (HasNoRotOrScale(Matrix33(worldTM)))
  613.         {
  614.                 Vec3 offset = worldTM.GetTranslation();
  615.  
  616.                 if (offset.IsZero())
  617.                 {
  618.                         for (size_t i = 0; i < triCount; ++i)
  619.                                 RasterizeTriangle(vertices[indices[i * 3 + 0]], vertices[indices[i * 3 + 1]], vertices[indices[i * 3 + 2]]);
  620.                 }
  621.                 else
  622.                 {
  623.                         for (size_t i = 0; i < triCount; ++i)
  624.                         {
  625.                                 RasterizeTriangle(vertices[indices[i * 3 + 0]] + offset,
  626.                                                   vertices[indices[i * 3 + 1]] + offset,
  627.                                                   vertices[indices[i * 3 + 2]] + offset);
  628.                         }
  629.                 }
  630.         }
  631.         else
  632.         {
  633.                 for (size_t i = 0; i < triCount; ++i)
  634.                 {
  635.                         RasterizeTriangle(worldTM.TransformPoint(vertices[indices[i * 3 + 0]]),
  636.                                           worldTM.TransformPoint(vertices[indices[i * 3 + 1]]),
  637.                                           worldTM.TransformPoint(vertices[indices[i * 3 + 2]]));
  638.                 }
  639.         }
  640. }
  641.  
  642. void WorldVoxelizer::VoxelizeGeometry(const Vec3* vertices, const uint32* indices, size_t triCount, const Matrix34& worldTM)
  643. {
  644.         if (HasNoRotOrScale(Matrix33(worldTM)))
  645.         {
  646.                 Vec3 offset = worldTM.GetTranslation();
  647.  
  648.                 if (offset.IsZero())
  649.                 {
  650.                         for (size_t i = 0; i < triCount; ++i)
  651.                                 RasterizeTriangle(vertices[indices[i * 3 + 0]], vertices[indices[i * 3 + 1]], vertices[indices[i * 3 + 2]]);
  652.                 }
  653.                 else
  654.                 {
  655.                         for (size_t i = 0; i < triCount; ++i)
  656.                         {
  657.                                 RasterizeTriangle(vertices[indices[i * 3 + 0]] + offset,
  658.                                                   vertices[indices[i * 3 + 1]] + offset,
  659.                                                   vertices[indices[i * 3 + 2]] + offset);
  660.                         }
  661.                 }
  662.         }
  663.         else
  664.         {
  665.                 for (size_t i = 0; i < triCount; ++i)
  666.                 {
  667.                         RasterizeTriangle(worldTM.TransformPoint(vertices[indices[i * 3 + 0]]),
  668.                                           worldTM.TransformPoint(vertices[indices[i * 3 + 1]]),
  669.                                           worldTM.TransformPoint(vertices[indices[i * 3 + 2]]));
  670.                 }
  671.         }
  672. }
  673.  
  674. AABB WorldVoxelizer::ComputeTerrainAABB(IGeometry* geometry)
  675. {
  676.         primitives::heightfield* phf = (primitives::heightfield*)geometry->GetData();
  677.         if (!phf) return AABB::RESET;
  678.  
  679.         const int minX = max(0, (int)((m_volumeAABB.min.x - phf->origin.x) * phf->stepr.x));
  680.         const int minY = max(0, (int)((m_volumeAABB.min.y - phf->origin.y) * phf->stepr.y));
  681.         const int maxX = min((int)((m_volumeAABB.max.x - phf->origin.x) * phf->stepr.x), (phf->size.x - 1));
  682.         const int maxY = min((int)((m_volumeAABB.max.y - phf->origin.y) * phf->stepr.y), (phf->size.y - 1));
  683.  
  684.         const Vec3 origin = phf->origin;
  685.  
  686.         const float xStep = (float)phf->step.x;
  687.         const float yStep = (float)phf->step.y;
  688.  
  689.         AABB terrainAABB(AABB::RESET);
  690.  
  691.         if (phf->fpGetSurfTypeCallback && phf->fpGetHeightCallback)
  692.         {
  693.                 for (int y = minY; y <= maxY; ++y)
  694.                 {
  695.                         for (int x = minX; x <= maxX; ++x)
  696.                         {
  697.                                 if (phf->fpGetSurfTypeCallback(x, y) != phf->typehole)
  698.                                 {
  699.                                         const Vec3 v0 = origin + Vec3(x * xStep, y * yStep, phf->getheight(x, y) * phf->heightscale);
  700.                                         const Vec3 v1 = origin + Vec3(x * xStep, (y + 1) * yStep, phf->getheight(x, y + 1) * phf->heightscale);
  701.                                         const Vec3 v2 = origin + Vec3((x + 1) * xStep, y * yStep, phf->getheight(x + 1, y) * phf->heightscale);
  702.                                         const Vec3 v3 = origin + Vec3((x + 1) * xStep, (y + 1) * yStep, phf->getheight(x + 1, y + 1) * phf->heightscale);
  703.  
  704.                                         terrainAABB.Add(v0);
  705.                                         terrainAABB.Add(v1);
  706.                                         terrainAABB.Add(v2);
  707.                                         terrainAABB.Add(v3);
  708.                                 }
  709.                         }
  710.                 }
  711.         }
  712.         else if (phf->fpGetSurfTypeCallback)
  713.         {
  714.                 float* height = (float*)phf->fpGetHeightCallback;
  715.  
  716.                 assert(height);
  717.                 PREFAST_ASSUME(height);
  718.  
  719.                 for (int y = minY; y <= maxY; ++y)
  720.                 {
  721.                         for (int x = minX; x <= maxX; ++x)
  722.                         {
  723.                                 const Vec3 v0 = origin + Vec3(x * xStep, y * yStep, height[Vec2i(x, y) * phf->stride] * phf->heightscale);
  724.                                 const Vec3 v1 = origin + Vec3(x * xStep, (y + 1) * yStep, height[Vec2i(x, y + 1) * phf->stride] * phf->heightscale);
  725.                                 const Vec3 v2 = origin + Vec3((x + 1) * xStep, y * yStep, height[Vec2i(x + 1, y) * phf->stride] * phf->heightscale);
  726.                                 const Vec3 v3 = origin + Vec3((x + 1) * xStep, (y + 1) * yStep, height[Vec2i(x + 1, y + 1) * phf->stride] * phf->heightscale);
  727.  
  728.                                 terrainAABB.Add(v0);
  729.                                 terrainAABB.Add(v1);
  730.                                 terrainAABB.Add(v2);
  731.                                 terrainAABB.Add(v3);
  732.                         }
  733.                 }
  734.         }
  735.         else
  736.         {
  737.                 for (int y = minY; y <= maxY; ++y)
  738.                 {
  739.                         for (int x = minX; x <= maxX; ++x)
  740.                         {
  741.                                 const Vec3 v0 = origin + Vec3(x * xStep, y * yStep, phf->getheight(x, y) * phf->heightscale);
  742.                                 const Vec3 v1 = origin + Vec3(x * xStep, (y + 1) * yStep, phf->getheight(x, y + 1) * phf->heightscale);
  743.                                 const Vec3 v2 = origin + Vec3((x + 1) * xStep, y * yStep, phf->getheight(x + 1, y) * phf->heightscale);
  744.                                 const Vec3 v3 = origin + Vec3((x + 1) * xStep, (y + 1) * yStep, phf->getheight(x + 1, y + 1) * phf->heightscale);
  745.  
  746.                                 terrainAABB.Add(v0);
  747.                                 terrainAABB.Add(v1);
  748.                                 terrainAABB.Add(v2);
  749.                                 terrainAABB.Add(v3);
  750.                         }
  751.                 }
  752.         }
  753.  
  754.         if (Overlap::AABB_AABB(m_volumeAABB, terrainAABB))
  755.                 return terrainAABB;
  756.  
  757.         return AABB::RESET;
  758. }
  759.  
  760. #pragma warning (push)
  761. #pragma warning (disable: 6262)
  762. size_t WorldVoxelizer::VoxelizeTerrain(IGeometry* geometry, const Matrix34& worldTM)
  763. {
  764.         primitives::heightfield* phf = (primitives::heightfield*)geometry->GetData();
  765.  
  766.         const int minX = max(0, (int)((m_volumeAABB.min.x - phf->origin.x) * phf->stepr.x));
  767.         const int minY = max(0, (int)((m_volumeAABB.min.y - phf->origin.y) * phf->stepr.y));
  768.         const int maxX = min((int)((m_volumeAABB.max.x - phf->origin.x) * phf->stepr.x), (phf->size.x - 1));
  769.         const int maxY = min((int)((m_volumeAABB.max.y - phf->origin.y) * phf->stepr.y), (phf->size.y - 1));
  770.  
  771.         const Vec3 origin = phf->origin;
  772.  
  773.         const float xStep = (float)phf->step.x;
  774.         const float yStep = (float)phf->step.y;
  775.  
  776.         size_t faceCount = 0;
  777.  
  778.         const size_t MaxVertexCount = 1024 * 4;
  779.         Vec3 vertices[MaxVertexCount];
  780.  
  781.         if (phf->fpGetSurfTypeCallback && phf->fpGetHeightCallback)
  782.         {
  783.                 for (int y = minY; y <= maxY; ++y)
  784.                 {
  785.                         for (int x = minX; x <= maxX; ++x)
  786.                         {
  787.                                 if (phf->fpGetSurfTypeCallback(x, y) != phf->typehole)
  788.                                 {
  789.                                         const Vec3 v0 = origin + Vec3(x * xStep, y * yStep, phf->getheight(x, y) * phf->heightscale);
  790.                                         const Vec3 v1 = origin + Vec3(x * xStep, (y + 1) * yStep, phf->getheight(x, y + 1) * phf->heightscale);
  791.                                         const Vec3 v2 = origin + Vec3((x + 1) * xStep, y * yStep, phf->getheight(x + 1, y) * phf->heightscale);
  792.                                         const Vec3 v3 = origin + Vec3((x + 1) * xStep, (y + 1) * yStep, phf->getheight(x + 1, y + 1) * phf->heightscale);
  793.  
  794.                                         assert(faceCount < MaxVertexCount);
  795.  
  796.                                         vertices[(faceCount << 2) + 0] = v0;
  797.                                         vertices[(faceCount << 2) + 1] = v1;
  798.                                         vertices[(faceCount << 2) + 2] = v2;
  799.                                         vertices[(faceCount++ << 2) + 3] = v3;
  800.                                 }
  801.                         }
  802.                 }
  803.         }
  804.         else if (phf->fpGetSurfTypeCallback)
  805.         {
  806.                 float* height = (float*)phf->fpGetHeightCallback;
  807.  
  808.                 assert(height);
  809.                 PREFAST_ASSUME(height);
  810.  
  811.                 for (int y = minY; y <= maxY; ++y)
  812.                 {
  813.                         for (int x = minX; x <= maxX; ++x)
  814.                         {
  815.                                 const Vec3 v0 = origin + Vec3(x * xStep, y * yStep, height[Vec2i(x, y) * phf->stride] * phf->heightscale);
  816.                                 const Vec3 v1 = origin + Vec3(x * xStep, (y + 1) * yStep, height[Vec2i(x, y + 1) * phf->stride] * phf->heightscale);
  817.                                 const Vec3 v2 = origin + Vec3((x + 1) * xStep, y * yStep, height[Vec2i(x + 1, y) * phf->stride] * phf->heightscale);
  818.                                 const Vec3 v3 = origin + Vec3((x + 1) * xStep, (y + 1) * yStep, height[Vec2i(x + 1, y + 1) * phf->stride] * phf->heightscale);
  819.  
  820.                                 assert(faceCount < MaxVertexCount);
  821.  
  822.                                 vertices[(faceCount << 2) + 0] = v0;
  823.                                 vertices[(faceCount << 2) + 1] = v1;
  824.                                 vertices[(faceCount << 2) + 2] = v2;
  825.                                 vertices[(faceCount++ << 2) + 3] = v3;
  826.                         }
  827.                 }
  828.         }
  829.         else
  830.         {
  831.                 for (int y = minY; y <= maxY; ++y)
  832.                 {
  833.                         for (int x = minX; x <= maxX; ++x)
  834.                         {
  835.                                 const Vec3 v0 = origin + Vec3(x * xStep, y * yStep, phf->getheight(x, y) * phf->heightscale);
  836.                                 const Vec3 v1 = origin + Vec3(x * xStep, (y + 1) * yStep, phf->getheight(x, y + 1) * phf->heightscale);
  837.                                 const Vec3 v2 = origin + Vec3((x + 1) * xStep, y * yStep, phf->getheight(x + 1, y) * phf->heightscale);
  838.                                 const Vec3 v3 = origin + Vec3((x + 1) * xStep, (y + 1) * yStep, phf->getheight(x + 1, y + 1) * phf->heightscale);
  839.  
  840.                                 assert(faceCount < MaxVertexCount);
  841.  
  842.                                 vertices[(faceCount << 2) + 0] = v0;
  843.                                 vertices[(faceCount << 2) + 1] = v1;
  844.                                 vertices[(faceCount << 2) + 2] = v2;
  845.                                 vertices[(faceCount++ << 2) + 3] = v3;
  846.                         }
  847.                 }
  848.         }
  849.  
  850.         for (size_t i = 0; i < faceCount; ++i)
  851.         {
  852.                 RasterizeTriangle(vertices[(i << 2) + 0], vertices[(i << 2) + 2], vertices[(i << 2) + 1]);
  853.                 RasterizeTriangle(vertices[(i << 2) + 1], vertices[(i << 2) + 2], vertices[(i << 2) + 3]);
  854.         }
  855.  
  856.         return faceCount << 1;
  857. }
  858. #pragma warning (pop)
  859.  
  860. #pragma warning (push)
  861. #pragma warning (disable: 6262)
  862. size_t WorldVoxelizer::VoxelizeGeometry(IGeometry* geometry, const Matrix34& worldTM)
  863. {
  864.         size_t triangleCount = 0;
  865.         switch (geometry->GetType())
  866.         {
  867.         case GEOM_TRIMESH:
  868.         case GEOM_VOXELGRID:
  869.                 {
  870.                         const mesh_data* mesh = static_cast<const mesh_data*>(geometry->GetData());
  871.  
  872.                         VoxelizeGeometry(mesh->pVertices, mesh->pIndices, mesh->nTris, worldTM);
  873.  
  874.                         return mesh->nTris;
  875.                 }
  876.                 break;
  877.         case GEOM_BOX:
  878.                 {
  879.                         const primitives::box& box = *static_cast<const primitives::box*>(geometry->GetData());
  880.  
  881.                         Vec3 vertices[] =
  882.                         {
  883.                                 Vec3(-box.size.x, -box.size.y, -box.size.z),
  884.                                 Vec3(box.size.x,  -box.size.y, -box.size.z),
  885.                                 Vec3(box.size.x,  box.size.y,  -box.size.z),
  886.                                 Vec3(-box.size.x, box.size.y,  -box.size.z),
  887.  
  888.                                 Vec3(-box.size.x, -box.size.y, box.size.z),
  889.                                 Vec3(box.size.x,  -box.size.y, box.size.z),
  890.                                 Vec3(box.size.x,  box.size.y,  box.size.z),
  891.                                 Vec3(-box.size.x, box.size.y,  box.size.z),
  892.                         };
  893.  
  894.                         Matrix34 boxTM(worldTM);
  895.  
  896.                         if (box.bOriented)
  897.                         {
  898.                                 boxTM = Matrix34(box.Basis.GetTransposed());
  899.                                 boxTM.SetTranslation(box.center);
  900.                                 boxTM = worldTM * boxTM;
  901.                         }
  902.                         else
  903.                                 boxTM.AddTranslation(boxTM.TransformVector(box.center));
  904.  
  905.                         VoxelizeGeometry(vertices, &BoxTriIndices[0], 12, boxTM);
  906.  
  907.                         return 12;
  908.                 }
  909.                 break;
  910.         case GEOM_SPHERE:
  911.                 {
  912.                         const primitives::sphere& sphere = *static_cast<const primitives::sphere*>(geometry->GetData());
  913.  
  914.                         const Vec3 center = sphere.center;
  915.                         const float r = sphere.r;
  916.  
  917.                         const size_t stacks = 48;
  918.                         const size_t slices = 48;
  919.  
  920.                         const size_t vertexCount = slices * (stacks - 2) + 2;
  921.                         Vec3 vertices[vertexCount];
  922.  
  923.                         const size_t indexCount = (slices - 1) * (stacks - 2) * 6;
  924.                         uint32 indices[indexCount];
  925.  
  926.                         vertices[0] = center;
  927.                         vertices[0].y += r;
  928.                         vertices[1] = center;
  929.                         vertices[1].y -= r;
  930.  
  931.                         size_t v = 2;
  932.                         for (size_t j = 1; j < stacks - 1; ++j)
  933.                         {
  934.                                 for (size_t i = 0; i < slices; ++i)
  935.                                 {
  936.                                         float theta = (j / (float)(stacks - 1)) * 3.14159265f;
  937.                                         float phi = (i / (float)(slices - 1)) * 2.0f * 3.14159265f;
  938.  
  939.                                         float stheta, ctheta;
  940.                                         sincos_tpl(theta, &stheta, &ctheta);
  941.  
  942.                                         float sphi, cphi;
  943.                                         sincos_tpl(phi, &sphi, &cphi);
  944.  
  945.                                         Vec3 point = center + Vec3(stheta * cphi * r, ctheta * r, -stheta * sphi * r);
  946.                                         vertices[v++] = point;
  947.                                 }
  948.                         }
  949.  
  950.                         size_t n = 0;
  951.  
  952.                         for (size_t i = 0; i < slices - 1; ++i)
  953.                         {
  954.                                 indices[n++] = 0;
  955.                                 indices[n++] = i + 2;
  956.                                 indices[n++] = i + 3;
  957.  
  958.                                 indices[n++] = (stacks - 3) * slices + i + 3;
  959.                                 indices[n++] = (stacks - 3) * slices + i + 2;
  960.                                 indices[n++] = 1;
  961.                         }
  962.  
  963.                         for (size_t j = 0; j < stacks - 3; ++j)
  964.                         {
  965.                                 for (size_t i = 0; i < slices - 1; ++i)
  966.                                 {
  967.                                         indices[n++] = (j + 1) * slices + i + 3;
  968.                                         indices[n++] = j * slices + i + 3;
  969.                                         indices[n++] = (j + 1) * slices + i + 2;
  970.                                         indices[n++] = j * slices + i + 3;
  971.                                         indices[n++] = j * slices + i + 2;
  972.                                         indices[n++] = (j + 1) * slices + i + 2;
  973.                                 }
  974.                         }
  975.  
  976.                         VoxelizeGeometry(vertices, indices, indexCount / 3, worldTM);
  977.                         triangleCount = vertexCount / 3;
  978.                 }
  979.                 break;
  980.         case GEOM_CYLINDER:
  981.                 {
  982.                         const primitives::cylinder& cylinder = *static_cast<const primitives::cylinder*>(geometry->GetData());
  983.  
  984.                         const Vec3 base = cylinder.center - cylinder.axis * cylinder.hh;
  985.                         const Vec3 top = cylinder.center + cylinder.axis * cylinder.hh;
  986.  
  987.                         Vec3 n = cylinder.axis;
  988.                         Vec3 a = n.GetOrthogonal();
  989.  
  990.                         Vec3 b = a.Cross(n);
  991.                         a = n.Cross(b);
  992.  
  993.                         a.Normalize();
  994.                         b.Normalize();
  995.  
  996.                         const size_t slices = 64;
  997.                         const float invSlices = 1.0f / (float)slices;
  998.  
  999.                         const float r = cylinder.r;
  1000.  
  1001.                         const size_t vertexCount = 2 + slices * 4;
  1002.                         Vec3 vertices[vertexCount];
  1003.  
  1004.                         const size_t indexCount = slices * 12;
  1005.                         uint32 indices[indexCount];
  1006.  
  1007.                         vertices[0] = base;
  1008.                         vertices[1] = top;
  1009.  
  1010.                         size_t v = 2;
  1011.                         for (size_t i = 0; i < slices; ++i)
  1012.                         {
  1013.                                 float theta0 = i * (3.14159265f * 2.0f * invSlices);
  1014.                                 float theta1 = (i + 1) * (3.14159265f * 2.0f * invSlices);
  1015.  
  1016.                                 float ctheta0, stheta0;
  1017.                                 sincos_tpl(theta0, &stheta0, &ctheta0);
  1018.                                 vertices[v++] = top + a * (r * ctheta0) + b * (r * stheta0);
  1019.                                 vertices[v++] = base + a * (r * ctheta0) + b * (r * stheta0);
  1020.  
  1021.                                 float ctheta1, stheta1;
  1022.                                 sincos_tpl(theta1, &stheta1, &ctheta1);
  1023.                                 vertices[v++] = base + a * (r * ctheta1) + b * (r * stheta1);
  1024.                                 vertices[v++] = top + a * (r * ctheta1) + b * (r * stheta1);
  1025.                         }
  1026.  
  1027.                         size_t t = 0;
  1028.                         for (size_t i = 0; i < slices; ++i)
  1029.                         {
  1030.                                 indices[t++] = 0;
  1031.                                 indices[t++] = 2 + i * 4 + 1;
  1032.                                 indices[t++] = 2 + i * 4 + 2;
  1033.  
  1034.                                 indices[t++] = 2 + i * 4 + 2;
  1035.                                 indices[t++] = 2 + i * 4 + 1;
  1036.                                 indices[t++] = 2 + i * 4 + 0;
  1037.  
  1038.                                 indices[t++] = 2 + i * 4 + 3;
  1039.                                 indices[t++] = 2 + i * 4 + 2;
  1040.                                 indices[t++] = 2 + i * 4 + 0;
  1041.  
  1042.                                 indices[t++] = 2 + i * 4 + 3;
  1043.                                 indices[t++] = 2 + i * 4 + 0;
  1044.                                 indices[t++] = 1;
  1045.                         }
  1046.  
  1047.                         VoxelizeGeometry(vertices, indices, indexCount / 3, worldTM);
  1048.                         triangleCount = vertexCount / 3;
  1049.                         return triangleCount;
  1050.                 }
  1051.                 break;
  1052.         case GEOM_CAPSULE:
  1053.                 {
  1054.                         const primitives::capsule& capsule = *static_cast<const primitives::capsule*>(geometry->GetData());
  1055.  
  1056.                         const Vec3 base = capsule.center - capsule.axis * capsule.hh;
  1057.                         const Vec3 top = capsule.center + capsule.axis * capsule.hh;
  1058.  
  1059.                         Vec3 n = capsule.axis;
  1060.                         Vec3 a = n.GetOrthogonal();
  1061.  
  1062.                         Vec3 b = a.Cross(n);
  1063.                         a = n.Cross(b);
  1064.  
  1065.                         a.Normalize();
  1066.                         b.Normalize();
  1067.                         n.Normalize();
  1068.  
  1069.                         const size_t stacks = 48;
  1070.                         const size_t slices = 64;
  1071.                         const float invSlices = 1.0f / (float)slices;
  1072.  
  1073.                         const float r = capsule.r;
  1074.  
  1075.                         {
  1076.                                 const size_t vertexCount = 2 + slices * 4;
  1077.                                 Vec3 vertices[vertexCount];
  1078.  
  1079.                                 const size_t indexCount = slices * 6;
  1080.                                 uint32 indices[indexCount];
  1081.  
  1082.                                 vertices[0] = base;
  1083.                                 vertices[1] = top;
  1084.  
  1085.                                 size_t v = 2;
  1086.                                 for (size_t i = 0; i < slices; ++i)
  1087.                                 {
  1088.                                         float theta0 = i * (3.14159265f * 2.0f * invSlices);
  1089.                                         float theta1 = (i + 1) * (3.14159265f * 2.0f * invSlices);
  1090.  
  1091.                                         float ctheta0, stheta0;
  1092.                                         sincos_tpl(theta0, &stheta0, &ctheta0);
  1093.                                         vertices[v++] = top + a * (r * ctheta0) + b * (r * stheta0);
  1094.                                         vertices[v++] = base + a * (r * ctheta0) + b * (r * stheta0);
  1095.  
  1096.                                         float ctheta1, stheta1;
  1097.                                         sincos_tpl(theta1, &stheta1, &ctheta1);
  1098.                                         vertices[v++] = base + a * (r * ctheta1) + b * (r * stheta1);
  1099.                                         vertices[v++] = top + a * (r * ctheta1) + b * (r * stheta1);
  1100.                                 }
  1101.  
  1102.                                 size_t t = 0;
  1103.                                 for (size_t i = 0; i < slices; ++i)
  1104.                                 {
  1105.                                         indices[t++] = 2 + i * 4 + 2;
  1106.                                         indices[t++] = 2 + i * 4 + 1;
  1107.                                         indices[t++] = 2 + i * 4 + 0;
  1108.  
  1109.                                         indices[t++] = 2 + i * 4 + 3;
  1110.                                         indices[t++] = 2 + i * 4 + 2;
  1111.                                         indices[t++] = 2 + i * 4 + 0;
  1112.                                 }
  1113.  
  1114.                                 VoxelizeGeometry(vertices, indices, indexCount / 3, worldTM);
  1115.                                 triangleCount += vertexCount / 3;
  1116.                         }
  1117.  
  1118.                         {
  1119.                                 // Bottom semi-sphere
  1120.                                 const Vec3 baseCenter = base;
  1121.                                 Vec3 baseDirection = baseCenter - capsule.center;
  1122.                                 baseDirection.Normalize();
  1123.  
  1124.                                 const size_t vertexCount = slices * (stacks - 2) + 2;
  1125.                                 Vec3 vertices[vertexCount];
  1126.  
  1127.                                 const size_t indexCount = (slices - 1) * (stacks - 3) * 6 + 6 * (slices - 1);
  1128.                                 uint32 indices[indexCount];
  1129.  
  1130.                                 vertices[0] = baseCenter + a * r;
  1131.                                 vertices[1] = baseCenter - a * r;
  1132.  
  1133.                                 size_t v = 2;
  1134.                                 for (size_t j = 1; j <= stacks - 2; ++j)
  1135.                                 {
  1136.                                         for (size_t i = 0; i < slices; ++i)
  1137.                                         {
  1138.                                                 float theta = (j / (float)(stacks - 1)) * 3.14159265f;
  1139.                                                 float phi = (i / (float)(slices - 1)) * 3.14159265f;
  1140.  
  1141.                                                 float stheta, ctheta;
  1142.                                                 sincos_tpl(theta, &stheta, &ctheta);
  1143.  
  1144.                                                 float sphi, cphi;
  1145.                                                 sincos_tpl(phi, &sphi, &cphi);
  1146.  
  1147.                                                 const Vec3 point = baseCenter + a * ctheta * r + b * stheta * cphi * r + baseDirection * stheta * sphi * r;
  1148.                                                 vertices[v++] = point;
  1149.                                         }
  1150.                                 }
  1151.  
  1152.                                 size_t t = 0;
  1153.                                 for (size_t i = 0; i < slices - 1; ++i)
  1154.                                 {
  1155.                                         indices[t++] = i + 2;
  1156.                                         indices[t++] = i + 3;
  1157.                                         indices[t++] = 0;
  1158.  
  1159.                                         indices[t++] = 1;
  1160.                                         indices[t++] = (stacks - 3) * slices + i + 3;
  1161.                                         indices[t++] = (stacks - 3) * slices + i + 2;
  1162.                                 }
  1163.  
  1164.                                 for (size_t j = 0; j < stacks - 3; ++j)
  1165.                                 {
  1166.                                         for (size_t i = 0; i < slices - 1; ++i)
  1167.                                         {
  1168.                                                 indices[t++] = (j + 1) * slices + i + 3;
  1169.                                                 indices[t++] = j * slices + i + 3;
  1170.                                                 indices[t++] = (j + 1) * slices + i + 2;
  1171.  
  1172.                                                 indices[t++] = j * slices + i + 3;
  1173.                                                 indices[t++] = j * slices + i + 2;
  1174.                                                 indices[t++] = (j + 1) * slices + i + 2;
  1175.                                         }
  1176.                                 }
  1177.  
  1178.                                 VoxelizeGeometry(vertices, indices, indexCount / 3, worldTM);
  1179.                                 triangleCount += vertexCount / 3;
  1180.                         }
  1181.  
  1182.                         {
  1183.                                 // Top semi-sphere
  1184.                                 const Vec3 topCenter = top;
  1185.                                 Vec3 topDirection = topCenter - capsule.center;
  1186.                                 topDirection.Normalize();
  1187.  
  1188.                                 const size_t vertexCount = slices * (stacks - 2) + 2;
  1189.                                 Vec3 vertices[vertexCount];
  1190.  
  1191.                                 const size_t indexCount = (slices - 1) * (stacks - 3) * 6 + 6 * (slices - 1);
  1192.                                 uint32 indices[indexCount];
  1193.  
  1194.                                 vertices[0] = topCenter + a * r;
  1195.                                 vertices[1] = topCenter - a * r;
  1196.  
  1197.                                 size_t v = 2;
  1198.                                 for (size_t j = 1; j <= stacks - 2; ++j)
  1199.                                 {
  1200.                                         for (size_t i = 0; i < slices; ++i)
  1201.                                         {
  1202.                                                 float theta = (j / (float)(stacks - 1)) * 3.14159265f;
  1203.                                                 float phi = (i / (float)(slices - 1)) * 3.14159265f;
  1204.  
  1205.                                                 float stheta, ctheta;
  1206.                                                 sincos_tpl(theta, &stheta, &ctheta);
  1207.  
  1208.                                                 float sphi, cphi;
  1209.                                                 sincos_tpl(phi, &sphi, &cphi);
  1210.  
  1211.                                                 const Vec3 point = topCenter + a * ctheta * r + b * stheta * cphi * r + topDirection * stheta * sphi * r;
  1212.                                                 vertices[v++] = point;
  1213.                                         }
  1214.                                 }
  1215.  
  1216.                                 size_t t = 0;
  1217.                                 for (size_t i = 0; i < slices - 1; ++i)
  1218.                                 {
  1219.                                         indices[t++] = 0;
  1220.                                         indices[t++] = i + 3;
  1221.                                         indices[t++] = i + 2;
  1222.  
  1223.                                         indices[t++] = (stacks - 3) * slices + i + 2;
  1224.                                         indices[t++] = (stacks - 3) * slices + i + 3;
  1225.                                         indices[t++] = 1;
  1226.                                 }
  1227.  
  1228.                                 for (size_t j = 0; j < stacks - 3; ++j)
  1229.                                 {
  1230.                                         for (size_t i = 0; i < slices - 1; ++i)
  1231.                                         {
  1232.                                                 indices[t++] = (j + 1) * slices + i + 2;
  1233.                                                 indices[t++] = j * slices + i + 3;
  1234.                                                 indices[t++] = (j + 1) * slices + i + 3;
  1235.                                                 indices[t++] = (j + 1) * slices + i + 2;
  1236.                                                 indices[t++] = j * slices + i + 2;
  1237.                                                 indices[t++] = j * slices + i + 3;
  1238.                                         }
  1239.                                 }
  1240.  
  1241.                                 VoxelizeGeometry(vertices, indices, indexCount / 3, worldTM);
  1242.                                 triangleCount += vertexCount / 3;
  1243.                         }
  1244.                         return triangleCount;
  1245.                 }
  1246.                 break;
  1247.         case GEOM_HEIGHTFIELD:
  1248.                 return VoxelizeTerrain(geometry, worldTM);
  1249.                 break;
  1250.         }
  1251.  
  1252.         return triangleCount;
  1253. }
  1254. #pragma warning (pop)
  1255. }
  1256.  
downloadVoxelizer.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