From ac3fb840555d142c4d6ecec0f2e7d51ec5190c4f Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Fri, 10 Jan 2014 19:12:45 +0000 Subject: [PATCH] Calculate gradients first to reduce number of calculations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gives about a 2× speedup. --- .../DualContouringSurfaceExtractor.inl | 99 ++++++++++++------- 1 file changed, 66 insertions(+), 33 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/DualContouringSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/DualContouringSurfaceExtractor.inl index 36ed1e4b..74b21cb1 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/DualContouringSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/DualContouringSurfaceExtractor.inl @@ -36,6 +36,7 @@ namespace PolyVox template struct EdgeData { + EdgeData() : intersects(false) {} Vector3DFloat normal; float fraction; ///> gradients; + std::vector> gradients; gradients.reserve(gradientRegionXDimension * gradientRegionYDimension * gradientRegionZDimension); std::vector> cells; cells.reserve(cellRegionXDimension * cellRegionYDimension * cellRegionZDimension); typename VolumeType::Sampler volSampler{volData}; - volSampler.setPosition(region.getLowerCorner()); + volSampler.setPosition(region.getLowerCorner() - Vector3DInt32{1,1,1}); volSampler.setWrapMode(WrapMode::Border, -100.0); // -100.0 is well below the threshold const float threshold = 0.0f; @@ -189,16 +190,17 @@ namespace PolyVox const auto lowerCornerY = region.getLowerCorner().getZ(); const auto lowerCornerZ = region.getLowerCorner().getX(); - for(int32_t cellZ = 0; cellZ < cellRegionZDimension; cellZ++) + for(int32_t z = 0; z < gradientRegionZDimension; z++) { - for(int32_t cellY = 0; cellY < cellRegionYDimension; cellY++) + volSampler.setPosition(lowerCornerX-1, lowerCornerY-1, lowerCornerZ+z-1); //Reset x and y and increment z + for(int32_t y = 0; y < gradientRegionYDimension; y++) { - for(int32_t cellX = 0; cellX < cellRegionXDimension; cellX++) + volSampler.setPosition(lowerCornerX-1, lowerCornerY+y-1, lowerCornerZ+z-1); //Reset x and increment y (z remains the same) + for(int32_t x = 0; x < gradientRegionXDimension; x++) { - //For each cell, calculate the edge intersection points and normals - volSampler.setPosition(lowerCornerX+cellX-1, lowerCornerY+cellY-1, lowerCornerZ+cellZ-1); + volSampler.movePositiveX(); //Increment x - const auto& voxel = static_cast(volSampler.getVoxel()); + const auto& voxel = volSampler.getVoxel(); const auto& voxel1px = static_cast(volSampler.peekVoxel1px0py0pz()); const auto& voxel1py = static_cast(volSampler.peekVoxel0px1py0pz()); const auto& voxel1pz = static_cast(volSampler.peekVoxel0px0py1pz()); @@ -206,30 +208,61 @@ namespace PolyVox const auto& voxel1nx = static_cast(volSampler.peekVoxel1nx0py0pz()); const auto& voxel1ny = static_cast(volSampler.peekVoxel0px1ny0pz()); const auto& voxel1nz = static_cast(volSampler.peekVoxel0px0py1nz()); - const Vector3DFloat g000(voxel1nx - voxel1px, voxel1ny - voxel1py, voxel1nz - voxel1pz); - volSampler.movePositiveX(); - const auto& voxel2px = static_cast(volSampler.peekVoxel1px0py0pz()); - const auto& voxel1px1ny = static_cast(volSampler.peekVoxel0px1ny0pz()); - const auto& voxel1px1py = static_cast(volSampler.peekVoxel0px1py0pz()); - const auto& voxel1px1nz = static_cast(volSampler.peekVoxel0px0py1nz()); - const auto& voxel1px1pz = static_cast(volSampler.peekVoxel0px0py1pz()); - const Vector3DFloat g100(voxel - voxel2px, voxel1px1ny - voxel1px1py, voxel1px1nz - voxel1px1pz); - volSampler.moveNegativeX(); - volSampler.movePositiveY(); - const auto& voxel1nx1py = static_cast(volSampler.peekVoxel1nx0py0pz()); - const auto& voxel2py = static_cast(volSampler.peekVoxel0px1py0pz()); - const auto& voxel1py1nz = static_cast(volSampler.peekVoxel0px0py1nz()); - const auto& voxel1py1pz = static_cast(volSampler.peekVoxel0px0py1pz()); - const Vector3DFloat g010(voxel1nx1py - voxel1px1py, voxel - voxel2py, voxel1py1nz - voxel1py1pz); - volSampler.moveNegativeY(); - volSampler.movePositiveZ(); - const auto& voxel1nx1pz = static_cast(volSampler.peekVoxel1nx0py0pz()); - const auto& voxel1ny1pz = static_cast(volSampler.peekVoxel0px1ny0pz()); - const auto& voxel2pz = static_cast(volSampler.peekVoxel0px0py1pz()); - const Vector3DFloat g001(voxel1nx1pz - voxel1px1pz, voxel1ny1pz - voxel1py1pz, voxel - voxel2pz); + const Vector3DFloat g(voxel1nx - voxel1px, voxel1ny - voxel1py, voxel1nz - voxel1pz); - cells.push_back({calculateEdge(voxel, voxel1px, g000, g100, threshold), calculateEdge(voxel, voxel1py, g000, g010, threshold), calculateEdge(voxel, voxel1pz, g000, g001, threshold)}); + std::pair data(voxel, g); + gradients.push_back(data); + } + } + } + + for(int32_t cellZ = 0; cellZ < cellRegionZDimension; cellZ++) + { + for(int32_t cellY = 0; cellY < cellRegionYDimension; cellY++) + { + for(int32_t cellX = 0; cellX < cellRegionXDimension; cellX++) + { + //For each cell, calculate the edge intersection points and normals + const auto& g000 = gradients[convert(cellX, cellY, cellZ, cellRegionXDimension, cellRegionYDimension)]; + + //For the last columns/rows, only calculate the interior edge + if(cellX < cellRegionXDimension-1 && cellY < cellRegionYDimension-1 && cellZ < cellRegionZDimension-1) //This is the main bulk + { + const auto& g100 = gradients[convert(cellX+1, cellY, cellZ, cellRegionXDimension, cellRegionYDimension)]; + const auto& g010 = gradients[convert(cellX, cellY+1, cellZ, cellRegionXDimension, cellRegionYDimension)]; + const auto& g001 = gradients[convert(cellX, cellY, cellZ+1, cellRegionXDimension, cellRegionYDimension)]; + cells.push_back({calculateEdge(g000.first, g100.first, g000.second, g100.second, threshold), calculateEdge(g000.first, g010.first, g000.second, g010.second, threshold), calculateEdge(g000.first, g001.first, g000.second, g001.second, threshold)}); + } + else if(cellX == cellRegionXDimension-1 || cellY == cellRegionYDimension-1 || cellZ == cellRegionZDimension-1) //This is the three far edges and the far corner + { + cells.push_back({}); //Default and empty + } + else if(cellX == cellRegionXDimension-1) //Far x side + { + const auto& g100 = gradients[convert(cellX+1, cellY, cellZ, cellRegionXDimension, cellRegionYDimension)]; + cells.push_back({calculateEdge(g000.first, g100.first, g000.second, g100.second, threshold), EdgeData(), EdgeData()}); + } + else if(cellY == cellRegionYDimension-1) //Far y side + { + const auto& g010 = gradients[convert(cellX+1, cellY, cellZ, cellRegionXDimension, cellRegionYDimension)]; + cells.push_back({EdgeData(), calculateEdge(g000.first, g010.first, g000.second, g010.second, threshold), EdgeData()}); + } + else if(cellZ == cellRegionZDimension-1) //Far z side + { + const auto& g001 = gradients[convert(cellX+1, cellY, cellZ, cellRegionXDimension, cellRegionYDimension)]; + cells.push_back({EdgeData(), EdgeData(), calculateEdge(g000.first, g001.first, g000.second, g001.second, threshold)}); + } + } + } + } + + for(int32_t cellZ = 0; cellZ < cellRegionZDimension; cellZ++) + { + for(int32_t cellY = 0; cellY < cellRegionYDimension; cellY++) + { + for(int32_t cellX = 0; cellX < cellRegionXDimension; cellX++) + { if(cellZ >= 1 && cellY >= 1 && cellX >= 1) { //After the first rows and columns are done, start calculating vertex positions