diff --git a/documentation/tutorial1.rst b/documentation/tutorial1.rst index 650dd23b..32c45a3c 100644 --- a/documentation/tutorial1.rst +++ b/documentation/tutorial1.rst @@ -82,17 +82,18 @@ Now that we have built our volume we need to convert it into a triangle mesh for .. code-block:: c++ - SurfaceExtractor surfaceExtractor(volData); + SurfaceMesh mesh; + SurfaceExtractor surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh); -Again, note thiat this class is templatised on the voxel type. It also takes a reference to the Volume on which the surface extraction will be performed. +The SurfaceExtractor takes a pointer to the volume data, and also it needs to be told which Region of the Volume the extraction should be performed on (in more advanced application this is useful for extracting only those parts of the volume which have been modified since the last extraction). For our purposes the Volume class provides a convienient Volume::getEnclosingRegion() function which returns a Region representing the whole volume. The constructor also takes a pointer to a SurfaceMesh object whiere it will store the result, so we need to create one of these before we can construct the SurfaceExtractor. -The actual extraction happens in the SurfaceExtractor::extractSurfaceForRegion() function. This function needs to be told which Region of the Volume the extraction should be performed on (in more advanced application this is useful for extracting only those parts of the volume which have been modified since the last extraction), but for our purposes the Volume class provides a convienient Volume::getEnclosingRegion() function which returns a Region representing the whole volume. +The actual extraction happens in the SurfaceExtractor::execute() function. This means you can set up your SurfaceExtractor with the required parameters and then actually execute it later (on a different thread, perhaps). For this example we just call it straight away. .. code-block:: c++ - shared_ptr surface = surfaceExtractor.extractSurfaceForRegion(volData.getEnclosingRegion()); + surfaceExtractor.execute(); -The result is a SurfaceMesh object, which basically contains an index and vertex buffer representing the desired triangle mesh. This is returned via a shared_ptr, meaning it will automatically be deleted once there are no remaining references to it. +This fills in our SurfaceMesh object, which basically contains an index and vertex buffer representing the desired triangle mesh. Rendering the surface ===================== diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index a000d137..1ff76f13 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -82,11 +82,12 @@ int main(int argc, char *argv[]) createSphereInVolume(volData, 30); //Extract the surface - SurfaceExtractor surfaceExtractor(volData); - shared_ptr surface = surfaceExtractor.extractSurfaceForRegion(volData.getEnclosingRegion()); + SurfaceMesh mesh; + SurfaceExtractor surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh); + surfaceExtractor.execute(); //Pass the surface to the OpenGL window - openGLWidget.setSurfaceMeshToRender(*surface); + openGLWidget.setSurfaceMeshToRender(mesh); //Run the message pump. return app.exec(); diff --git a/examples/OpenGL/OpenGLWidget.cpp b/examples/OpenGL/OpenGLWidget.cpp index 90db68d7..75b270b0 100644 --- a/examples/OpenGL/OpenGLWidget.cpp +++ b/examples/OpenGL/OpenGLWidget.cpp @@ -63,8 +63,6 @@ void OpenGLWidget::setVolume(PolyVox::Volume* volData) m_uVolumeHeightInRegions = volData->getHeight() / m_uRegionSideLength; m_uVolumeDepthInRegions = volData->getDepth() / m_uRegionSideLength; - SurfaceExtractor surfaceExtractor(*volData); - //Our volume is broken down into cuboid regions, and we create one mesh for each region. //This three-level for loop iterates over each region. for(uint16_t uRegionZ = 0; uRegionZ < m_uVolumeDepthInRegions; ++uRegionZ) @@ -90,7 +88,10 @@ void OpenGLWidget::setVolume(PolyVox::Volume* volData) //Extract the surface for this region //extractSurface(m_volData, 0, PolyVox::Region(regLowerCorner, regUpperCorner), meshCurrent); - shared_ptr mesh = surfaceExtractor.extractSurfaceForRegion(PolyVox::Region(regLowerCorner, regUpperCorner)); + + shared_ptr mesh(new SurfaceMesh); + SurfaceExtractor surfaceExtractor(volData, PolyVox::Region(regLowerCorner, regUpperCorner), mesh.get()); + surfaceExtractor.execute(); //computeNormalsForVertices(m_volData, *(mesh.get()), SOBEL_SMOOTHED); //*meshCurrent = getSmoothedSurface(*meshCurrent); diff --git a/library/PolyVoxCore/include/SurfaceExtractor.h b/library/PolyVoxCore/include/SurfaceExtractor.h index a2ad9526..3028459b 100644 --- a/library/PolyVoxCore/include/SurfaceExtractor.h +++ b/library/PolyVoxCore/include/SurfaceExtractor.h @@ -39,9 +39,9 @@ namespace PolyVox class SurfaceExtractor { public: - SurfaceExtractor(Volume& volData); + SurfaceExtractor(Volume* volData, Region region, SurfaceMesh* result); - std::shared_ptr extractSurfaceForRegion(Region region); + void execute(); private: //Compute the cell bitmask for a particular slice in z. @@ -71,7 +71,7 @@ namespace PolyVox const Array2DInt32& m_pCurrentVertexIndicesZ); //The volume data and a sampler to access it. - Volume m_volData; + Volume* m_volData; VolumeSampler m_sampVolume; //Holds a position in volume space. @@ -91,6 +91,7 @@ namespace PolyVox SurfaceMesh* m_meshCurrent; //Information about the region we are currently processing + Region m_regInput; Region m_regInputCropped; Region m_regInputUncropped; Region m_regVolumeCropped; diff --git a/library/PolyVoxCore/include/SurfaceExtractor.inl b/library/PolyVoxCore/include/SurfaceExtractor.inl index 7c6e9790..24e0e28a 100644 --- a/library/PolyVoxCore/include/SurfaceExtractor.inl +++ b/library/PolyVoxCore/include/SurfaceExtractor.inl @@ -32,27 +32,29 @@ using namespace std; namespace PolyVox { template - SurfaceExtractor::SurfaceExtractor(Volume& volData) + SurfaceExtractor::SurfaceExtractor(Volume* volData, Region region, SurfaceMesh* result) :m_volData(volData) - ,m_sampVolume(&volData) + ,m_sampVolume(volData) + ,m_regInput(region) + ,m_meshCurrent(result) { } template - shared_ptr SurfaceExtractor::extractSurfaceForRegion(Region region) + void SurfaceExtractor::execute() { - m_regInputUncropped = region; + m_regInputUncropped = m_regInput; //When generating the mesh for a region we actually look outside it in the // back, bottom, right direction. Protect against access violations by cropping region here - m_regVolumeCropped = m_volData.getEnclosingRegion(); + m_regVolumeCropped = m_volData->getEnclosingRegion(); m_regInputUncropped.cropTo(m_regVolumeCropped); m_regVolumeCropped.setUpperCorner(m_regVolumeCropped.getUpperCorner() - Vector3DInt16(1,1,1)); - m_regInputCropped = region; + m_regInputCropped = m_regInput; m_regInputCropped.cropTo(m_regVolumeCropped); - m_meshCurrent = new SurfaceMesh(); + //m_meshCurrent = new SurfaceMesh(); m_uRegionWidth = m_regInputCropped.width(); m_uRegionHeight = m_regInputCropped.height(); @@ -147,8 +149,6 @@ namespace PolyVox lodRecord.beginIndex = 0; lodRecord.endIndex = m_meshCurrent->getNoOfIndices(); m_meshCurrent->m_vecLodRecords.push_back(lodRecord); - - return shared_ptr(m_meshCurrent); } template