Advertisement
Guest User

Untitled

a guest
Jun 27th, 2017
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.88 KB | None | 0 0
  1. //#pragma warning(disable : 4503)
  2. #pragma once
  3. /**
  4. * \file This file contains an implementation of a custom CubicSurfaceExtractor.
  5. *
  6. **/
  7. #include <vector>
  8. #include <utility>
  9. #include <Ogre.h>
  10. #include <PolyVoxForwardDeclarations.h>
  11. #include <Volume.h>
  12. #include <VolumeSampler.h>
  13. #include <PolyVoxImpl/TypeDef.h>
  14. #include "world/WorldDefs.h"
  15. namespace PolyVox
  16. {
  17.         template <typename VoxelType>
  18.         /**
  19.         *\brief This class is a custom class for extracting a cubic surface from PolyVox Volumes using Run Length Encoding.
  20.         *
  21.         *This class takes a PolyVox volume to generate a 1D run length encoding over the voxels while iterating over Z slices (constant Z per slice). For each
  22.         *slice update, it uses this RLE information to merge faces; for Z and Y facing faces, it merges per iteration of Y; for X facing faces, it merges per
  23.         *iteration of Z (since X facing faces' run length are computed in the Y direction as per iteration over Z slices).
  24.         **/
  25.         class ZCubicSurfaceExtractor
  26.         {
  27.         public:
  28.             ZCubicSurfaceExtractor(Volume<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterial>* result);
  29.  
  30.             void execute();
  31.  
  32.         private:
  33.            
  34.             static const VoxelType AIR_BLOCK = 0;
  35.            
  36.             enum AXIS
  37.             {
  38.                 X = 0, Y, Z
  39.             };
  40.             enum FACE
  41.             {
  42.                 MYFACE = 1, NOTMYFACE=0, NOFACE=-1
  43.             };
  44.  
  45.             struct RLE_VOXEL
  46.             {
  47.                 RLE_VOXEL(VoxelType mat, uint16_t len, FACE which)
  48.                     : material(mat), length(len), whichFace(which)
  49.                 {
  50.                 }
  51.                 VoxelType material;
  52.                 uint16_t length;
  53.                 FACE whichFace;
  54.             };
  55.  
  56.             struct RLE_INFO
  57.             {
  58.                 uint16_t faceCount;
  59.                 VoxelType faceMaterial;
  60.                 FACE whichFace;
  61.             };
  62.  
  63.             //material id, count, face orientation.
  64.             //typedef std::pair<VoxelType, std::pair<size_t, FACE> > RLE;
  65.             typedef std::vector<RLE_VOXEL> RLE_VEC;
  66.             Volume<VoxelType>* _volData;
  67.             //VolumeSampler<VoxelType> _sampVolume;
  68.  
  69.             SurfaceMesh<PositionMaterial>* _meshCurrent;
  70.  
  71.             Region _regSizeInVoxels;
  72.             Region _regSizeInCells;
  73.  
  74.             void _resetParams(uint16_t x, uint16_t y, uint16_t z, FACE &whichFace,
  75.                 VoxelType &faceMaterial, AXIS xyz);
  76.  
  77.             void _markRLE(VoxelType &faceMaterial, VoxelType currentMaterial,
  78.                 VoxelType currentMaterialPlus, uint16_t &faceCount, FACE &previousWhichFace,
  79.                 RLE_VEC& rleVec);
  80.             void _finalizeRLE(VoxelType faceMaterial, uint16_t faceCount,
  81.                 FACE previousWhichFace, RLE_VEC& rleVec);
  82.  
  83.             void _mergeFace(RLE_VEC &rleVec,
  84.                 uint16_t regX, uint16_t regY, uint16_t regZ,
  85.                 AXIS xyz);
  86.         };
  87. }
  88.  
  89. #include "ZCubicSurfaceExtractor.inl"
  90.  
  91. //ZCubicSurfaceExtractor.inl
  92.  
  93. #include <iostream>
  94. using std::cout;
  95. using std::endl;
  96. #include <Array.h>
  97. #include <MaterialDensityPair.h>
  98. #include <SurfaceMesh.h>
  99. #include <PolyVoxImpl/MarchingCubesTables.h>
  100. #include <VertexTypes.h>
  101. namespace PolyVox
  102. {
  103.     template <typename VoxelType>
  104.     ZCubicSurfaceExtractor<VoxelType>::ZCubicSurfaceExtractor(Volume<VoxelType>* volData, Region region,
  105.         SurfaceMesh<PositionMaterial>* result) : _volData(volData),
  106.         //_sampVolume(volData),
  107.         _regSizeInVoxels(region),
  108.         _meshCurrent(result)
  109.     {
  110.         _regSizeInVoxels.cropTo(_volData->getEnclosingRegion());
  111.         _regSizeInCells = _regSizeInVoxels;
  112.         _regSizeInCells.setUpperCorner(_regSizeInCells.getUpperCorner() - Vector3DInt16(1, 1, 1));
  113.         _meshCurrent->clear();
  114.     }
  115.  
  116.     template <typename VoxelType>
  117.     inline void ZCubicSurfaceExtractor<VoxelType>::_resetParams(uint16_t x, uint16_t y, uint16_t z,
  118.         FACE &whichFace, VoxelType &faceMaterial, AXIS xyz)
  119.     {
  120.         faceMaterial = _volData->getVoxelAt(x, y, z);
  121.         VoxelType plusMaterial;
  122.  
  123.         switch(xyz)
  124.         {
  125.         case Z:
  126.             plusMaterial = _volData->getVoxelAt(x, y, z+1);
  127.             break;
  128.         case Y:
  129.             plusMaterial = _volData->getVoxelAt(x, y+1, z);
  130.             break;
  131.         case X:
  132.             plusMaterial = _volData->getVoxelAt(x+1, y, z);
  133.             break;    
  134.         }
  135.         bool A = faceMaterial > AIR_BLOCK;
  136.         bool B = plusMaterial > AIR_BLOCK;
  137.         if(A == B)
  138.         {
  139.             whichFace = NOFACE;
  140.             faceMaterial = 0;
  141.             return;
  142.         }
  143.         if(A > B)
  144.         {
  145.             whichFace = MYFACE;
  146.             return;
  147.         }
  148.         if(A < B)
  149.         {
  150.             whichFace = NOTMYFACE;
  151.             faceMaterial = plusMaterial;
  152.             return;
  153.         }    
  154.     }
  155.  
  156.     /**
  157.     * This method will extract a surface from the voxel data. The surface that is extracted will be decimated through
  158.     * RLE; such that, for a slice the number of faces will be less than or equal to the number of voxels for that slice.
  159.     * \precondition the volume data is valid in that it specifies a valid region of data (take notice of boundary conditions else you will get holes).
  160.     * \postcondition a surface is extracted from the given Volume and that surfaces has been merged through RLE.
  161.     **/
  162.     template <typename VoxelType>
  163.     void ZCubicSurfaceExtractor<VoxelType>::execute()
  164.     {
  165.         using namespace PolyVox;
  166.  
  167.         const size_t WORLD_BLOCK_WIDTH = _regSizeInVoxels.depth() + 1;
  168.         std::vector<RLE_VEC> rleXs(WORLD_BLOCK_WIDTH);
  169.         std::vector<RLE_INFO> rleXsInfo(WORLD_BLOCK_WIDTH);
  170.  
  171.         for(uint16_t z = _regSizeInVoxels.getLowerCorner().getZ(); z <= _regSizeInVoxels.getUpperCorner().getZ(); z++)
  172.         {
  173.             uint16_t startX = _regSizeInVoxels.getLowerCorner().getX();
  174.             //Initialize X faces
  175.             for(size_t i = 0; i < WORLD_BLOCK_WIDTH; ++i)
  176.             {
  177.                 rleXsInfo[i].faceCount = 0;
  178.                 _resetParams(i, _regSizeInVoxels.getLowerCorner().getY(), z,
  179.                     rleXsInfo[i].whichFace, rleXsInfo[i].faceMaterial, X);
  180.             }
  181.  
  182.             uint16_t regZ = z - _regSizeInVoxels.getLowerCorner().getZ();
  183.  
  184.             for(uint16_t y = _regSizeInVoxels.getLowerCorner().getY(); y <= _regSizeInVoxels.getUpperCorner().getY(); y++)
  185.             {
  186.  
  187.                 //Initialize Z face.
  188.                 uint16_t zFaceCount = 0;
  189.  
  190.                 FACE zWhichFace; //whether face is on voxel or face is on next voxel.
  191.                 VoxelType zFaceMaterial;
  192.                 _resetParams(startX, y, z, zWhichFace, zFaceMaterial, Z);
  193.                 RLE_VEC rleZ;
  194.  
  195.                 //Initialize Y face
  196.                 uint16_t yFaceCount = 0;
  197.                 FACE yWhichFace;
  198.                 VoxelType yFaceMaterial;
  199.                 _resetParams(startX, y, z, yWhichFace, yFaceMaterial, Y);
  200.                 RLE_VEC rleY;
  201.  
  202.                 uint16_t regY = y - _regSizeInVoxels.getLowerCorner().getY();
  203.  
  204.                 for(uint16_t x = _regSizeInVoxels.getLowerCorner().getX(); x <= _regSizeInVoxels.getUpperCorner().getX(); x++)
  205.                 {
  206.                     //Start at the lower corner x.
  207.                     uint16_t regX = x - _regSizeInVoxels.getLowerCorner().getX();
  208.                     //int currentVoxel = _volData->getVoxelAt(x, y, z).getDensity() >= VoxelType::getThreshold();
  209.                     //int plusZVoxel = _volData->getVoxelAt(x, y, z+1).getDensity() >= VoxelType::getThreshold();
  210.                     //int plusYVoxel = _volData->getVoxelAt(x, y+1, z).getDensity() >= VoxelType::getThreshold();
  211.                     //int plusXVoxel = _volData->getVoxelAt(x+1, y, z).getDensity() >= VoxelType::getThreshold();
  212.                    
  213.                     VoxelType currentMaterial = _volData->getVoxelAt(x, y, z);
  214.                     VoxelType currentMaterialPlusZ = _volData->getVoxelAt(x, y, z+1);
  215.                     VoxelType currentMaterialPlusY = _volData->getVoxelAt(x, y+1, z);
  216.                     VoxelType currentMaterialPlusX = _volData->getVoxelAt(x + 1, y, z);
  217.  
  218.                     _markRLE(zFaceMaterial, currentMaterial,
  219.                         currentMaterialPlusZ, zFaceCount, zWhichFace,
  220.                         rleZ);
  221.  
  222.                     _markRLE(yFaceMaterial, currentMaterial,
  223.                         currentMaterialPlusY, yFaceCount, yWhichFace,
  224.                         rleY);
  225.                     _markRLE(rleXsInfo[regX].faceMaterial, currentMaterial,
  226.                         currentMaterialPlusX, rleXsInfo[regX].faceCount, rleXsInfo[regX].whichFace,
  227.                         rleXs[regX]);
  228.                 }
  229.                 _finalizeRLE(zFaceMaterial, zFaceCount, zWhichFace, rleZ);
  230.                 _finalizeRLE(yFaceMaterial, yFaceCount, yWhichFace, rleY);
  231.                 _mergeFace(rleZ, 0, regY, regZ, Z);
  232.                 _mergeFace(rleY, 0, regY, regZ, Y);
  233.             }
  234.  
  235.             for(size_t i = 0; i < WORLD_BLOCK_WIDTH; ++i)
  236.             {
  237.  
  238.                 _finalizeRLE(rleXsInfo[i].faceMaterial, rleXsInfo[i].faceCount, rleXsInfo[i].whichFace,
  239.                     rleXs[i]);
  240.                 _mergeFace(rleXs[i],
  241.                     (uint16_t)(i), 0, regZ, X);
  242.                 rleXs[i].clear();
  243.             }
  244.         }
  245.      
  246.         _meshCurrent->m_Region = _regSizeInVoxels;
  247.         _meshCurrent->m_vecLodRecords.clear();
  248.         LodRecord lodRecord;
  249.         lodRecord.beginIndex = 0;
  250.         lodRecord.endIndex = _meshCurrent->getNoOfIndices();
  251.         _meshCurrent->m_vecLodRecords.push_back(lodRecord);
  252.  
  253.     }
  254.  
  255.  
  256.  
  257.     /** This method will mark a slice based on RLE given book keeping data for RLE.**/
  258.     template <typename VoxelType>
  259.     inline void ZCubicSurfaceExtractor<VoxelType>::_markRLE(VoxelType &faceMaterial, VoxelType currentMaterial,
  260.         VoxelType currentMaterialPlus, uint16_t &faceCount, FACE &previousWhichFace,
  261.         RLE_VEC &rleVec)
  262.     {
  263.         bool A = currentMaterial > AIR_BLOCK;
  264.         bool B = currentMaterialPlus > AIR_BLOCK;
  265.  
  266.         if(A == B) //The current voxel and plusVoxel must have the same material (AIR or Any Material)
  267.         {
  268.             if(previousWhichFace == NOFACE)
  269.             {
  270.                 faceCount++;
  271.             }
  272.             else
  273.             {
  274.                 rleVec.push_back(RLE_VOXEL(faceMaterial, faceCount, previousWhichFace)); //write facematerial, count, and which face face is facing.
  275.                 previousWhichFace = NOFACE;
  276.                 faceMaterial = AIR_BLOCK;
  277.                 faceCount = 1;
  278.             }
  279.             return;
  280.         }
  281.         if(A > B) //If current voxel is greater than plusVoxel
  282.         {
  283.             if(previousWhichFace == MYFACE)
  284.             {
  285.                 if(faceMaterial == currentMaterial)
  286.                     faceCount++;
  287.                 else
  288.                 {
  289.                     rleVec.push_back(RLE_VOXEL(faceMaterial, faceCount, previousWhichFace));
  290.                     //previousWhichFace = MYFACE;
  291.                     faceMaterial = currentMaterial;
  292.                     faceCount = 1;
  293.                 }
  294.             }
  295.             else //The previous face is NOTMYFACE or NOFACE, meaning the face has flipped to MyFace.
  296.             {
  297.                 rleVec.push_back(RLE_VOXEL(faceMaterial, faceCount, previousWhichFace));
  298.                 previousWhichFace = MYFACE;
  299.                 faceMaterial = currentMaterial;
  300.                 faceCount = 1;
  301.             }
  302.             return;
  303.         }
  304.         if(A < B) //CurrentVoxel is less than plusVoxel.
  305.         {
  306.             if(previousWhichFace == MYFACE)
  307.             {
  308.                 rleVec.push_back(RLE_VOXEL(faceMaterial, faceCount, previousWhichFace));
  309.                 previousWhichFace = NOTMYFACE;
  310.                 faceMaterial = currentMaterialPlus;
  311.                 faceCount = 1;
  312.             }
  313.             else
  314.             {
  315.                 if(faceMaterial == currentMaterialPlus)
  316.                 {
  317.                     faceCount++;
  318.                 }
  319.                 else
  320.                 {
  321.                     rleVec.push_back(RLE_VOXEL(faceMaterial, faceCount, previousWhichFace));
  322.                     previousWhichFace = NOTMYFACE;
  323.                     faceMaterial = currentMaterialPlus;
  324.                     faceCount = 1;
  325.                 }
  326.             }
  327.             return;
  328.         }
  329.     }
  330.  
  331.     /** This method does the final step in marking a slice with RLE. Basically, the last run length data needs to be written out (i.e the state machine
  332.     has reached a final state, in the final state we need to write out the last bit of Run Length).**/
  333.     template <typename VoxelType>
  334.     inline void ZCubicSurfaceExtractor<VoxelType>::_finalizeRLE(
  335.         VoxelType faceMaterial, uint16_t faceCount, FACE previousWhichFace,
  336.         RLE_VEC& rleVec)
  337.     {
  338.         rleVec.push_back(RLE_VOXEL(faceMaterial, faceCount, previousWhichFace));
  339.     }
  340.  
  341.     /** This method will generate faces given a Run Length Encoding vector representing compressed faces.**/
  342.     template <typename VoxelType>
  343.     inline void ZCubicSurfaceExtractor<VoxelType>::_mergeFace(RLE_VEC &rleVec,
  344.         uint16_t regX, uint16_t regY, uint16_t regZ, AXIS xyz)
  345.     {
  346.         uint16_t count = 0;
  347.         for(size_t i = 0; i < rleVec.size(); ++i)
  348.         {
  349.             count = rleVec[i].length;
  350.            
  351.             if(rleVec[i].material > AIR_BLOCK)
  352.             {
  353.                 uint32_t v0, v1, v2, v3;
  354.                 //Lower left corner
  355.                 VoxelType faceMaterial = rleVec[i].material;
  356.  
  357.                 switch(xyz)
  358.                 {
  359.                 case Z: //z axis
  360.                     v0 = _meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY - 0.5f, regZ + 0.5f),
  361.                         faceMaterial));
  362.                     //upper left corner
  363.                     v1 = _meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f),
  364.                         faceMaterial));
  365.                     //lower right corner
  366.                     v2 = _meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + count - 0.5f, regY - 0.5f, regZ + 0.5f),
  367.                         faceMaterial));
  368.                     //upper right corner
  369.                     v3 = _meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + count - 0.5f, regY + 0.5f, regZ + 0.5f),
  370.                         faceMaterial));
  371.                     if(rleVec[i].whichFace== MYFACE)
  372.                     {
  373.  
  374.                         _meshCurrent->addTriangleCubic(v0, v2, v1);
  375.                         _meshCurrent->addTriangleCubic(v1, v2, v3);
  376.                     }
  377.                     else
  378.                     {
  379.                         _meshCurrent->addTriangleCubic(v0, v1, v2);
  380.                         _meshCurrent->addTriangleCubic(v1, v3, v2);
  381.                     }
  382.                     break;
  383.                 case Y: //y axis
  384.                     v0 = _meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ - 0.5f),
  385.                         faceMaterial));
  386.                     //upper left corner
  387.                     v1 = _meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f),
  388.                         faceMaterial));
  389.                     //lower right corner
  390.                     v2 = _meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + count - 0.5f, regY + 0.5f, regZ - 0.5f),
  391.                         faceMaterial));
  392.                     //upper right corner
  393.                     v3 = _meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + count - 0.5f, regY + 0.5f, regZ + 0.5f),
  394.                         faceMaterial));
  395.                    
  396.                     if(rleVec[i].whichFace == MYFACE)
  397.                     {
  398.                          _meshCurrent->addTriangleCubic(v0, v1, v2);
  399.                          _meshCurrent->addTriangleCubic(v1, v3, v2);
  400.                     }
  401.                     else
  402.                     {
  403.  
  404.                         _meshCurrent->addTriangleCubic(v0, v2, v1);
  405.                         _meshCurrent->addTriangleCubic(v1, v2, v3);
  406.                     }
  407.                     break;
  408.                 case X:
  409.                     v0 = _meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ - 0.5f),
  410.                         faceMaterial));
  411.                     //upper left corner
  412.                     v1 = _meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f),
  413.                         faceMaterial));
  414.                     //lower right corner
  415.                     v2 = _meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY + count - 0.5f, regZ - 0.5f),
  416.                         faceMaterial));
  417.                     //upper right corner
  418.                     v3 = _meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY + count - 0.5f, regZ + 0.5f),
  419.                         faceMaterial));
  420.                     if(rleVec[i].whichFace == MYFACE)
  421.                     {
  422.  
  423.                         _meshCurrent->addTriangleCubic(v0, v2, v1);
  424.                         _meshCurrent->addTriangleCubic(v1, v2, v3);
  425.                     }
  426.                     else
  427.                     {
  428.                         _meshCurrent->addTriangleCubic(v0, v1, v2);
  429.                         _meshCurrent->addTriangleCubic(v1, v3, v2);
  430.                     }
  431.                     break;
  432.                 default:
  433.                     break;
  434.                 }
  435.  
  436.             }
  437.             switch(xyz)
  438.             {
  439.             case Z:
  440.             case Y:
  441.                 regX += count;
  442.                 break;
  443.             case X:
  444.                 regY += count;
  445.                 break;
  446.             }
  447.         }
  448.  
  449.  
  450.     }
  451. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement