From 51e93fdabce340810fd1304ffd0edec3e9e5ce99 Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 22 May 2014 16:25:36 +0200 Subject: [PATCH 01/72] Modifying the OpenGLWidget so that it can render multiple meshes. --- examples/Basic/OpenGLWidget.cpp | 18 +++++++++--------- examples/Basic/OpenGLWidget.h | 13 +++++++++---- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index a3f6ad96..ad0facfa 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -21,17 +21,17 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh), vecVertices.data(), GL_STATIC_DRAW); //and GL_ELEMENT_ARRAY_BUFFER will contain the indices - glGenBuffers(1, &indexBuffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); + glGenBuffers(1, &(mMeshData.indexBuffer)); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mMeshData.indexBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), vecIndices.data(), GL_STATIC_DRAW); //We need to tell OpenGL how to understand the format of the vertex data @@ -40,7 +40,7 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh #include +struct OpenGLMeshData +{ + GLuint noOfIndices; + GLuint indexBuffer; + GLuint vertexBuffer; + GLuint vertexArrayObject; +}; + class OpenGLWidget : public QGLWidget { public: @@ -52,10 +60,7 @@ protected: private: //Index/vertex buffer data - GLuint noOfIndices; - GLuint indexBuffer; - GLuint vertexBuffer; - GLuint vertexArrayObject; + OpenGLMeshData mMeshData; QGLShaderProgram shader; From 7d55e00f7686744ba2af998ded014d818c7c8ba9 Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 22 May 2014 16:38:02 +0200 Subject: [PATCH 02/72] More work adding support for multiple meshes. --- examples/Basic/OpenGLWidget.cpp | 41 ++++++++++++++++++++------------- examples/Basic/OpenGLWidget.h | 2 +- examples/Basic/main.cpp | 6 ++++- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index ad0facfa..e9998220 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -19,19 +19,23 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh), vecVertices.data(), GL_STATIC_DRAW); //and GL_ELEMENT_ARRAY_BUFFER will contain the indices - glGenBuffers(1, &(mMeshData.indexBuffer)); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mMeshData.indexBuffer); + glGenBuffers(1, &(meshData.indexBuffer)); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshData.indexBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), vecIndices.data(), GL_STATIC_DRAW); //We need to tell OpenGL how to understand the format of the vertex data @@ -40,7 +44,9 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh mMeshData; QGLShaderProgram shader; diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index 09dc5423..3b04f04c 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -78,11 +78,15 @@ int main(int argc, char *argv[]) createSphereInVolume(volData, 30); // Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see. - auto mesh = extractCubicSurface(&volData, volData.getEnclosingRegion()); + //auto mesh = extractCubicSurface(&volData, volData.getEnclosingRegion()); //auto mesh = extractMarchingCubesSurface(&volData, volData.getEnclosingRegion()); + + auto mesh = extractCubicSurface(&volData, PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(31, 31, 31))); + auto mesh2 = extractCubicSurface(&volData, PolyVox::Region(Vector3DInt32(32, 32, 32), Vector3DInt32(63, 63, 63))); //Pass the surface to the OpenGL window openGLWidget.setSurfaceMeshToRender(mesh); + openGLWidget.setSurfaceMeshToRender(mesh2); //Run the message pump. return app.exec(); From 16cbb94d90b1d8a1df1c89759beba30c2f47b52e Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 22 May 2014 16:51:41 +0200 Subject: [PATCH 03/72] Rotation is now applied by moving the camera rather than the meshes. --- examples/Basic/OpenGLWidget.cpp | 27 +++++++++++++++------------ examples/Basic/main.cpp | 8 ++++---- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index e9998220..5ca5880f 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -129,15 +129,6 @@ void OpenGLWidget::initializeGL() std::cerr << shader.log().toStdString() << std::endl; exit(EXIT_FAILURE); } - - shader.bind(); - - QMatrix4x4 worldToCameraMatrix{}; - worldToCameraMatrix.translate(0, 0, -50); //Move the camera back by 50 units - - shader.setUniformValue("worldToCameraMatrix", worldToCameraMatrix); - - shader.release(); } void OpenGLWidget::resizeGL(int w, int h) @@ -163,9 +154,9 @@ void OpenGLWidget::paintGL() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); QMatrix4x4 modelToWorldMatrix{}; - modelToWorldMatrix.rotate(m_xRotation, 0, 1, 0); //rotate around y-axis - modelToWorldMatrix.rotate(m_yRotation, 1, 0, 0); //rotate around x-axis - modelToWorldMatrix.translate(-32, -32, -32); //centre the model on the origin + //modelToWorldMatrix.rotate(m_xRotation, 0, 1, 0); //rotate around y-axis + //modelToWorldMatrix.rotate(m_yRotation, 1, 0, 0); //rotate around x-axis + //modelToWorldMatrix.translate(-32, -32, -32); //centre the model on the origin shader.bind(); @@ -205,5 +196,17 @@ void OpenGLWidget::mouseMoveEvent(QMouseEvent* event) m_yRotation += diff.y(); m_LastFrameMousePos = m_CurrentMousePos; + shader.bind(); + + QMatrix4x4 worldToCameraMatrix{}; + worldToCameraMatrix.translate(0, 0, -50); //Move the camera back by 50 units + worldToCameraMatrix.rotate(m_xRotation, 0, 1, 0); //rotate around y-axis + worldToCameraMatrix.rotate(m_yRotation, 1, 0, 0); //rotate around x-axis + worldToCameraMatrix.translate(-32, -32, -32); //centre the model on the origin + + shader.setUniformValue("worldToCameraMatrix", worldToCameraMatrix); + + shader.release(); + update(); } diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index 3b04f04c..72dd96eb 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -78,15 +78,15 @@ int main(int argc, char *argv[]) createSphereInVolume(volData, 30); // Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see. - //auto mesh = extractCubicSurface(&volData, volData.getEnclosingRegion()); + auto mesh = extractCubicSurface(&volData, volData.getEnclosingRegion()); //auto mesh = extractMarchingCubesSurface(&volData, volData.getEnclosingRegion()); - auto mesh = extractCubicSurface(&volData, PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(31, 31, 31))); - auto mesh2 = extractCubicSurface(&volData, PolyVox::Region(Vector3DInt32(32, 32, 32), Vector3DInt32(63, 63, 63))); + //auto mesh = extractCubicSurface(&volData, PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(31, 31, 31))); + //auto mesh2 = extractCubicSurface(&volData, PolyVox::Region(Vector3DInt32(32, 32, 32), Vector3DInt32(63, 63, 63))); //Pass the surface to the OpenGL window openGLWidget.setSurfaceMeshToRender(mesh); - openGLWidget.setSurfaceMeshToRender(mesh2); + //openGLWidget.setSurfaceMeshToRender(mesh2); //Run the message pump. return app.exec(); From f8ce3a5f3d2f42f83c1fd557d8420ceb65700d80 Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 22 May 2014 17:03:06 +0200 Subject: [PATCH 04/72] Tidying camera code. --- examples/Basic/OpenGLWidget.cpp | 19 ++++++++++++++----- examples/Basic/OpenGLWidget.h | 7 +++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index 5ca5880f..17355b2f 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -9,6 +9,8 @@ using namespace std; OpenGLWidget::OpenGLWidget(QWidget *parent) :QGLWidget(parent) + ,mCenterPoint(32,32,32) + ,mDistFromCenter(50) ,m_xRotation(0) ,m_yRotation(0) { @@ -129,6 +131,8 @@ void OpenGLWidget::initializeGL() std::cerr << shader.log().toStdString() << std::endl; exit(EXIT_FAILURE); } + + setupWorldToCameraMatrix(); } void OpenGLWidget::resizeGL(int w, int h) @@ -196,17 +200,22 @@ void OpenGLWidget::mouseMoveEvent(QMouseEvent* event) m_yRotation += diff.y(); m_LastFrameMousePos = m_CurrentMousePos; + setupWorldToCameraMatrix(); + + update(); +} + +void OpenGLWidget::setupWorldToCameraMatrix() +{ shader.bind(); QMatrix4x4 worldToCameraMatrix{}; - worldToCameraMatrix.translate(0, 0, -50); //Move the camera back by 50 units + worldToCameraMatrix.translate(0, 0, -mDistFromCenter); //Move the camera back by the required amount worldToCameraMatrix.rotate(m_xRotation, 0, 1, 0); //rotate around y-axis worldToCameraMatrix.rotate(m_yRotation, 1, 0, 0); //rotate around x-axis - worldToCameraMatrix.translate(-32, -32, -32); //centre the model on the origin + worldToCameraMatrix.translate(-mCenterPoint); //centre the model on the origin shader.setUniformValue("worldToCameraMatrix", worldToCameraMatrix); shader.release(); - - update(); -} +} \ No newline at end of file diff --git a/examples/Basic/OpenGLWidget.h b/examples/Basic/OpenGLWidget.h index b797b5b3..5e7e46d9 100644 --- a/examples/Basic/OpenGLWidget.h +++ b/examples/Basic/OpenGLWidget.h @@ -59,6 +59,9 @@ protected: void paintGL(); private: + + void setupWorldToCameraMatrix(); + //Index/vertex buffer data std::vector mMeshData; @@ -67,6 +70,10 @@ private: //Mouse data QPoint m_LastFrameMousePos; QPoint m_CurrentMousePos; + + //Camera setup + QVector3D mCenterPoint; + float mDistFromCenter; int m_xRotation; int m_yRotation; }; From ab741583e4504df1674e574f7c7e8d8f16e4b081 Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 22 May 2014 23:26:40 +0200 Subject: [PATCH 05/72] Renamed extractXxxSurface() to extractXxxMesh() --- examples/Basic/main.cpp | 10 +++++----- examples/Paging/main.cpp | 2 +- examples/SmoothLOD/main.cpp | 4 ++-- .../include/PolyVoxCore/CubicSurfaceExtractor.h | 8 ++++---- .../PolyVoxCore/MarchingCubesSurfaceExtractor.h | 8 ++++---- tests/TestCubicSurfaceExtractor.cpp | 2 +- tests/TestSurfaceExtractor.cpp | 2 +- tests/TestVolumeSubclass.cpp | 2 +- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index 72dd96eb..78de21d4 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -77,12 +77,12 @@ int main(int argc, char *argv[]) SimpleVolume volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(63, 63, 63))); createSphereInVolume(volData, 30); - // Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see. - auto mesh = extractCubicSurface(&volData, volData.getEnclosingRegion()); - //auto mesh = extractMarchingCubesSurface(&volData, volData.getEnclosingRegion()); + // Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see. + auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion()); + //auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion()); - //auto mesh = extractCubicSurface(&volData, PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(31, 31, 31))); - //auto mesh2 = extractCubicSurface(&volData, PolyVox::Region(Vector3DInt32(32, 32, 32), Vector3DInt32(63, 63, 63))); + //auto mesh = extractCubicMesh(&volData, PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(31, 31, 31))); + //auto mesh2 = extractCubicMesh(&volData, PolyVox::Region(Vector3DInt32(32, 32, 32), Vector3DInt32(63, 63, 63))); //Pass the surface to the OpenGL window openGLWidget.setSurfaceMeshToRender(mesh); diff --git a/examples/Paging/main.cpp b/examples/Paging/main.cpp index b1134fdd..d1e0ae09 100644 --- a/examples/Paging/main.cpp +++ b/examples/Paging/main.cpp @@ -186,7 +186,7 @@ int main(int argc, char *argv[]) std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl; //Extract the surface - auto mesh = extractCubicSurface(&volData, reg); + auto mesh = extractCubicMesh(&volData, reg); std::cout << "#vertices: " << mesh.getNoOfVertices() << std::endl; //Pass the surface to the OpenGL window diff --git a/examples/SmoothLOD/main.cpp b/examples/SmoothLOD/main.cpp index 2e97c876..5bc79f96 100644 --- a/examples/SmoothLOD/main.cpp +++ b/examples/SmoothLOD/main.cpp @@ -90,11 +90,11 @@ int main(int argc, char *argv[]) volumeResampler.execute(); //Extract the surface - auto meshLowLOD = extractMarchingCubesSurface(&volDataLowLOD, volDataLowLOD.getEnclosingRegion()); + auto meshLowLOD = extractMarchingCubesMesh(&volDataLowLOD, volDataLowLOD.getEnclosingRegion()); meshLowLOD.scaleVertices(/*2.0f*/63.0f / 31.0f); //Extract the surface - auto meshHighLOD = extractMarchingCubesSurface(&volData, PolyVox::Region(Vector3DInt32(30, 0, 0), Vector3DInt32(63, 63, 63))); + auto meshHighLOD = extractMarchingCubesMesh(&volData, PolyVox::Region(Vector3DInt32(30, 0, 0), Vector3DInt32(63, 63, 63))); meshHighLOD.translateVertices(Vector3DFloat(30, 0, 0)); //Pass the surface to the OpenGL window diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h index b4493d29..01020ad3 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h @@ -159,7 +159,7 @@ namespace PolyVox }; template - SurfaceMesh > extractCubicSurface(VolumeType* volData, Region region, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded) + SurfaceMesh > extractCubicMesh(VolumeType* volData, Region region, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded) { SurfaceMesh > result; CubicSurfaceExtractor extractor(volData, region, &result, eWrapMode, tBorderValue, bMergeQuads, isQuadNeeded); @@ -171,13 +171,13 @@ namespace PolyVox // This is a bit ugly - it seems that the C++03 syntax is different from the C++11 syntax? See this thread: http://stackoverflow.com/questions/6076015/typename-outside-of-template // Long term we should probably come back to this and if the #ifdef is still needed then maybe it should check for C++11 mode instead of MSVC? #if defined(_MSC_VER) - SurfaceMesh > extractCubicSurface(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true) + SurfaceMesh > extractCubicMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true) #else - SurfaceMesh > extractCubicSurface(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true) + SurfaceMesh > extractCubicMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true) #endif { DefaultIsQuadNeeded isQuadNeeded; - return extractCubicSurface >(volData, region, eWrapMode, tBorderValue, bMergeQuads, isQuadNeeded); + return extractCubicMesh >(volData, region, eWrapMode, tBorderValue, bMergeQuads, isQuadNeeded); } } diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h index fe541f74..cf403ab0 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h @@ -212,7 +212,7 @@ namespace PolyVox }; template< typename VolumeType, typename Controller> - SurfaceMesh > extractMarchingCubesSurface(VolumeType* volData, Region region, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, Controller controller) + SurfaceMesh > extractMarchingCubesMesh(VolumeType* volData, Region region, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, Controller controller) { SurfaceMesh > result; MarchingCubesSurfaceExtractor extractor(volData, region, &result, eWrapMode, tBorderValue, controller); @@ -224,13 +224,13 @@ namespace PolyVox // This is a bit ugly - it seems that the C++03 syntax is different from the C++11 syntax? See this thread: http://stackoverflow.com/questions/6076015/typename-outside-of-template // Long term we should probably come back to this and if the #ifdef is still needed then maybe it should check for C++11 mode instead of MSVC? #if defined(_MSC_VER) - SurfaceMesh > extractMarchingCubesSurface(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType()) + SurfaceMesh > extractMarchingCubesMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType()) #else - SurfaceMesh > extractMarchingCubesSurface(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType()) + SurfaceMesh > extractMarchingCubesMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType()) #endif { DefaultMarchingCubesController controller; - return extractMarchingCubesSurface(volData, region, eWrapMode, tBorderValue, controller); + return extractMarchingCubesMesh(volData, region, eWrapMode, tBorderValue, controller); } } diff --git a/tests/TestCubicSurfaceExtractor.cpp b/tests/TestCubicSurfaceExtractor.cpp index 3696cd42..7c74dee1 100644 --- a/tests/TestCubicSurfaceExtractor.cpp +++ b/tests/TestCubicSurfaceExtractor.cpp @@ -108,7 +108,7 @@ uint32_t testForType(void) { Region regionToExtract(x, y, z, x + uRegionSideLength - 1, y + uRegionSideLength - 1, z + uRegionSideLength - 1); - auto result = extractCubicSurface(&volData, regionToExtract); + auto result = extractCubicMesh(&volData, regionToExtract); uTotalVertices += result.getNoOfVertices(); uTotalIndices += result.getNoOfIndices(); diff --git a/tests/TestSurfaceExtractor.cpp b/tests/TestSurfaceExtractor.cpp index 47d5404b..c11541a5 100644 --- a/tests/TestSurfaceExtractor.cpp +++ b/tests/TestSurfaceExtractor.cpp @@ -128,7 +128,7 @@ SurfaceMesh > testForType(void) //I think we coul DefaultMarchingCubesController controller; controller.setThreshold(50); - auto result = extractMarchingCubesSurface(&volData, volData.getEnclosingRegion(), WrapModes::Border, VoxelType(), controller); + auto result = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion(), WrapModes::Border, VoxelType(), controller); return result; } diff --git a/tests/TestVolumeSubclass.cpp b/tests/TestVolumeSubclass.cpp index 7562f1ef..73351113 100644 --- a/tests/TestVolumeSubclass.cpp +++ b/tests/TestVolumeSubclass.cpp @@ -184,7 +184,7 @@ void TestVolumeSubclass::testExtractSurface() } } - auto result = extractCubicSurface(&volumeSubclass, volumeSubclass.getEnclosingRegion()); + auto result = extractCubicMesh(&volumeSubclass, volumeSubclass.getEnclosingRegion()); QCOMPARE(result.getNoOfVertices(), static_cast(8)); } From 4cec89de384169f77b56aaa0da0dec4c41162e66 Mon Sep 17 00:00:00 2001 From: David Williams Date: Fri, 23 May 2014 14:32:46 +0200 Subject: [PATCH 06/72] Added ability to specify the visible region so that the example framework can support different volume sizes. --- examples/Basic/OpenGLWidget.cpp | 19 +++++++++++++++---- examples/Basic/OpenGLWidget.h | 5 +++-- examples/Basic/main.cpp | 1 + 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index 17355b2f..eb47180e 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -9,8 +9,7 @@ using namespace std; OpenGLWidget::OpenGLWidget(QWidget *parent) :QGLWidget(parent) - ,mCenterPoint(32,32,32) - ,mDistFromCenter(50) + ,m_viewableRegion(Region(0, 0, 0, 255, 255, 255)) ,m_xRotation(0) ,m_yRotation(0) { @@ -51,6 +50,12 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh); + void setViewableRegion(PolyVox::Region viewableRegion); + protected: //Qt OpenGL functions void initializeGL(); @@ -72,8 +74,7 @@ private: QPoint m_CurrentMousePos; //Camera setup - QVector3D mCenterPoint; - float mDistFromCenter; + PolyVox::Region m_viewableRegion; int m_xRotation; int m_yRotation; }; diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index 78de21d4..82031152 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -86,6 +86,7 @@ int main(int argc, char *argv[]) //Pass the surface to the OpenGL window openGLWidget.setSurfaceMeshToRender(mesh); + openGLWidget.setViewableRegion(volData.getEnclosingRegion()); //openGLWidget.setSurfaceMeshToRender(mesh2); //Run the message pump. From da8f294847a1e5835baf5f70ba6d0f9739f3e58d Mon Sep 17 00:00:00 2001 From: David Williams Date: Fri, 23 May 2014 14:37:35 +0200 Subject: [PATCH 07/72] Comments --- examples/Basic/OpenGLWidget.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/Basic/OpenGLWidget.h b/examples/Basic/OpenGLWidget.h index 9009bad8..f95dbdbb 100644 --- a/examples/Basic/OpenGLWidget.h +++ b/examples/Basic/OpenGLWidget.h @@ -42,20 +42,21 @@ struct OpenGLMeshData class OpenGLWidget : public QGLWidget { public: - //Constructor + // Constructor OpenGLWidget(QWidget *parent); - //Mouse handling + // Mouse handling void mouseMoveEvent(QMouseEvent* event); void mousePressEvent(QMouseEvent* event); - //Convert a SurfaceMesh to OpenGL index/vertex buffers + // Convert a SurfaceMesh to OpenGL index/vertex buffers void setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh); + // The viewable region can be adjusted so that this example framework can be use for different volume sizes. void setViewableRegion(PolyVox::Region viewableRegion); protected: - //Qt OpenGL functions + // Qt OpenGL functions void initializeGL(); void resizeGL(int w, int h); void paintGL(); @@ -64,16 +65,16 @@ private: void setupWorldToCameraMatrix(); - //Index/vertex buffer data + // Index/vertex buffer data std::vector mMeshData; QGLShaderProgram shader; - //Mouse data + // Mouse data QPoint m_LastFrameMousePos; QPoint m_CurrentMousePos; - //Camera setup + // Camera setup PolyVox::Region m_viewableRegion; int m_xRotation; int m_yRotation; From 4aae00e4a8d0458f18dadff4e48750f7572cbb71 Mon Sep 17 00:00:00 2001 From: David Williams Date: Fri, 23 May 2014 15:17:07 +0200 Subject: [PATCH 08/72] Renamed SurfaceMesh to just Mesh --- examples/Basic/OpenGLWidget.cpp | 2 +- examples/Basic/OpenGLWidget.h | 4 +- examples/Basic/main.cpp | 6 +- .../OpenGL/OpenGLImmediateModeSupport.cpp | 4 +- examples/OpenGL/OpenGLImmediateModeSupport.h | 2 +- .../OpenGLVertexBufferObjectSupport.cpp | 20 +- .../OpenGL/OpenGLVertexBufferObjectSupport.h | 8 +- examples/OpenGL/OpenGLWidget.cpp | 18 +- examples/OpenGL/OpenGLWidget.h | 6 +- examples/OpenGL/main.cpp | 2 +- examples/Paging/OpenGLWidget.cpp | 2 +- examples/Paging/OpenGLWidget.h | 4 +- examples/Paging/main.cpp | 8 +- examples/SmoothLOD/OpenGLWidget.cpp | 4 +- examples/SmoothLOD/OpenGLWidget.h | 6 +- examples/SmoothLOD/main.cpp | 10 +- library/PolyVoxCore/CMakeLists.txt | 4 +- .../PolyVoxCore/CubicSurfaceExtractor.h | 16 +- .../PolyVoxCore/CubicSurfaceExtractor.inl | 2 +- .../include/PolyVoxCore/GradientEstimators.h | 2 +- .../MarchingCubesSurfaceExtractor.h | 16 +- .../MarchingCubesSurfaceExtractor.inl | 16 +- .../PolyVoxCore/{SurfaceMesh.h => Mesh.h} | 208 ++-- .../PolyVoxCore/{SurfaceMesh.inl => Mesh.inl} | 976 +++++++++--------- .../PolyVoxCore/PolyVoxForwardDeclarations.h | 4 +- tests/TestCubicSurfaceExtractor.cpp | 2 +- tests/TestSurfaceExtractor.cpp | 6 +- 27 files changed, 679 insertions(+), 679 deletions(-) rename library/PolyVoxCore/include/PolyVoxCore/{SurfaceMesh.h => Mesh.h} (86%) rename library/PolyVoxCore/include/PolyVoxCore/{SurfaceMesh.inl => Mesh.inl} (85%) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index eb47180e..7fb5f2cb 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -15,7 +15,7 @@ OpenGLWidget::OpenGLWidget(QWidget *parent) { } -void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh) +void OpenGLWidget::setMeshToRender(const PolyVox::Mesh >& surfaceMesh) { //Convienient access to the vertices and indices const auto& vecIndices = surfaceMesh.getIndices(); diff --git a/examples/Basic/OpenGLWidget.h b/examples/Basic/OpenGLWidget.h index f95dbdbb..266ee0e6 100644 --- a/examples/Basic/OpenGLWidget.h +++ b/examples/Basic/OpenGLWidget.h @@ -24,7 +24,7 @@ distribution. #ifndef __BasicExample_OpenGLWidget_H__ #define __BasicExample_OpenGLWidget_H__ -#include "PolyVoxCore/SurfaceMesh.h" +#include "PolyVoxCore/Mesh.h" #include "glew/glew.h" @@ -50,7 +50,7 @@ public: void mousePressEvent(QMouseEvent* event); // Convert a SurfaceMesh to OpenGL index/vertex buffers - void setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh); + void setMeshToRender(const PolyVox::Mesh >& surfaceMesh); // The viewable region can be adjusted so that this example framework can be use for different volume sizes. void setViewableRegion(PolyVox::Region viewableRegion); diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index 82031152..c3a53f59 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -25,7 +25,7 @@ freely, subject to the following restrictions: #include "PolyVoxCore/CubicSurfaceExtractor.h" #include "PolyVoxCore/MarchingCubesSurfaceExtractor.h" -#include "PolyVoxCore/SurfaceMesh.h" +#include "PolyVoxCore/Mesh.h" #include "PolyVoxCore/SimpleVolume.h" #include @@ -85,9 +85,9 @@ int main(int argc, char *argv[]) //auto mesh2 = extractCubicMesh(&volData, PolyVox::Region(Vector3DInt32(32, 32, 32), Vector3DInt32(63, 63, 63))); //Pass the surface to the OpenGL window - openGLWidget.setSurfaceMeshToRender(mesh); + openGLWidget.setMeshToRender(mesh); openGLWidget.setViewableRegion(volData.getEnclosingRegion()); - //openGLWidget.setSurfaceMeshToRender(mesh2); + //openGLWidget.setMeshToRender(mesh2); //Run the message pump. return app.exec(); diff --git a/examples/OpenGL/OpenGLImmediateModeSupport.cpp b/examples/OpenGL/OpenGLImmediateModeSupport.cpp index 7aff64df..ab2522bd 100644 --- a/examples/OpenGL/OpenGLImmediateModeSupport.cpp +++ b/examples/OpenGL/OpenGLImmediateModeSupport.cpp @@ -24,12 +24,12 @@ freely, subject to the following restrictions: #include "OpenGLImmediateModeSupport.h" #include "OpenGLSupport.h" -#include "PolyVoxCore/SurfaceMesh.h" +#include "PolyVoxCore/Mesh.h" using namespace PolyVox; using namespace std; -void renderRegionImmediateMode(PolyVox::SurfaceMesh >& mesh, unsigned int uLodLevel) +void renderRegionImmediateMode(PolyVox::Mesh >& mesh, unsigned int uLodLevel) { const vector >& vecVertices = mesh.getVertices(); const vector& vecIndices = mesh.getIndices(); diff --git a/examples/OpenGL/OpenGLImmediateModeSupport.h b/examples/OpenGL/OpenGLImmediateModeSupport.h index 9f5aea79..3bc45a2b 100644 --- a/examples/OpenGL/OpenGLImmediateModeSupport.h +++ b/examples/OpenGL/OpenGLImmediateModeSupport.h @@ -29,6 +29,6 @@ freely, subject to the following restrictions: #include "glew/glew.h" -void renderRegionImmediateMode(PolyVox::SurfaceMesh >& mesh, unsigned int uLodLevel); +void renderRegionImmediateMode(PolyVox::Mesh >& mesh, unsigned int uLodLevel); #endif //__OpenGLExample_OpenGLImmediateModeSupport_H__ diff --git a/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp b/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp index ae5afd15..17e9e138 100644 --- a/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp +++ b/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp @@ -25,15 +25,15 @@ freely, subject to the following restrictions: #include "OpenGLVertexBufferObjectSupport.h" #include "PolyVoxCore/MaterialDensityPair.h" -#include "PolyVoxCore/SurfaceMesh.h" +#include "PolyVoxCore/Mesh.h" using namespace PolyVox; using namespace std; -OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const SurfaceMesh >& mesh) +OpenGLMesh BuildOpenGLMesh(const Mesh >& mesh) { //Represents our filled in OpenGL vertex and index buffer objects. - OpenGLSurfaceMesh result; + OpenGLMesh result; //The source result.sourceMesh = &mesh; @@ -102,23 +102,23 @@ OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const SurfaceMeshm_vecLodRecords[uLodLevel].beginIndex; - int endIndex = openGLSurfaceMesh.sourceMesh->m_vecLodRecords[uLodLevel].endIndex; - glBindBuffer(GL_ARRAY_BUFFER, openGLSurfaceMesh.vertexBuffer); + int beginIndex = openGLMesh.sourceMesh->m_vecLodRecords[uLodLevel].beginIndex; + int endIndex = openGLMesh.sourceMesh->m_vecLodRecords[uLodLevel].endIndex; + glBindBuffer(GL_ARRAY_BUFFER, openGLMesh.vertexBuffer); glVertexPointer(3, GL_FLOAT, 36, 0); glNormalPointer(GL_FLOAT, 36, (GLvoid*)12); glColorPointer(3, GL_FLOAT, 36, (GLvoid*)24); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, openGLSurfaceMesh.indexBuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, openGLMesh.indexBuffer); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); - //glDrawElements(GL_TRIANGLES, openGLSurfaceMesh.noOfIndices, GL_UNSIGNED_INT, 0); - glDrawRangeElements(GL_TRIANGLES, beginIndex, endIndex-1, endIndex - beginIndex,/* openGLSurfaceMesh.noOfIndices,*/ GL_UNSIGNED_INT, 0); + //glDrawElements(GL_TRIANGLES, openGLMesh.noOfIndices, GL_UNSIGNED_INT, 0); + glDrawRangeElements(GL_TRIANGLES, beginIndex, endIndex-1, endIndex - beginIndex,/* openGLMesh.noOfIndices,*/ GL_UNSIGNED_INT, 0); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); diff --git a/examples/OpenGL/OpenGLVertexBufferObjectSupport.h b/examples/OpenGL/OpenGLVertexBufferObjectSupport.h index fc97dfb8..e82a8c29 100644 --- a/examples/OpenGL/OpenGLVertexBufferObjectSupport.h +++ b/examples/OpenGL/OpenGLVertexBufferObjectSupport.h @@ -28,15 +28,15 @@ freely, subject to the following restrictions: #include "glew/glew.h" -struct OpenGLSurfaceMesh +struct OpenGLMesh { GLulong noOfIndices; GLuint indexBuffer; GLuint vertexBuffer; - const PolyVox::SurfaceMesh >* sourceMesh; + const PolyVox::Mesh >* sourceMesh; }; -OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const PolyVox::SurfaceMesh >& mesh); -void renderRegionVertexBufferObject(const OpenGLSurfaceMesh& openGLSurfaceMesh, unsigned int uLodLevel); +OpenGLMesh BuildOpenGLMesh(const PolyVox::Mesh >& mesh); +void renderRegionVertexBufferObject(const OpenGLMesh& openGLMesh, unsigned int uLodLevel); #endif //__OpenGLExample_OpenGLVertexBufferObjectSupport_H__ diff --git a/examples/OpenGL/OpenGLWidget.cpp b/examples/OpenGL/OpenGLWidget.cpp index 475ba846..38c107a9 100644 --- a/examples/OpenGL/OpenGLWidget.cpp +++ b/examples/OpenGL/OpenGLWidget.cpp @@ -50,8 +50,8 @@ OpenGLWidget::OpenGLWidget(QWidget *parent) void OpenGLWidget::setVolume(PolyVox::LargeVolume* volData) { //First we free anything from the previous volume (if there was one). - m_mapOpenGLSurfaceMeshes.clear(); - m_mapSurfaceMeshes.clear(); + m_mapOpenGLMeshes.clear(); + m_mapMeshes.clear(); m_volData = volData; //If we have any volume data then generate the new surface patches. @@ -87,7 +87,7 @@ void OpenGLWidget::setVolume(PolyVox::LargeVolume* volDat //Extract the surface for this region //extractSurface(m_volData, 0, PolyVox::Region(regLowerCorner, regUpperCorner), meshCurrent); - std::shared_ptr< SurfaceMesh > > mesh(new SurfaceMesh >); + std::shared_ptr< Mesh > > mesh(new Mesh >); MarchingCubesSurfaceExtractor< LargeVolume > surfaceExtractor(volData, PolyVox::Region(regLowerCorner, regUpperCorner), mesh.get()); surfaceExtractor.execute(); @@ -105,12 +105,12 @@ void OpenGLWidget::setVolume(PolyVox::LargeVolume* volDat Vector3DUint8 v3dRegPos(uRegionX,uRegionY,uRegionZ); if(m_bUseOpenGLVertexBufferObjects) { - OpenGLSurfaceMesh openGLSurfaceMesh = BuildOpenGLSurfaceMesh(*(mesh.get())); - m_mapOpenGLSurfaceMeshes.insert(make_pair(v3dRegPos, openGLSurfaceMesh)); + OpenGLMesh openGLMesh = BuildOpenGLMesh(*(mesh.get())); + m_mapOpenGLMeshes.insert(make_pair(v3dRegPos, openGLMesh)); } //else //{ - m_mapSurfaceMeshes.insert(make_pair(v3dRegPos, mesh)); + m_mapMeshes.insert(make_pair(v3dRegPos, mesh)); //} //delete meshCurrent; } @@ -191,13 +191,13 @@ void OpenGLWidget::paintGL() for(uint16_t uRegionX = 0; uRegionX < m_uVolumeWidthInRegions; ++uRegionX) { Vector3DUint8 v3dRegPos(uRegionX,uRegionY,uRegionZ); - if(m_mapSurfaceMeshes.find(v3dRegPos) != m_mapSurfaceMeshes.end()) + if(m_mapMeshes.find(v3dRegPos) != m_mapMeshes.end()) { - std::shared_ptr< SurfaceMesh > > meshCurrent = m_mapSurfaceMeshes[v3dRegPos]; + std::shared_ptr< Mesh > > meshCurrent = m_mapMeshes[v3dRegPos]; unsigned int uLodLevel = 0; //meshCurrent->m_vecLodRecords.size() - 1; if(m_bUseOpenGLVertexBufferObjects) { - renderRegionVertexBufferObject(m_mapOpenGLSurfaceMeshes[v3dRegPos], uLodLevel); + renderRegionVertexBufferObject(m_mapOpenGLMeshes[v3dRegPos], uLodLevel); } else { diff --git a/examples/OpenGL/OpenGLWidget.h b/examples/OpenGL/OpenGLWidget.h index 1b4b4612..3511ac75 100644 --- a/examples/OpenGL/OpenGLWidget.h +++ b/examples/OpenGL/OpenGLWidget.h @@ -30,7 +30,7 @@ freely, subject to the following restrictions: #include #include "PolyVoxCore/LargeVolume.h" -#include "PolyVoxCore/SurfaceMesh.h" +#include "PolyVoxCore/Mesh.h" #include "PolyVoxCore/Impl/Utility.h" #include "OpenGLImmediateModeSupport.h" @@ -87,8 +87,8 @@ class OpenGLWidget : public QGLWidget PolyVox::LargeVolume* m_volData; //Rather than storing one big mesh, the volume is broken into regions and a mesh is stored for each region - std::map m_mapOpenGLSurfaceMeshes; - std::map > >, Vector3DUint8Compare> m_mapSurfaceMeshes; + std::map m_mapOpenGLMeshes; + std::map > >, Vector3DUint8Compare> m_mapMeshes; unsigned int m_uRegionSideLength; unsigned int m_uVolumeWidthInRegions; diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index e6ae33d7..ab70e957 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -27,7 +27,7 @@ freely, subject to the following restrictions: #include "PolyVoxCore/LowPassFilter.h" #include "PolyVoxCore/RawVolume.h" #include "PolyVoxCore/RLEBlockCompressor.h" -#include "PolyVoxCore/SurfaceMesh.h" +#include "PolyVoxCore/Mesh.h" #include "PolyVoxCore/Impl/Utility.h" #include "OpenGLImmediateModeSupport.h" diff --git a/examples/Paging/OpenGLWidget.cpp b/examples/Paging/OpenGLWidget.cpp index 0227a66f..fa2aa7be 100644 --- a/examples/Paging/OpenGLWidget.cpp +++ b/examples/Paging/OpenGLWidget.cpp @@ -15,7 +15,7 @@ OpenGLWidget::OpenGLWidget(QWidget *parent) { } -void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh) +void OpenGLWidget::setMeshToRender(const PolyVox::Mesh >& surfaceMesh) { if((surfaceMesh.getNoOfIndices() == 0) || (surfaceMesh.getNoOfVertices() == 0)) { diff --git a/examples/Paging/OpenGLWidget.h b/examples/Paging/OpenGLWidget.h index 61702be1..63afbb97 100644 --- a/examples/Paging/OpenGLWidget.h +++ b/examples/Paging/OpenGLWidget.h @@ -25,7 +25,7 @@ distribution. #define __BasicExample_OpenGLWidget_H__ #include "PolyVoxCore/MaterialDensityPair.h" -#include "PolyVoxCore/SurfaceMesh.h" +#include "PolyVoxCore/Mesh.h" #include "glew/glew.h" @@ -42,7 +42,7 @@ public: void mousePressEvent(QMouseEvent* event); //Convert a SrfaceMesh to OpenGL index/vertex buffers - void setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh); + void setMeshToRender(const PolyVox::Mesh >& surfaceMesh); protected: //Qt OpenGL functions diff --git a/examples/Paging/main.cpp b/examples/Paging/main.cpp index d1e0ae09..77c64d16 100644 --- a/examples/Paging/main.cpp +++ b/examples/Paging/main.cpp @@ -29,7 +29,7 @@ freely, subject to the following restrictions: #include "PolyVoxCore/MarchingCubesSurfaceExtractor.h" #include "PolyVoxCore/Pager.h" #include "PolyVoxCore/RLEBlockCompressor.h" -#include "PolyVoxCore/SurfaceMesh.h" +#include "PolyVoxCore/Mesh.h" #include "PolyVoxCore/LargeVolume.h" #include @@ -185,12 +185,12 @@ int main(int argc, char *argv[]) std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl; std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl; - //Extract the surface - auto mesh = extractCubicMesh(&volData, reg); + //Extract the surface + auto mesh = extractCubicMesh(&volData, reg); std::cout << "#vertices: " << mesh.getNoOfVertices() << std::endl; //Pass the surface to the OpenGL window - openGLWidget.setSurfaceMeshToRender(mesh); + openGLWidget.setMeshToRender(mesh); //Run the message pump. return app.exec(); diff --git a/examples/SmoothLOD/OpenGLWidget.cpp b/examples/SmoothLOD/OpenGLWidget.cpp index e804240b..d487f73b 100644 --- a/examples/SmoothLOD/OpenGLWidget.cpp +++ b/examples/SmoothLOD/OpenGLWidget.cpp @@ -21,7 +21,7 @@ OpenGLWidget::OpenGLWidget(QWidget *parent) { } -void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh) +void OpenGLWidget::setMeshToRender(const PolyVox::Mesh >& surfaceMesh) { //Convienient access to the vertices and indices const vector& vecIndices = surfaceMesh.getIndices(); @@ -43,7 +43,7 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh) +void OpenGLWidget::setMeshToRenderLowLOD(const PolyVox::Mesh >& surfaceMesh) { //Convienient access to the vertices and indices const vector& vecIndices = surfaceMesh.getIndices(); diff --git a/examples/SmoothLOD/OpenGLWidget.h b/examples/SmoothLOD/OpenGLWidget.h index 895e9e74..af5b96ee 100644 --- a/examples/SmoothLOD/OpenGLWidget.h +++ b/examples/SmoothLOD/OpenGLWidget.h @@ -24,7 +24,7 @@ distribution. #ifndef __BasicExample_OpenGLWidget_H__ #define __BasicExample_OpenGLWidget_H__ -#include "PolyVoxCore/SurfaceMesh.h" +#include "PolyVoxCore/Mesh.h" #include "glew/glew.h" @@ -41,8 +41,8 @@ public: void mousePressEvent(QMouseEvent* event); //Convert a SrfaceMesh to OpenGL index/vertex buffers - void setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh); - void setSurfaceMeshToRenderLowLOD(const PolyVox::SurfaceMesh >& surfaceMesh); + void setMeshToRender(const PolyVox::Mesh >& surfaceMesh); + void setMeshToRenderLowLOD(const PolyVox::Mesh >& surfaceMesh); protected: //Qt OpenGL functions diff --git a/examples/SmoothLOD/main.cpp b/examples/SmoothLOD/main.cpp index 5bc79f96..a0dc6dcd 100644 --- a/examples/SmoothLOD/main.cpp +++ b/examples/SmoothLOD/main.cpp @@ -25,7 +25,7 @@ freely, subject to the following restrictions: #include "PolyVoxCore/Density.h" #include "PolyVoxCore/MarchingCubesSurfaceExtractor.h" -#include "PolyVoxCore/SurfaceMesh.h" +#include "PolyVoxCore/Mesh.h" #include "PolyVoxCore/RawVolume.h" #include "PolyVoxCore/SimpleVolume.h" #include "PolyVoxCore/VolumeResampler.h" @@ -89,17 +89,17 @@ int main(int argc, char *argv[]) VolumeResampler< SimpleVolume, RawVolume > volumeResampler(&volData, PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(31, 63, 63)), &volDataLowLOD, volDataLowLOD.getEnclosingRegion()); volumeResampler.execute(); - //Extract the surface + //Extract the surface auto meshLowLOD = extractMarchingCubesMesh(&volDataLowLOD, volDataLowLOD.getEnclosingRegion()); meshLowLOD.scaleVertices(/*2.0f*/63.0f / 31.0f); //Extract the surface - auto meshHighLOD = extractMarchingCubesMesh(&volData, PolyVox::Region(Vector3DInt32(30, 0, 0), Vector3DInt32(63, 63, 63))); + auto meshHighLOD = extractMarchingCubesMesh(&volData, PolyVox::Region(Vector3DInt32(30, 0, 0), Vector3DInt32(63, 63, 63))); meshHighLOD.translateVertices(Vector3DFloat(30, 0, 0)); //Pass the surface to the OpenGL window - openGLWidget.setSurfaceMeshToRender(meshHighLOD); - openGLWidget.setSurfaceMeshToRenderLowLOD(meshLowLOD); + openGLWidget.setMeshToRender(meshHighLOD); + openGLWidget.setMeshToRenderLowLOD(meshLowLOD); //Run the message pump. return app.exec(); diff --git a/library/PolyVoxCore/CMakeLists.txt b/library/PolyVoxCore/CMakeLists.txt index e4289feb..42844fce 100644 --- a/library/PolyVoxCore/CMakeLists.txt +++ b/library/PolyVoxCore/CMakeLists.txt @@ -84,8 +84,8 @@ SET(CORE_INC_FILES include/PolyVoxCore/SimpleVolume.inl include/PolyVoxCore/SimpleVolumeBlock.inl include/PolyVoxCore/SimpleVolumeSampler.inl - include/PolyVoxCore/SurfaceMesh.h - include/PolyVoxCore/SurfaceMesh.inl + include/PolyVoxCore/Mesh.h + include/PolyVoxCore/Mesh.inl include/PolyVoxCore/UncompressedBlock.h include/PolyVoxCore/UncompressedBlock.inl include/PolyVoxCore/Vector.h diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h index 01020ad3..03e973a3 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h @@ -31,7 +31,7 @@ freely, subject to the following restrictions: #include "PolyVoxCore/Array.h" #include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these? #include "PolyVoxCore/DefaultIsQuadNeeded.h" -#include "PolyVoxCore/SurfaceMesh.h" +#include "PolyVoxCore/Mesh.h" namespace PolyVox { @@ -113,9 +113,9 @@ namespace PolyVox // This is a bit ugly - it seems that the C++03 syntax is different from the C++11 syntax? See this thread: http://stackoverflow.com/questions/6076015/typename-outside-of-template // Long term we should probably come back to this and if the #ifdef is still needed then maybe it should check for C++11 mode instead of MSVC? #if defined(_MSC_VER) - CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); + CubicSurfaceExtractor(VolumeType* volData, Region region, Mesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); #else - CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); + CubicSurfaceExtractor(VolumeType* volData, Region region, Mesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); #endif @@ -135,7 +135,7 @@ namespace PolyVox Region m_regSizeInVoxels; //The surface patch we are currently filling. - SurfaceMesh >* m_meshCurrent; + Mesh >* m_meshCurrent; //Used to avoid creating duplicate vertices. Array<3, IndexAndMaterial> m_previousSliceVertices; @@ -159,9 +159,9 @@ namespace PolyVox }; template - SurfaceMesh > extractCubicMesh(VolumeType* volData, Region region, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded) + Mesh > extractCubicMesh(VolumeType* volData, Region region, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded) { - SurfaceMesh > result; + Mesh > result; CubicSurfaceExtractor extractor(volData, region, &result, eWrapMode, tBorderValue, bMergeQuads, isQuadNeeded); extractor.execute(); return result; @@ -171,9 +171,9 @@ namespace PolyVox // This is a bit ugly - it seems that the C++03 syntax is different from the C++11 syntax? See this thread: http://stackoverflow.com/questions/6076015/typename-outside-of-template // Long term we should probably come back to this and if the #ifdef is still needed then maybe it should check for C++11 mode instead of MSVC? #if defined(_MSC_VER) - SurfaceMesh > extractCubicMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true) + Mesh > extractCubicMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true) #else - SurfaceMesh > extractCubicMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true) + Mesh > extractCubicMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true) #endif { DefaultIsQuadNeeded isQuadNeeded; diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl index 822b9256..5bc067a9 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl @@ -36,7 +36,7 @@ namespace PolyVox const uint32_t CubicSurfaceExtractor::MaxVerticesPerPosition = 8; template - CubicSurfaceExtractor::CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded) + CubicSurfaceExtractor::CubicSurfaceExtractor(VolumeType* volData, Region region, Mesh >* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded) :m_volData(volData) ,m_regSizeInVoxels(region) ,m_meshCurrent(result) diff --git a/library/PolyVoxCore/include/PolyVoxCore/GradientEstimators.h b/library/PolyVoxCore/include/PolyVoxCore/GradientEstimators.h index cb8fcbe4..871dbcb2 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/GradientEstimators.h +++ b/library/PolyVoxCore/include/PolyVoxCore/GradientEstimators.h @@ -55,7 +55,7 @@ namespace PolyVox template Vector3DFloat computeSmoothSobelGradient(typename VolumeType::Sampler& volIter); - //POLYVOX_API void computeNormalsForVertices(VolumeType* volumeData, SurfaceMesh& mesh, NormalGenerationMethod normalGenerationMethod); + //POLYVOX_API void computeNormalsForVertices(VolumeType* volumeData, Mesh& mesh, NormalGenerationMethod normalGenerationMethod); //POLYVOX_API Vector3DFloat computeNormal(VolumeType* volumeData, const Vector3DFloat& v3dPos, NormalGenerationMethod normalGenerationMethod); } diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h index cf403ab0..6510ac5c 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h @@ -29,7 +29,7 @@ freely, subject to the following restrictions: #include "PolyVoxCore/Array.h" #include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these? -#include "PolyVoxCore/SurfaceMesh.h" +#include "PolyVoxCore/Mesh.h" #include "PolyVoxCore/DefaultMarchingCubesController.h" namespace PolyVox @@ -41,9 +41,9 @@ namespace PolyVox // This is a bit ugly - it seems that the C++03 syntax is different from the C++11 syntax? See this thread: http://stackoverflow.com/questions/6076015/typename-outside-of-template // Long term we should probably come back to this and if the #ifdef is still needed then maybe it should check for C++11 mode instead of MSVC? #if defined(_MSC_VER) - MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), Controller controller = Controller()); + MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, Mesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), Controller controller = Controller()); #else - MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), Controller controller = Controller()); + MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, Mesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), Controller controller = Controller()); #endif void execute(); @@ -193,7 +193,7 @@ namespace PolyVox uint32_t m_uNoOfOccupiedCells; //The surface patch we are currently filling. - SurfaceMesh >* m_meshCurrent; + Mesh >* m_meshCurrent; //Information about the region we are currently processing Region m_regSizeInVoxels; @@ -212,9 +212,9 @@ namespace PolyVox }; template< typename VolumeType, typename Controller> - SurfaceMesh > extractMarchingCubesMesh(VolumeType* volData, Region region, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, Controller controller) + Mesh > extractMarchingCubesMesh(VolumeType* volData, Region region, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, Controller controller) { - SurfaceMesh > result; + Mesh > result; MarchingCubesSurfaceExtractor extractor(volData, region, &result, eWrapMode, tBorderValue, controller); extractor.execute(); return result; @@ -224,9 +224,9 @@ namespace PolyVox // This is a bit ugly - it seems that the C++03 syntax is different from the C++11 syntax? See this thread: http://stackoverflow.com/questions/6076015/typename-outside-of-template // Long term we should probably come back to this and if the #ifdef is still needed then maybe it should check for C++11 mode instead of MSVC? #if defined(_MSC_VER) - SurfaceMesh > extractMarchingCubesMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType()) + Mesh > extractMarchingCubesMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType()) #else - SurfaceMesh > extractMarchingCubesMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType()) + Mesh > extractMarchingCubesMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType()) #endif { DefaultMarchingCubesController controller; diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl index 5c2868d9..99998bf4 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl @@ -25,8 +25,8 @@ freely, subject to the following restrictions: namespace PolyVox { - template - MarchingCubesSurfaceExtractor::MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, Controller controller) + template + MarchingCubesSurfaceExtractor::MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, Mesh >* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, Controller controller) :m_volData(volData) ,m_sampVolume(volData) ,m_meshCurrent(result) @@ -456,10 +456,10 @@ namespace PolyVox v3dNormal.normalise(); } - // Allow the controller to decide how the material should be derived from the voxels. + // Allow the controller to decide how the material should be derived from the voxels. const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v100, fInterp); - const MarchingCubesVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); + const MarchingCubesVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); m_pCurrentVertexIndicesX[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; @@ -485,11 +485,11 @@ namespace PolyVox v3dNormal.normalise(); } - // Allow the controller to decide how the material should be derived from the voxels. + // Allow the controller to decide how the material should be derived from the voxels. const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v010, fInterp); MarchingCubesVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); - uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); + uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); m_pCurrentVertexIndicesY[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; m_sampVolume.moveNegativeY(); @@ -513,10 +513,10 @@ namespace PolyVox v3dNormal.normalise(); } - // Allow the controller to decide how the material should be derived from the voxels. + // Allow the controller to decide how the material should be derived from the voxels. const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v001, fInterp); - const MarchingCubesVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); + const MarchingCubesVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); m_pCurrentVertexIndicesZ[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; diff --git a/library/PolyVoxCore/include/PolyVoxCore/SurfaceMesh.h b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h similarity index 86% rename from library/PolyVoxCore/include/PolyVoxCore/SurfaceMesh.h rename to library/PolyVoxCore/include/PolyVoxCore/Mesh.h index 1de4a905..90ebbfac 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/SurfaceMesh.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h @@ -1,104 +1,104 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#ifndef __PolyVox_SurfaceMesh_H__ -#define __PolyVox_SurfaceMesh_H__ - -#include "Impl/TypeDef.h" - -#include "PolyVoxCore/Region.h" -#include "PolyVoxCore/VertexTypes.h" //Should probably do away with this on in the future... - -#include -#include -#include -#include -#include -#include - -namespace PolyVox -{ - class LodRecord - { - public: - int beginIndex; - int endIndex; //Let's put it just past the end STL style - }; - - template - class SurfaceMesh - { - public: - SurfaceMesh(); - ~SurfaceMesh(); - - const std::vector& getIndices(void) const; - uint32_t getNoOfIndices(void) const; - uint32_t getNoOfNonUniformTrianges(void) const; - uint32_t getNoOfUniformTrianges(void) const; - uint32_t getNoOfVertices(void) const; - std::vector& getRawVertexData(void); //FIXME - this should be removed - const std::vector& getVertices(void) const; - - void addTriangle(uint32_t index0, uint32_t index1, uint32_t index2); - void addTriangleCubic(uint32_t index0, uint32_t index1, uint32_t index2); - uint32_t addVertex(const VertexType& vertex); - void clear(void); - bool isEmpty(void) const; - - void scaleVertices(float amount); - void translateVertices(const Vector3DFloat& amount); - - //THESE FUNCTIONS TO BE REMOVED IN THE FUTURE. OR AT LEAST MOVED OUT OF THIS CLASS INTO FREE FUNCTIONS. - //THEY ARE CAUSING PROBLEMS WITH THE SWIG BINDINGS. THE FUNCTIONS REGARDING NORMALS MAKE NO SENSE WHEN - //A VERTEX MIGHT NOT HAVE NORMALS. THE EXTRACT SUBSET FUNCTION SHOULD MAYBE BE APPLICATION CODE, AT ANY - //RATE THE STD::SET CAUSES PROBLEMS WITH SWIG. IF YOU UNCOMMENT ANY OF THESE FUNCTIONS, PLEASE POST ON - //THE FORUM SO WE CAN KNOW THE FUNCTIONALITY IS STILL NEEDED IN SOME FORM. - //void sumNearbyNormals(bool bNormaliseResult = true); - //std::shared_ptr< SurfaceMesh > extractSubset(std::set setMaterials); - //void generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices = false); - - int noOfDegenerateTris(void); - void removeDegenerateTris(void); - void removeUnusedVertices(void); - - Region m_Region; - - int32_t m_iTimeStamp; - - int32_t m_iNoOfLod0Tris; - - public: - std::vector m_vecTriangleIndices; - std::vector m_vecVertices; - - std::vector m_vecLodRecords; - }; - - template - std::shared_ptr< SurfaceMesh > extractSubset(SurfaceMesh& inputMesh, std::set setMaterials); -} - -#include "PolyVoxCore/SurfaceMesh.inl" - -#endif /* __SurfaceMesh_H__ */ +/******************************************************************************* +Copyright (c) 2005-2009 David Williams + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*******************************************************************************/ + +#ifndef __PolyVox_Mesh_H__ +#define __PolyVox_Mesh_H__ + +#include "Impl/TypeDef.h" + +#include "PolyVoxCore/Region.h" +#include "PolyVoxCore/VertexTypes.h" //Should probably do away with this on in the future... + +#include +#include +#include +#include +#include +#include + +namespace PolyVox +{ + class LodRecord + { + public: + int beginIndex; + int endIndex; //Let's put it just past the end STL style + }; + + template + class Mesh + { + public: + Mesh(); + ~Mesh(); + + const std::vector& getIndices(void) const; + uint32_t getNoOfIndices(void) const; + uint32_t getNoOfNonUniformTrianges(void) const; + uint32_t getNoOfUniformTrianges(void) const; + uint32_t getNoOfVertices(void) const; + std::vector& getRawVertexData(void); //FIXME - this should be removed + const std::vector& getVertices(void) const; + + void addTriangle(uint32_t index0, uint32_t index1, uint32_t index2); + void addTriangleCubic(uint32_t index0, uint32_t index1, uint32_t index2); + uint32_t addVertex(const VertexType& vertex); + void clear(void); + bool isEmpty(void) const; + + void scaleVertices(float amount); + void translateVertices(const Vector3DFloat& amount); + + //THESE FUNCTIONS TO BE REMOVED IN THE FUTURE. OR AT LEAST MOVED OUT OF THIS CLASS INTO FREE FUNCTIONS. + //THEY ARE CAUSING PROBLEMS WITH THE SWIG BINDINGS. THE FUNCTIONS REGARDING NORMALS MAKE NO SENSE WHEN + //A VERTEX MIGHT NOT HAVE NORMALS. THE EXTRACT SUBSET FUNCTION SHOULD MAYBE BE APPLICATION CODE, AT ANY + //RATE THE STD::SET CAUSES PROBLEMS WITH SWIG. IF YOU UNCOMMENT ANY OF THESE FUNCTIONS, PLEASE POST ON + //THE FORUM SO WE CAN KNOW THE FUNCTIONALITY IS STILL NEEDED IN SOME FORM. + //void sumNearbyNormals(bool bNormaliseResult = true); + //std::shared_ptr< Mesh > extractSubset(std::set setMaterials); + //void generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices = false); + + int noOfDegenerateTris(void); + void removeDegenerateTris(void); + void removeUnusedVertices(void); + + Region m_Region; + + int32_t m_iTimeStamp; + + int32_t m_iNoOfLod0Tris; + + public: + std::vector m_vecTriangleIndices; + std::vector m_vecVertices; + + std::vector m_vecLodRecords; + }; + + template + std::shared_ptr< Mesh > extractSubset(Mesh& inputMesh, std::set setMaterials); +} + +#include "PolyVoxCore/Mesh.inl" + +#endif /* __Mesh_H__ */ diff --git a/library/PolyVoxCore/include/PolyVoxCore/SurfaceMesh.inl b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl similarity index 85% rename from library/PolyVoxCore/include/PolyVoxCore/SurfaceMesh.inl rename to library/PolyVoxCore/include/PolyVoxCore/Mesh.inl index 9b1bf020..44fc5320 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/SurfaceMesh.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl @@ -1,488 +1,488 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -namespace PolyVox -{ - template - SurfaceMesh::SurfaceMesh() - { - m_iTimeStamp = -1; - } - - template - SurfaceMesh::~SurfaceMesh() - { - } - - template - const std::vector& SurfaceMesh::getIndices(void) const - { - return m_vecTriangleIndices; - } - - template - uint32_t SurfaceMesh::getNoOfIndices(void) const - { - return m_vecTriangleIndices.size(); - } - - template - uint32_t SurfaceMesh::getNoOfNonUniformTrianges(void) const - { - uint32_t result = 0; - for(uint32_t i = 0; i < m_vecTriangleIndices.size() - 2; i += 3) - { - if((m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+1]].getMaterial()) - && (m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+2]].getMaterial())) - { - } - else - { - result++; - } - } - return result; - } - - template - uint32_t SurfaceMesh::getNoOfUniformTrianges(void) const - { - uint32_t result = 0; - for(uint32_t i = 0; i < m_vecTriangleIndices.size() - 2; i += 3) - { - if((m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+1]].getMaterial()) - && (m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+2]].getMaterial())) - { - result++; - } - } - return result; - } - - template - uint32_t SurfaceMesh::getNoOfVertices(void) const - { - return m_vecVertices.size(); - } - - template - std::vector& SurfaceMesh::getRawVertexData(void) - { - return m_vecVertices; - } - - template - const std::vector& SurfaceMesh::getVertices(void) const - { - return m_vecVertices; - } - - template - void SurfaceMesh::addTriangle(uint32_t index0, uint32_t index1, uint32_t index2) - { - //Make sure the specified indices correspond to valid vertices. - POLYVOX_ASSERT(index0 < m_vecVertices.size(), "Index points at an invalid vertex."); - POLYVOX_ASSERT(index1 < m_vecVertices.size(), "Index points at an invalid vertex."); - POLYVOX_ASSERT(index2 < m_vecVertices.size(), "Index points at an invalid vertex."); - - m_vecTriangleIndices.push_back(index0); - m_vecTriangleIndices.push_back(index1); - m_vecTriangleIndices.push_back(index2); - } - - template - void SurfaceMesh::addTriangleCubic(uint32_t index0, uint32_t index1, uint32_t index2) - { - //Make sure the specified indices correspond to valid vertices. - POLYVOX_ASSERT(index0 < m_vecVertices.size(), "Index points at an invalid vertex."); - POLYVOX_ASSERT(index1 < m_vecVertices.size(), "Index points at an invalid vertex."); - POLYVOX_ASSERT(index2 < m_vecVertices.size(), "Index points at an invalid vertex."); - - m_vecTriangleIndices.push_back(index0); - m_vecTriangleIndices.push_back(index1); - m_vecTriangleIndices.push_back(index2); - } - - template - uint32_t SurfaceMesh::addVertex(const VertexType& vertex) - { - m_vecVertices.push_back(vertex); - return m_vecVertices.size() - 1; - } - - template - void SurfaceMesh::clear(void) - { - m_vecVertices.clear(); - m_vecTriangleIndices.clear(); - m_vecLodRecords.clear(); - } - - template - bool SurfaceMesh::isEmpty(void) const - { - return (getNoOfVertices() == 0) || (getNoOfIndices() == 0); - } - - //////////////////////////////////////////////////////////////////////////////// - /// This function can help improve the visual appearance of a surface patch by - /// smoothing normals with other nearby normals. It iterates over each triangle - /// in the surface patch and determines the sum of its corners normals. For any - /// given vertex, these sums are in turn summed for any triangles which use the - /// vertex. Usually, the resulting normals should be renormalised afterwards. - /// Note: This function can cause lighting discontinuities accross region boundaries. - //////////////////////////////////////////////////////////////////////////////// - /*template - void SurfaceMesh::sumNearbyNormals(bool bNormaliseResult) - { - if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... - { - return; - } - - std::vector summedNormals(m_vecVertices.size()); - - //Initialise all normals to zero. Should be ok as the vector should store all elements contiguously. - memset(&summedNormals[0], 0, summedNormals.size() * sizeof(Vector3DFloat)); - - for(vector::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();) - { - PositionMaterialNormal& v0 = m_vecVertices[*iterIndex]; - Vector3DFloat& v0New = summedNormals[*iterIndex]; - iterIndex++; - PositionMaterialNormal& v1 = m_vecVertices[*iterIndex]; - Vector3DFloat& v1New = summedNormals[*iterIndex]; - iterIndex++; - PositionMaterialNormal& v2 = m_vecVertices[*iterIndex]; - Vector3DFloat& v2New = summedNormals[*iterIndex]; - iterIndex++; - - Vector3DFloat sumOfNormals = v0.getNormal() + v1.getNormal() + v2.getNormal(); - - v0New += sumOfNormals; - v1New += sumOfNormals; - v2New += sumOfNormals; - } - - for(uint32_t uIndex = 0; uIndex < summedNormals.size(); uIndex++) - { - if(bNormaliseResult) - { - summedNormals[uIndex].normalise(); - } - m_vecVertices[uIndex].setNormal(summedNormals[uIndex]); - } - }*/ - - /*template - void SurfaceMesh::generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices) - { - Vector3DFloat offset = static_cast(m_Region.getLowerCorner()); - - //Initially zero the normals - for(vector::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++) - { - if(m_Region.containsPoint(iterVertex->getPosition() + offset, 0.001)) - { - iterVertex->setNormal(Vector3DFloat(0.0f,0.0f,0.0f)); - } - } - - for(vector::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();) - { - PositionMaterialNormal& v0 = m_vecVertices[*iterIndex]; - iterIndex++; - PositionMaterialNormal& v1 = m_vecVertices[*iterIndex]; - iterIndex++; - PositionMaterialNormal& v2 = m_vecVertices[*iterIndex]; - iterIndex++; - - Vector3DFloat triangleNormal = (v1.getPosition()-v0.getPosition()).cross(v2.getPosition()-v0.getPosition()); - - if(m_Region.containsPoint(v0.getPosition() + offset, 0.001)) - { - v0.setNormal(v0.getNormal() + triangleNormal); - } - if(m_Region.containsPoint(v1.getPosition() + offset, 0.001)) - { - v1.setNormal(v1.getNormal() + triangleNormal); - } - if(m_Region.containsPoint(v2.getPosition() + offset, 0.001)) - { - v2.setNormal(v2.getNormal() + triangleNormal); - } - } - - if(bNormalise) - { - for(vector::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++) - { - Vector3DFloat normal = iterVertex->getNormal(); - normal.normalise(); - iterVertex->setNormal(normal); - } - } - }*/ - - /*template - std::shared_ptr< SurfaceMesh > SurfaceMesh::extractSubset(std::set setMaterials) - { - std::shared_ptr< SurfaceMesh > result(new SurfaceMesh); - - if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... - { - return result; - } - - assert(m_vecLodRecords.size() == 1); - if(m_vecLodRecords.size() != 1) - { - //If we have done progressive LOD then it's too late to split into subsets. - return result; - } - - std::vector indexMap(m_vecVertices.size()); - std::fill(indexMap.begin(), indexMap.end(), -1); - - for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size(); triCt += 3) - { - - PositionMaterialNormal& v0 = m_vecVertices[m_vecTriangleIndices[triCt]]; - PositionMaterialNormal& v1 = m_vecVertices[m_vecTriangleIndices[triCt + 1]]; - PositionMaterialNormal& v2 = m_vecVertices[m_vecTriangleIndices[triCt + 2]]; - - if( - (setMaterials.find(v0.getMaterial()) != setMaterials.end()) || - (setMaterials.find(v1.getMaterial()) != setMaterials.end()) || - (setMaterials.find(v2.getMaterial()) != setMaterials.end())) - { - uint32_t i0; - if(indexMap[m_vecTriangleIndices[triCt]] == -1) - { - indexMap[m_vecTriangleIndices[triCt]] = result->addVertex(v0); - } - i0 = indexMap[m_vecTriangleIndices[triCt]]; - - uint32_t i1; - if(indexMap[m_vecTriangleIndices[triCt+1]] == -1) - { - indexMap[m_vecTriangleIndices[triCt+1]] = result->addVertex(v1); - } - i1 = indexMap[m_vecTriangleIndices[triCt+1]]; - - uint32_t i2; - if(indexMap[m_vecTriangleIndices[triCt+2]] == -1) - { - indexMap[m_vecTriangleIndices[triCt+2]] = result->addVertex(v2); - } - i2 = indexMap[m_vecTriangleIndices[triCt+2]]; - - result->addTriangle(i0,i1,i2); - } - } - - result->m_vecLodRecords.clear(); - LodRecord lodRecord; - lodRecord.beginIndex = 0; - lodRecord.endIndex = result->getNoOfIndices(); - result->m_vecLodRecords.push_back(lodRecord); - - return result; - }*/ - - template - int SurfaceMesh::noOfDegenerateTris(void) - { - int count = 0; - for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size();) - { - int v0 = m_vecTriangleIndices[triCt]; - triCt++; - int v1 = m_vecTriangleIndices[triCt]; - triCt++; - int v2 = m_vecTriangleIndices[triCt]; - triCt++; - - if((v0 == v1) || (v1 == v2) || (v2 == v0)) - { - count++; - } - } - return count; - } - - template - void SurfaceMesh::removeDegenerateTris(void) - { - int noOfNonDegenerate = 0; - int targetCt = 0; - for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size();) - { - int v0 = m_vecTriangleIndices[triCt]; - triCt++; - int v1 = m_vecTriangleIndices[triCt]; - triCt++; - int v2 = m_vecTriangleIndices[triCt]; - triCt++; - - if((v0 != v1) && (v1 != v2) & (v2 != v0)) - { - m_vecTriangleIndices[targetCt] = v0; - targetCt++; - m_vecTriangleIndices[targetCt] = v1; - targetCt++; - m_vecTriangleIndices[targetCt] = v2; - targetCt++; - - noOfNonDegenerate++; - } - } - - m_vecTriangleIndices.resize(noOfNonDegenerate * 3); - } - - template - void SurfaceMesh::removeUnusedVertices(void) - { - std::vector isVertexUsed(m_vecVertices.size()); - std::fill(isVertexUsed.begin(), isVertexUsed.end(), false); - - for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size(); triCt++) - { - int v = m_vecTriangleIndices[triCt]; - isVertexUsed[v] = true; - } - - int noOfUsedVertices = 0; - std::vector newPos(m_vecVertices.size()); - for(uint32_t vertCt = 0; vertCt < m_vecVertices.size(); vertCt++) - { - if(isVertexUsed[vertCt]) - { - m_vecVertices[noOfUsedVertices] = m_vecVertices[vertCt]; - newPos[vertCt] = noOfUsedVertices; - noOfUsedVertices++; - } - } - - m_vecVertices.resize(noOfUsedVertices); - - for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size(); triCt++) - { - m_vecTriangleIndices[triCt] = newPos[m_vecTriangleIndices[triCt]]; - } - } - - //Currently a free function - think where this needs to go. - template - std::shared_ptr< SurfaceMesh > extractSubset(SurfaceMesh& inputMesh, std::set setMaterials) - { - std::shared_ptr< SurfaceMesh > result(new SurfaceMesh); - - result->m_Region = inputMesh.m_Region; - - if(inputMesh.m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... - { - return result; - } - - POLYVOX_ASSERT(inputMesh.m_vecLodRecords.size() == 1, "Number of LOD records must equal one."); - if(inputMesh.m_vecLodRecords.size() != 1) - { - //If we have done progressive LOD then it's too late to split into subsets. - return result; - } - - std::vector indexMap(inputMesh.m_vecVertices.size()); - std::fill(indexMap.begin(), indexMap.end(), -1); - - for(uint32_t triCt = 0; triCt < inputMesh.m_vecTriangleIndices.size(); triCt += 3) - { - - VertexType& v0 = inputMesh.m_vecVertices[inputMesh.m_vecTriangleIndices[triCt]]; - VertexType& v1 = inputMesh.m_vecVertices[inputMesh.m_vecTriangleIndices[triCt + 1]]; - VertexType& v2 = inputMesh.m_vecVertices[inputMesh.m_vecTriangleIndices[triCt + 2]]; - - if( - (setMaterials.find(v0.getMaterial()) != setMaterials.end()) || - (setMaterials.find(v1.getMaterial()) != setMaterials.end()) || - (setMaterials.find(v2.getMaterial()) != setMaterials.end())) - { - uint32_t i0; - if(indexMap[inputMesh.m_vecTriangleIndices[triCt]] == -1) - { - indexMap[inputMesh.m_vecTriangleIndices[triCt]] = result->addVertex(v0); - } - i0 = indexMap[inputMesh.m_vecTriangleIndices[triCt]]; - - uint32_t i1; - if(indexMap[inputMesh.m_vecTriangleIndices[triCt+1]] == -1) - { - indexMap[inputMesh.m_vecTriangleIndices[triCt+1]] = result->addVertex(v1); - } - i1 = indexMap[inputMesh.m_vecTriangleIndices[triCt+1]]; - - uint32_t i2; - if(indexMap[inputMesh.m_vecTriangleIndices[triCt+2]] == -1) - { - indexMap[inputMesh.m_vecTriangleIndices[triCt+2]] = result->addVertex(v2); - } - i2 = indexMap[inputMesh.m_vecTriangleIndices[triCt+2]]; - - result->addTriangle(i0,i1,i2); - } - } - - result->m_vecLodRecords.clear(); - LodRecord lodRecord; - lodRecord.beginIndex = 0; - lodRecord.endIndex = result->getNoOfIndices(); - result->m_vecLodRecords.push_back(lodRecord); - - return result; - } - - template - void SurfaceMesh::scaleVertices(float amount) - { - for(uint32_t ct = 0; ct < m_vecVertices.size(); ct++) - { - //TODO: Should rethink accessors here to provide faster access - Vector3DFloat position = m_vecVertices[ct].getPosition(); - position *= amount; - m_vecVertices[ct].setPosition(position); - } - } - - template - void SurfaceMesh::translateVertices(const Vector3DFloat& amount) - { - for(uint32_t ct = 0; ct < m_vecVertices.size(); ct++) - { - //TODO: Should rethink accessors here to provide faster access - Vector3DFloat position = m_vecVertices[ct].getPosition(); - position += amount; - m_vecVertices[ct].setPosition(position); - } - } -} +/******************************************************************************* +Copyright (c) 2005-2009 David Williams + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*******************************************************************************/ + +namespace PolyVox +{ + template + Mesh::Mesh() + { + m_iTimeStamp = -1; + } + + template + Mesh::~Mesh() + { + } + + template + const std::vector& Mesh::getIndices(void) const + { + return m_vecTriangleIndices; + } + + template + uint32_t Mesh::getNoOfIndices(void) const + { + return m_vecTriangleIndices.size(); + } + + template + uint32_t Mesh::getNoOfNonUniformTrianges(void) const + { + uint32_t result = 0; + for(uint32_t i = 0; i < m_vecTriangleIndices.size() - 2; i += 3) + { + if((m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+1]].getMaterial()) + && (m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+2]].getMaterial())) + { + } + else + { + result++; + } + } + return result; + } + + template + uint32_t Mesh::getNoOfUniformTrianges(void) const + { + uint32_t result = 0; + for(uint32_t i = 0; i < m_vecTriangleIndices.size() - 2; i += 3) + { + if((m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+1]].getMaterial()) + && (m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+2]].getMaterial())) + { + result++; + } + } + return result; + } + + template + uint32_t Mesh::getNoOfVertices(void) const + { + return m_vecVertices.size(); + } + + template + std::vector& Mesh::getRawVertexData(void) + { + return m_vecVertices; + } + + template + const std::vector& Mesh::getVertices(void) const + { + return m_vecVertices; + } + + template + void Mesh::addTriangle(uint32_t index0, uint32_t index1, uint32_t index2) + { + //Make sure the specified indices correspond to valid vertices. + POLYVOX_ASSERT(index0 < m_vecVertices.size(), "Index points at an invalid vertex."); + POLYVOX_ASSERT(index1 < m_vecVertices.size(), "Index points at an invalid vertex."); + POLYVOX_ASSERT(index2 < m_vecVertices.size(), "Index points at an invalid vertex."); + + m_vecTriangleIndices.push_back(index0); + m_vecTriangleIndices.push_back(index1); + m_vecTriangleIndices.push_back(index2); + } + + template + void Mesh::addTriangleCubic(uint32_t index0, uint32_t index1, uint32_t index2) + { + //Make sure the specified indices correspond to valid vertices. + POLYVOX_ASSERT(index0 < m_vecVertices.size(), "Index points at an invalid vertex."); + POLYVOX_ASSERT(index1 < m_vecVertices.size(), "Index points at an invalid vertex."); + POLYVOX_ASSERT(index2 < m_vecVertices.size(), "Index points at an invalid vertex."); + + m_vecTriangleIndices.push_back(index0); + m_vecTriangleIndices.push_back(index1); + m_vecTriangleIndices.push_back(index2); + } + + template + uint32_t Mesh::addVertex(const VertexType& vertex) + { + m_vecVertices.push_back(vertex); + return m_vecVertices.size() - 1; + } + + template + void Mesh::clear(void) + { + m_vecVertices.clear(); + m_vecTriangleIndices.clear(); + m_vecLodRecords.clear(); + } + + template + bool Mesh::isEmpty(void) const + { + return (getNoOfVertices() == 0) || (getNoOfIndices() == 0); + } + + //////////////////////////////////////////////////////////////////////////////// + /// This function can help improve the visual appearance of a surface patch by + /// smoothing normals with other nearby normals. It iterates over each triangle + /// in the surface patch and determines the sum of its corners normals. For any + /// given vertex, these sums are in turn summed for any triangles which use the + /// vertex. Usually, the resulting normals should be renormalised afterwards. + /// Note: This function can cause lighting discontinuities accross region boundaries. + //////////////////////////////////////////////////////////////////////////////// + /*template + void Mesh::sumNearbyNormals(bool bNormaliseResult) + { + if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... + { + return; + } + + std::vector summedNormals(m_vecVertices.size()); + + //Initialise all normals to zero. Should be ok as the vector should store all elements contiguously. + memset(&summedNormals[0], 0, summedNormals.size() * sizeof(Vector3DFloat)); + + for(vector::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();) + { + PositionMaterialNormal& v0 = m_vecVertices[*iterIndex]; + Vector3DFloat& v0New = summedNormals[*iterIndex]; + iterIndex++; + PositionMaterialNormal& v1 = m_vecVertices[*iterIndex]; + Vector3DFloat& v1New = summedNormals[*iterIndex]; + iterIndex++; + PositionMaterialNormal& v2 = m_vecVertices[*iterIndex]; + Vector3DFloat& v2New = summedNormals[*iterIndex]; + iterIndex++; + + Vector3DFloat sumOfNormals = v0.getNormal() + v1.getNormal() + v2.getNormal(); + + v0New += sumOfNormals; + v1New += sumOfNormals; + v2New += sumOfNormals; + } + + for(uint32_t uIndex = 0; uIndex < summedNormals.size(); uIndex++) + { + if(bNormaliseResult) + { + summedNormals[uIndex].normalise(); + } + m_vecVertices[uIndex].setNormal(summedNormals[uIndex]); + } + }*/ + + /*template + void Mesh::generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices) + { + Vector3DFloat offset = static_cast(m_Region.getLowerCorner()); + + //Initially zero the normals + for(vector::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++) + { + if(m_Region.containsPoint(iterVertex->getPosition() + offset, 0.001)) + { + iterVertex->setNormal(Vector3DFloat(0.0f,0.0f,0.0f)); + } + } + + for(vector::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();) + { + PositionMaterialNormal& v0 = m_vecVertices[*iterIndex]; + iterIndex++; + PositionMaterialNormal& v1 = m_vecVertices[*iterIndex]; + iterIndex++; + PositionMaterialNormal& v2 = m_vecVertices[*iterIndex]; + iterIndex++; + + Vector3DFloat triangleNormal = (v1.getPosition()-v0.getPosition()).cross(v2.getPosition()-v0.getPosition()); + + if(m_Region.containsPoint(v0.getPosition() + offset, 0.001)) + { + v0.setNormal(v0.getNormal() + triangleNormal); + } + if(m_Region.containsPoint(v1.getPosition() + offset, 0.001)) + { + v1.setNormal(v1.getNormal() + triangleNormal); + } + if(m_Region.containsPoint(v2.getPosition() + offset, 0.001)) + { + v2.setNormal(v2.getNormal() + triangleNormal); + } + } + + if(bNormalise) + { + for(vector::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++) + { + Vector3DFloat normal = iterVertex->getNormal(); + normal.normalise(); + iterVertex->setNormal(normal); + } + } + }*/ + + /*template + std::shared_ptr< Mesh > Mesh::extractSubset(std::set setMaterials) + { + std::shared_ptr< Mesh > result(new Mesh); + + if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... + { + return result; + } + + assert(m_vecLodRecords.size() == 1); + if(m_vecLodRecords.size() != 1) + { + //If we have done progressive LOD then it's too late to split into subsets. + return result; + } + + std::vector indexMap(m_vecVertices.size()); + std::fill(indexMap.begin(), indexMap.end(), -1); + + for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size(); triCt += 3) + { + + PositionMaterialNormal& v0 = m_vecVertices[m_vecTriangleIndices[triCt]]; + PositionMaterialNormal& v1 = m_vecVertices[m_vecTriangleIndices[triCt + 1]]; + PositionMaterialNormal& v2 = m_vecVertices[m_vecTriangleIndices[triCt + 2]]; + + if( + (setMaterials.find(v0.getMaterial()) != setMaterials.end()) || + (setMaterials.find(v1.getMaterial()) != setMaterials.end()) || + (setMaterials.find(v2.getMaterial()) != setMaterials.end())) + { + uint32_t i0; + if(indexMap[m_vecTriangleIndices[triCt]] == -1) + { + indexMap[m_vecTriangleIndices[triCt]] = result->addVertex(v0); + } + i0 = indexMap[m_vecTriangleIndices[triCt]]; + + uint32_t i1; + if(indexMap[m_vecTriangleIndices[triCt+1]] == -1) + { + indexMap[m_vecTriangleIndices[triCt+1]] = result->addVertex(v1); + } + i1 = indexMap[m_vecTriangleIndices[triCt+1]]; + + uint32_t i2; + if(indexMap[m_vecTriangleIndices[triCt+2]] == -1) + { + indexMap[m_vecTriangleIndices[triCt+2]] = result->addVertex(v2); + } + i2 = indexMap[m_vecTriangleIndices[triCt+2]]; + + result->addTriangle(i0,i1,i2); + } + } + + result->m_vecLodRecords.clear(); + LodRecord lodRecord; + lodRecord.beginIndex = 0; + lodRecord.endIndex = result->getNoOfIndices(); + result->m_vecLodRecords.push_back(lodRecord); + + return result; + }*/ + + template + int Mesh::noOfDegenerateTris(void) + { + int count = 0; + for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size();) + { + int v0 = m_vecTriangleIndices[triCt]; + triCt++; + int v1 = m_vecTriangleIndices[triCt]; + triCt++; + int v2 = m_vecTriangleIndices[triCt]; + triCt++; + + if((v0 == v1) || (v1 == v2) || (v2 == v0)) + { + count++; + } + } + return count; + } + + template + void Mesh::removeDegenerateTris(void) + { + int noOfNonDegenerate = 0; + int targetCt = 0; + for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size();) + { + int v0 = m_vecTriangleIndices[triCt]; + triCt++; + int v1 = m_vecTriangleIndices[triCt]; + triCt++; + int v2 = m_vecTriangleIndices[triCt]; + triCt++; + + if((v0 != v1) && (v1 != v2) & (v2 != v0)) + { + m_vecTriangleIndices[targetCt] = v0; + targetCt++; + m_vecTriangleIndices[targetCt] = v1; + targetCt++; + m_vecTriangleIndices[targetCt] = v2; + targetCt++; + + noOfNonDegenerate++; + } + } + + m_vecTriangleIndices.resize(noOfNonDegenerate * 3); + } + + template + void Mesh::removeUnusedVertices(void) + { + std::vector isVertexUsed(m_vecVertices.size()); + std::fill(isVertexUsed.begin(), isVertexUsed.end(), false); + + for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size(); triCt++) + { + int v = m_vecTriangleIndices[triCt]; + isVertexUsed[v] = true; + } + + int noOfUsedVertices = 0; + std::vector newPos(m_vecVertices.size()); + for(uint32_t vertCt = 0; vertCt < m_vecVertices.size(); vertCt++) + { + if(isVertexUsed[vertCt]) + { + m_vecVertices[noOfUsedVertices] = m_vecVertices[vertCt]; + newPos[vertCt] = noOfUsedVertices; + noOfUsedVertices++; + } + } + + m_vecVertices.resize(noOfUsedVertices); + + for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size(); triCt++) + { + m_vecTriangleIndices[triCt] = newPos[m_vecTriangleIndices[triCt]]; + } + } + + //Currently a free function - think where this needs to go. + template + std::shared_ptr< Mesh > extractSubset(Mesh& inputMesh, std::set setMaterials) + { + std::shared_ptr< Mesh > result(new Mesh); + + result->m_Region = inputMesh.m_Region; + + if(inputMesh.m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... + { + return result; + } + + POLYVOX_ASSERT(inputMesh.m_vecLodRecords.size() == 1, "Number of LOD records must equal one."); + if(inputMesh.m_vecLodRecords.size() != 1) + { + //If we have done progressive LOD then it's too late to split into subsets. + return result; + } + + std::vector indexMap(inputMesh.m_vecVertices.size()); + std::fill(indexMap.begin(), indexMap.end(), -1); + + for(uint32_t triCt = 0; triCt < inputMesh.m_vecTriangleIndices.size(); triCt += 3) + { + + VertexType& v0 = inputMesh.m_vecVertices[inputMesh.m_vecTriangleIndices[triCt]]; + VertexType& v1 = inputMesh.m_vecVertices[inputMesh.m_vecTriangleIndices[triCt + 1]]; + VertexType& v2 = inputMesh.m_vecVertices[inputMesh.m_vecTriangleIndices[triCt + 2]]; + + if( + (setMaterials.find(v0.getMaterial()) != setMaterials.end()) || + (setMaterials.find(v1.getMaterial()) != setMaterials.end()) || + (setMaterials.find(v2.getMaterial()) != setMaterials.end())) + { + uint32_t i0; + if(indexMap[inputMesh.m_vecTriangleIndices[triCt]] == -1) + { + indexMap[inputMesh.m_vecTriangleIndices[triCt]] = result->addVertex(v0); + } + i0 = indexMap[inputMesh.m_vecTriangleIndices[triCt]]; + + uint32_t i1; + if(indexMap[inputMesh.m_vecTriangleIndices[triCt+1]] == -1) + { + indexMap[inputMesh.m_vecTriangleIndices[triCt+1]] = result->addVertex(v1); + } + i1 = indexMap[inputMesh.m_vecTriangleIndices[triCt+1]]; + + uint32_t i2; + if(indexMap[inputMesh.m_vecTriangleIndices[triCt+2]] == -1) + { + indexMap[inputMesh.m_vecTriangleIndices[triCt+2]] = result->addVertex(v2); + } + i2 = indexMap[inputMesh.m_vecTriangleIndices[triCt+2]]; + + result->addTriangle(i0,i1,i2); + } + } + + result->m_vecLodRecords.clear(); + LodRecord lodRecord; + lodRecord.beginIndex = 0; + lodRecord.endIndex = result->getNoOfIndices(); + result->m_vecLodRecords.push_back(lodRecord); + + return result; + } + + template + void Mesh::scaleVertices(float amount) + { + for(uint32_t ct = 0; ct < m_vecVertices.size(); ct++) + { + //TODO: Should rethink accessors here to provide faster access + Vector3DFloat position = m_vecVertices[ct].getPosition(); + position *= amount; + m_vecVertices[ct].setPosition(position); + } + } + + template + void Mesh::translateVertices(const Vector3DFloat& amount) + { + for(uint32_t ct = 0; ct < m_vecVertices.size(); ct++) + { + //TODO: Should rethink accessors here to provide faster access + Vector3DFloat position = m_vecVertices[ct].getPosition(); + position += amount; + m_vecVertices[ct].setPosition(position); + } + } +} diff --git a/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h b/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h index 0d68b3e9..3d9ef742 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h +++ b/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h @@ -160,9 +160,9 @@ namespace PolyVox template class MarchingCubesSurfaceExtractor; //////////////////////////////////////////////////////////////////////////////// - // SurfaceMesh + // Mesh //////////////////////////////////////////////////////////////////////////////// - template class SurfaceMesh; + template class Mesh; //////////////////////////////////////////////////////////////////////////////// // Vector diff --git a/tests/TestCubicSurfaceExtractor.cpp b/tests/TestCubicSurfaceExtractor.cpp index 7c74dee1..8476b7f8 100644 --- a/tests/TestCubicSurfaceExtractor.cpp +++ b/tests/TestCubicSurfaceExtractor.cpp @@ -130,7 +130,7 @@ void TestCubicSurfaceExtractor::testExecute() const static uint32_t uIndexToCheck = 2000; const static uint32_t uExpectedIndex = 1334; - SurfaceMesh mesh;*/ + Mesh mesh;*/ /*testForType(mesh); QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices); diff --git a/tests/TestSurfaceExtractor.cpp b/tests/TestSurfaceExtractor.cpp index c11541a5..2189b9c2 100644 --- a/tests/TestSurfaceExtractor.cpp +++ b/tests/TestSurfaceExtractor.cpp @@ -102,7 +102,7 @@ void writeMaterialValueToVoxel(int valueToWrite, MaterialDensityPair88& voxel) // Runs the surface extractor for a given type. template -SurfaceMesh > testForType(void) //I think we could avoid specifying this return type by using auto/decltype? +Mesh > testForType(void) //I think we could avoid specifying this return type by using auto/decltype? { const int32_t uVolumeSideLength = 32; @@ -133,7 +133,7 @@ SurfaceMesh > testForType(void) //I think we coul return result; } -void testCustomController(SurfaceMesh >& result) +void testCustomController(Mesh >& result) { const int32_t uVolumeSideLength = 32; @@ -165,7 +165,7 @@ void TestSurfaceExtractor::testExecute() const static float fExpectedMaterial = 42.0f; const static float fNoMaterial = 1.0f; - SurfaceMesh > mesh; + Mesh > mesh; //Run the test for various voxel types. QBENCHMARK { mesh = testForType(); From e8313a683bd748ab36b2aff42ebdd16d28bd5320 Mon Sep 17 00:00:00 2001 From: David Williams Date: Fri, 23 May 2014 15:32:28 +0200 Subject: [PATCH 09/72] Compile fixes for VS2012 --- examples/Basic/OpenGLWidget.cpp | 56 ++++++++++++++++----------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index 7fb5f2cb..824a6ca4 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -86,44 +86,44 @@ void OpenGLWidget::initializeGL() glDepthFunc(GL_LEQUAL); glDepthRange(0.0, 1.0); - if (!shader.addShaderFromSourceCode(QGLShader::Vertex, R"( - #version 140 + if (!shader.addShaderFromSourceCode(QGLShader::Vertex, + "#version 140\n" - in vec4 position; //This will be the position of the vertex in model-space + "in vec4 position; //This will be the position of the vertex in model-space\n" - uniform mat4 cameraToClipMatrix; - uniform mat4 worldToCameraMatrix; - uniform mat4 modelToWorldMatrix; + "uniform mat4 cameraToClipMatrix;\n" + "uniform mat4 worldToCameraMatrix;\n" + "uniform mat4 modelToWorldMatrix;\n" - out vec4 worldPosition; //This is being passed to the fragment shader to calculate the normals + "out vec4 worldPosition; //This is being passed to the fragment shader to calculate the normals\n" - void main() - { - worldPosition = modelToWorldMatrix * position; - vec4 cameraPosition = worldToCameraMatrix * worldPosition; - gl_Position = cameraToClipMatrix * cameraPosition; - } - )")) + "void main()\n" + "{\n" + " worldPosition = modelToWorldMatrix * position;\n" + " vec4 cameraPosition = worldToCameraMatrix * worldPosition;\n" + " gl_Position = cameraToClipMatrix * cameraPosition;\n" + "}\n" + )) { std::cerr << shader.log().toStdString() << std::endl; exit(EXIT_FAILURE); } - if (!shader.addShaderFromSourceCode(QGLShader::Fragment, R"( - #version 130 + if (!shader.addShaderFromSourceCode(QGLShader::Fragment, + "#version 130\n" - in vec4 worldPosition; //Passed in from the vertex shader + "in vec4 worldPosition; //Passed in from the vertex shader\n" - out vec4 outputColor; + "out vec4 outputColor;\n" - void main() - { - vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz))); + "void main()\n" + "{\n" + " vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz)));\n" - float color = clamp(abs(dot(normalize(normal.xyz), vec3(0.9,0.1,0.5))), 0, 1); - outputColor = vec4(1.0, 0.5, color, 1.0); - } - )")) + " float color = clamp(abs(dot(normalize(normal.xyz), vec3(0.9,0.1,0.5))), 0, 1);\n" + " outputColor = vec4(1.0, 0.5, color, 1.0);\n" + "}" + )) { std::cerr << shader.log().toStdString() << std::endl; exit(EXIT_FAILURE); @@ -149,7 +149,7 @@ void OpenGLWidget::resizeGL(int w, int h) float zNear = 1.0; float zFar = 1000.0; - QMatrix4x4 cameraToClipMatrix{}; + QMatrix4x4 cameraToClipMatrix; cameraToClipMatrix.frustum(-aspectRatio, aspectRatio, -1, 1, zNear, zFar); shader.bind(); @@ -162,7 +162,7 @@ void OpenGLWidget::paintGL() //Clear the screen glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - QMatrix4x4 modelToWorldMatrix{}; + QMatrix4x4 modelToWorldMatrix; //modelToWorldMatrix.rotate(m_xRotation, 0, 1, 0); //rotate around y-axis //modelToWorldMatrix.rotate(m_yRotation, 1, 0, 0); //rotate around x-axis //modelToWorldMatrix.translate(-32, -32, -32); //centre the model on the origin @@ -220,7 +220,7 @@ void OpenGLWidget::setupWorldToCameraMatrix() QVector3D centerPoint = (lowerCorner + upperCorner) * 0.5; float fDiagonalLength = (upperCorner - lowerCorner).length(); - QMatrix4x4 worldToCameraMatrix{}; + QMatrix4x4 worldToCameraMatrix; worldToCameraMatrix.translate(0, 0, -fDiagonalLength / 2.0f); //Move the camera back by the required amount worldToCameraMatrix.rotate(m_xRotation, 0, 1, 0); //rotate around y-axis worldToCameraMatrix.rotate(m_yRotation, 1, 0, 0); //rotate around x-axis From 79acf814dbd25f1be87223665e4fcbbef114ab95 Mon Sep 17 00:00:00 2001 From: David Williams Date: Fri, 23 May 2014 16:11:53 +0200 Subject: [PATCH 10/72] Revert "Compile fixes for VS2012" This reverts commit e8313a683bd748ab36b2aff42ebdd16d28bd5320. --- examples/Basic/OpenGLWidget.cpp | 56 ++++++++++++++++----------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index 824a6ca4..7fb5f2cb 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -86,44 +86,44 @@ void OpenGLWidget::initializeGL() glDepthFunc(GL_LEQUAL); glDepthRange(0.0, 1.0); - if (!shader.addShaderFromSourceCode(QGLShader::Vertex, - "#version 140\n" + if (!shader.addShaderFromSourceCode(QGLShader::Vertex, R"( + #version 140 - "in vec4 position; //This will be the position of the vertex in model-space\n" + in vec4 position; //This will be the position of the vertex in model-space - "uniform mat4 cameraToClipMatrix;\n" - "uniform mat4 worldToCameraMatrix;\n" - "uniform mat4 modelToWorldMatrix;\n" + uniform mat4 cameraToClipMatrix; + uniform mat4 worldToCameraMatrix; + uniform mat4 modelToWorldMatrix; - "out vec4 worldPosition; //This is being passed to the fragment shader to calculate the normals\n" + out vec4 worldPosition; //This is being passed to the fragment shader to calculate the normals - "void main()\n" - "{\n" - " worldPosition = modelToWorldMatrix * position;\n" - " vec4 cameraPosition = worldToCameraMatrix * worldPosition;\n" - " gl_Position = cameraToClipMatrix * cameraPosition;\n" - "}\n" - )) + void main() + { + worldPosition = modelToWorldMatrix * position; + vec4 cameraPosition = worldToCameraMatrix * worldPosition; + gl_Position = cameraToClipMatrix * cameraPosition; + } + )")) { std::cerr << shader.log().toStdString() << std::endl; exit(EXIT_FAILURE); } - if (!shader.addShaderFromSourceCode(QGLShader::Fragment, - "#version 130\n" + if (!shader.addShaderFromSourceCode(QGLShader::Fragment, R"( + #version 130 - "in vec4 worldPosition; //Passed in from the vertex shader\n" + in vec4 worldPosition; //Passed in from the vertex shader - "out vec4 outputColor;\n" + out vec4 outputColor; - "void main()\n" - "{\n" - " vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz)));\n" + void main() + { + vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz))); - " float color = clamp(abs(dot(normalize(normal.xyz), vec3(0.9,0.1,0.5))), 0, 1);\n" - " outputColor = vec4(1.0, 0.5, color, 1.0);\n" - "}" - )) + float color = clamp(abs(dot(normalize(normal.xyz), vec3(0.9,0.1,0.5))), 0, 1); + outputColor = vec4(1.0, 0.5, color, 1.0); + } + )")) { std::cerr << shader.log().toStdString() << std::endl; exit(EXIT_FAILURE); @@ -149,7 +149,7 @@ void OpenGLWidget::resizeGL(int w, int h) float zNear = 1.0; float zFar = 1000.0; - QMatrix4x4 cameraToClipMatrix; + QMatrix4x4 cameraToClipMatrix{}; cameraToClipMatrix.frustum(-aspectRatio, aspectRatio, -1, 1, zNear, zFar); shader.bind(); @@ -162,7 +162,7 @@ void OpenGLWidget::paintGL() //Clear the screen glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - QMatrix4x4 modelToWorldMatrix; + QMatrix4x4 modelToWorldMatrix{}; //modelToWorldMatrix.rotate(m_xRotation, 0, 1, 0); //rotate around y-axis //modelToWorldMatrix.rotate(m_yRotation, 1, 0, 0); //rotate around x-axis //modelToWorldMatrix.translate(-32, -32, -32); //centre the model on the origin @@ -220,7 +220,7 @@ void OpenGLWidget::setupWorldToCameraMatrix() QVector3D centerPoint = (lowerCorner + upperCorner) * 0.5; float fDiagonalLength = (upperCorner - lowerCorner).length(); - QMatrix4x4 worldToCameraMatrix; + QMatrix4x4 worldToCameraMatrix{}; worldToCameraMatrix.translate(0, 0, -fDiagonalLength / 2.0f); //Move the camera back by the required amount worldToCameraMatrix.rotate(m_xRotation, 0, 1, 0); //rotate around y-axis worldToCameraMatrix.rotate(m_yRotation, 1, 0, 0); //rotate around x-axis From 37bdf8e3ac2a4dc5f72298b605859e2d7ff61741 Mon Sep 17 00:00:00 2001 From: David Williams Date: Fri, 23 May 2014 16:26:56 +0200 Subject: [PATCH 11/72] Templatised code for example mesh conversion. --- examples/Basic/OpenGLWidget.cpp | 23 +++++++++++++++++------ examples/Basic/OpenGLWidget.h | 4 ++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index 7fb5f2cb..badf1cba 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -16,6 +16,17 @@ OpenGLWidget::OpenGLWidget(QWidget *parent) } void OpenGLWidget::setMeshToRender(const PolyVox::Mesh >& surfaceMesh) +{ + setMeshToRenderImpl(surfaceMesh); +} + +void OpenGLWidget::setMeshToRender(const PolyVox::Mesh >& surfaceMesh) +{ + setMeshToRenderImpl(surfaceMesh); +} + +template +void OpenGLWidget::setMeshToRenderImpl(const MeshType& surfaceMesh) { //Convienient access to the vertices and indices const auto& vecIndices = surfaceMesh.getIndices(); @@ -24,27 +35,27 @@ void OpenGLWidget::setMeshToRender(const PolyVox::Mesh >& s // This struct holds the OpenGL properties (buffer handles, etc) which will be used // to render our mesh. We copy the data from the PolyVox mesh into this structure. OpenGLMeshData meshData; - + //Create the VAO for the mesh glGenVertexArrays(1, &(meshData.vertexArrayObject)); glBindVertexArray(meshData.vertexArrayObject); - + //The GL_ARRAY_BUFFER will contain the list of vertex positions glGenBuffers(1, &(meshData.vertexBuffer)); glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer); glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(CubicVertex), vecVertices.data(), GL_STATIC_DRAW); - + //and GL_ELEMENT_ARRAY_BUFFER will contain the indices glGenBuffers(1, &(meshData.indexBuffer)); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshData.indexBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), vecIndices.data(), GL_STATIC_DRAW); - + //We need to tell OpenGL how to understand the format of the vertex data glEnableVertexAttribArray(0); //We're talking about shader attribute '0' glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(CubicVertex), 0); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) - + glBindVertexArray(0); - + meshData.noOfIndices = vecIndices.size(); //Save this for the call to glDrawElements later mMeshData.push_back(meshData); diff --git a/examples/Basic/OpenGLWidget.h b/examples/Basic/OpenGLWidget.h index 266ee0e6..8e6f048c 100644 --- a/examples/Basic/OpenGLWidget.h +++ b/examples/Basic/OpenGLWidget.h @@ -51,11 +51,15 @@ public: // Convert a SurfaceMesh to OpenGL index/vertex buffers void setMeshToRender(const PolyVox::Mesh >& surfaceMesh); + void setMeshToRender(const PolyVox::Mesh >& surfaceMesh); // The viewable region can be adjusted so that this example framework can be use for different volume sizes. void setViewableRegion(PolyVox::Region viewableRegion); protected: + template + void setMeshToRenderImpl(const MeshType& surfaceMesh); + // Qt OpenGL functions void initializeGL(); void resizeGL(int w, int h); From 9f5b2e165926ebeadffb799cfb62dfaad887af41 Mon Sep 17 00:00:00 2001 From: David Williams Date: Fri, 23 May 2014 17:02:46 +0200 Subject: [PATCH 12/72] Better templatization of addMesh. --- examples/Basic/OpenGLWidget.cpp | 46 --------------------------------- examples/Basic/OpenGLWidget.h | 43 +++++++++++++++++++++++++++--- examples/Basic/main.cpp | 4 +-- 3 files changed, 41 insertions(+), 52 deletions(-) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index badf1cba..edd75b55 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -15,52 +15,6 @@ OpenGLWidget::OpenGLWidget(QWidget *parent) { } -void OpenGLWidget::setMeshToRender(const PolyVox::Mesh >& surfaceMesh) -{ - setMeshToRenderImpl(surfaceMesh); -} - -void OpenGLWidget::setMeshToRender(const PolyVox::Mesh >& surfaceMesh) -{ - setMeshToRenderImpl(surfaceMesh); -} - -template -void OpenGLWidget::setMeshToRenderImpl(const MeshType& surfaceMesh) -{ - //Convienient access to the vertices and indices - const auto& vecIndices = surfaceMesh.getIndices(); - const auto& vecVertices = surfaceMesh.getVertices(); - - // This struct holds the OpenGL properties (buffer handles, etc) which will be used - // to render our mesh. We copy the data from the PolyVox mesh into this structure. - OpenGLMeshData meshData; - - //Create the VAO for the mesh - glGenVertexArrays(1, &(meshData.vertexArrayObject)); - glBindVertexArray(meshData.vertexArrayObject); - - //The GL_ARRAY_BUFFER will contain the list of vertex positions - glGenBuffers(1, &(meshData.vertexBuffer)); - glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(CubicVertex), vecVertices.data(), GL_STATIC_DRAW); - - //and GL_ELEMENT_ARRAY_BUFFER will contain the indices - glGenBuffers(1, &(meshData.indexBuffer)); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshData.indexBuffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), vecIndices.data(), GL_STATIC_DRAW); - - //We need to tell OpenGL how to understand the format of the vertex data - glEnableVertexAttribArray(0); //We're talking about shader attribute '0' - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(CubicVertex), 0); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) - - glBindVertexArray(0); - - meshData.noOfIndices = vecIndices.size(); //Save this for the call to glDrawElements later - - mMeshData.push_back(meshData); -} - void OpenGLWidget::setViewableRegion(Region viewableRegion) { m_viewableRegion = viewableRegion; diff --git a/examples/Basic/OpenGLWidget.h b/examples/Basic/OpenGLWidget.h index 8e6f048c..7ac39928 100644 --- a/examples/Basic/OpenGLWidget.h +++ b/examples/Basic/OpenGLWidget.h @@ -50,15 +50,14 @@ public: void mousePressEvent(QMouseEvent* event); // Convert a SurfaceMesh to OpenGL index/vertex buffers - void setMeshToRender(const PolyVox::Mesh >& surfaceMesh); - void setMeshToRender(const PolyVox::Mesh >& surfaceMesh); + template + void addMesh(const MeshType& surfaceMesh); // The viewable region can be adjusted so that this example framework can be use for different volume sizes. void setViewableRegion(PolyVox::Region viewableRegion); protected: - template - void setMeshToRenderImpl(const MeshType& surfaceMesh); + // Qt OpenGL functions void initializeGL(); @@ -84,4 +83,40 @@ private: int m_yRotation; }; +template +void OpenGLWidget::addMesh(const MeshType& surfaceMesh) +{ + //Convienient access to the vertices and indices + const auto& vecIndices = surfaceMesh.getIndices(); + const auto& vecVertices = surfaceMesh.getVertices(); + + // This struct holds the OpenGL properties (buffer handles, etc) which will be used + // to render our mesh. We copy the data from the PolyVox mesh into this structure. + OpenGLMeshData meshData; + + //Create the VAO for the mesh + glGenVertexArrays(1, &(meshData.vertexArrayObject)); + glBindVertexArray(meshData.vertexArrayObject); + + //The GL_ARRAY_BUFFER will contain the list of vertex positions + glGenBuffers(1, &(meshData.vertexBuffer)); + glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(CubicVertex), vecVertices.data(), GL_STATIC_DRAW); + + //and GL_ELEMENT_ARRAY_BUFFER will contain the indices + glGenBuffers(1, &(meshData.indexBuffer)); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshData.indexBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), vecIndices.data(), GL_STATIC_DRAW); + + //We need to tell OpenGL how to understand the format of the vertex data + glEnableVertexAttribArray(0); //We're talking about shader attribute '0' + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(CubicVertex), 0); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + + glBindVertexArray(0); + + meshData.noOfIndices = vecIndices.size(); //Save this for the call to glDrawElements later + + mMeshData.push_back(meshData); +} + #endif //__BasicExample_OpenGLWidget_H__ diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index c3a53f59..b422f1c4 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -85,9 +85,9 @@ int main(int argc, char *argv[]) //auto mesh2 = extractCubicMesh(&volData, PolyVox::Region(Vector3DInt32(32, 32, 32), Vector3DInt32(63, 63, 63))); //Pass the surface to the OpenGL window - openGLWidget.setMeshToRender(mesh); + openGLWidget.addMesh(mesh); openGLWidget.setViewableRegion(volData.getEnclosingRegion()); - //openGLWidget.setMeshToRender(mesh2); + //openGLWidget.addMesh(mesh2); //Run the message pump. return app.exec(); From 4f7e1e68460a60cd14cc6523e77ed5ba8095706f Mon Sep 17 00:00:00 2001 From: David Williams Date: Fri, 23 May 2014 22:03:57 +0200 Subject: [PATCH 13/72] Each mesh now has it's own transform matrix applied, so that our example framework can support breaking a volume into regions. --- examples/Basic/OpenGLWidget.cpp | 11 ++--- examples/Basic/OpenGLWidget.h | 80 ++++++++++++++++----------------- examples/Basic/main.cpp | 8 ++-- 3 files changed, 48 insertions(+), 51 deletions(-) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index edd75b55..78dbff0c 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -127,17 +127,14 @@ void OpenGLWidget::paintGL() //Clear the screen glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - QMatrix4x4 modelToWorldMatrix{}; - //modelToWorldMatrix.rotate(m_xRotation, 0, 1, 0); //rotate around y-axis - //modelToWorldMatrix.rotate(m_yRotation, 1, 0, 0); //rotate around x-axis - //modelToWorldMatrix.translate(-32, -32, -32); //centre the model on the origin - shader.bind(); - shader.setUniformValue("modelToWorldMatrix", modelToWorldMatrix); //Update to the latest camera matrix - for (OpenGLMeshData meshData : mMeshData) { + QMatrix4x4 modelToWorldMatrix{}; + modelToWorldMatrix.translate(meshData.translation.getX(), meshData.translation.getY(), meshData.translation.getZ()); // Centre the model on the origin + shader.setUniformValue("modelToWorldMatrix", modelToWorldMatrix); // Update to the latest camera matrix + glBindVertexArray(meshData.vertexArrayObject); glDrawElements(GL_TRIANGLES, meshData.noOfIndices, GL_UNSIGNED_INT, 0); diff --git a/examples/Basic/OpenGLWidget.h b/examples/Basic/OpenGLWidget.h index 7ac39928..2d9cc6d6 100644 --- a/examples/Basic/OpenGLWidget.h +++ b/examples/Basic/OpenGLWidget.h @@ -37,6 +37,7 @@ struct OpenGLMeshData GLuint indexBuffer; GLuint vertexBuffer; GLuint vertexArrayObject; + PolyVox::Vector3DInt32 translation; }; class OpenGLWidget : public QGLWidget @@ -49,13 +50,48 @@ public: void mouseMoveEvent(QMouseEvent* event); void mousePressEvent(QMouseEvent* event); - // Convert a SurfaceMesh to OpenGL index/vertex buffers - template - void addMesh(const MeshType& surfaceMesh); - // The viewable region can be adjusted so that this example framework can be use for different volume sizes. void setViewableRegion(PolyVox::Region viewableRegion); + // Convert a SurfaceMesh to OpenGL index/vertex buffers. Inlined because it's templatised. + template + void addMesh(const MeshType& surfaceMesh) + { + //Convienient access to the vertices and indices + const auto& vecIndices = surfaceMesh.getIndices(); + const auto& vecVertices = surfaceMesh.getVertices(); + + // This struct holds the OpenGL properties (buffer handles, etc) which will be used + // to render our mesh. We copy the data from the PolyVox mesh into this structure. + OpenGLMeshData meshData; + + //Create the VAO for the mesh + glGenVertexArrays(1, &(meshData.vertexArrayObject)); + glBindVertexArray(meshData.vertexArrayObject); + + //The GL_ARRAY_BUFFER will contain the list of vertex positions + glGenBuffers(1, &(meshData.vertexBuffer)); + glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(CubicVertex), vecVertices.data(), GL_STATIC_DRAW); + + //and GL_ELEMENT_ARRAY_BUFFER will contain the indices + glGenBuffers(1, &(meshData.indexBuffer)); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshData.indexBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), vecIndices.data(), GL_STATIC_DRAW); + + //We need to tell OpenGL how to understand the format of the vertex data + glEnableVertexAttribArray(0); //We're talking about shader attribute '0' + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(CubicVertex), 0); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + + glBindVertexArray(0); + + meshData.noOfIndices = vecIndices.size(); //Save this for the call to glDrawElements later + + meshData.translation = surfaceMesh.m_Region.getLowerCorner(); + + mMeshData.push_back(meshData); + } + protected: @@ -83,40 +119,4 @@ private: int m_yRotation; }; -template -void OpenGLWidget::addMesh(const MeshType& surfaceMesh) -{ - //Convienient access to the vertices and indices - const auto& vecIndices = surfaceMesh.getIndices(); - const auto& vecVertices = surfaceMesh.getVertices(); - - // This struct holds the OpenGL properties (buffer handles, etc) which will be used - // to render our mesh. We copy the data from the PolyVox mesh into this structure. - OpenGLMeshData meshData; - - //Create the VAO for the mesh - glGenVertexArrays(1, &(meshData.vertexArrayObject)); - glBindVertexArray(meshData.vertexArrayObject); - - //The GL_ARRAY_BUFFER will contain the list of vertex positions - glGenBuffers(1, &(meshData.vertexBuffer)); - glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(CubicVertex), vecVertices.data(), GL_STATIC_DRAW); - - //and GL_ELEMENT_ARRAY_BUFFER will contain the indices - glGenBuffers(1, &(meshData.indexBuffer)); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshData.indexBuffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), vecIndices.data(), GL_STATIC_DRAW); - - //We need to tell OpenGL how to understand the format of the vertex data - glEnableVertexAttribArray(0); //We're talking about shader attribute '0' - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(CubicVertex), 0); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) - - glBindVertexArray(0); - - meshData.noOfIndices = vecIndices.size(); //Save this for the call to glDrawElements later - - mMeshData.push_back(meshData); -} - #endif //__BasicExample_OpenGLWidget_H__ diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index b422f1c4..ee908dd7 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -78,16 +78,16 @@ int main(int argc, char *argv[]) createSphereInVolume(volData, 30); // Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see. - auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion()); + //auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion()); //auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion()); - //auto mesh = extractCubicMesh(&volData, PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(31, 31, 31))); - //auto mesh2 = extractCubicMesh(&volData, PolyVox::Region(Vector3DInt32(32, 32, 32), Vector3DInt32(63, 63, 63))); + auto mesh = extractCubicMesh(&volData, PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(31, 31, 31))); + auto mesh2 = extractCubicMesh(&volData, PolyVox::Region(Vector3DInt32(32, 32, 32), Vector3DInt32(63, 63, 63))); //Pass the surface to the OpenGL window openGLWidget.addMesh(mesh); + openGLWidget.addMesh(mesh2); openGLWidget.setViewableRegion(volData.getEnclosingRegion()); - //openGLWidget.addMesh(mesh2); //Run the message pump. return app.exec(); From d34fd6b3c8d42b4ca1f3ebb9a909820ee99c89cd Mon Sep 17 00:00:00 2001 From: David Williams Date: Fri, 23 May 2014 22:11:47 +0200 Subject: [PATCH 14/72] Moved OpenGLWidget into common folder so it can be used by other examples. --- examples/Basic/CMakeLists.txt | 2 +- examples/Basic/main.cpp | 8 ++++---- examples/{Basic => common}/OpenGLWidget.cpp | 0 examples/{Basic => common}/OpenGLWidget.h | 0 4 files changed, 5 insertions(+), 5 deletions(-) rename examples/{Basic => common}/OpenGLWidget.cpp (100%) rename examples/{Basic => common}/OpenGLWidget.h (100%) diff --git a/examples/Basic/CMakeLists.txt b/examples/Basic/CMakeLists.txt index 02e203d2..30ca5f3e 100644 --- a/examples/Basic/CMakeLists.txt +++ b/examples/Basic/CMakeLists.txt @@ -26,7 +26,7 @@ PROJECT(BasicExample) #Projects source files SET(SRC_FILES main.cpp - OpenGLWidget.cpp + ../common/OpenGLWidget.cpp ) #Projects headers files diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index ee908dd7..f123361b 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -78,15 +78,15 @@ int main(int argc, char *argv[]) createSphereInVolume(volData, 30); // Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see. - //auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion()); + auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion()); //auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion()); - auto mesh = extractCubicMesh(&volData, PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(31, 31, 31))); - auto mesh2 = extractCubicMesh(&volData, PolyVox::Region(Vector3DInt32(32, 32, 32), Vector3DInt32(63, 63, 63))); + //auto mesh = extractCubicMesh(&volData, PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(31, 31, 31))); + //auto mesh2 = extractCubicMesh(&volData, PolyVox::Region(Vector3DInt32(32, 32, 32), Vector3DInt32(63, 63, 63))); //Pass the surface to the OpenGL window openGLWidget.addMesh(mesh); - openGLWidget.addMesh(mesh2); + //openGLWidget.addMesh(mesh2); openGLWidget.setViewableRegion(volData.getEnclosingRegion()); //Run the message pump. diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp similarity index 100% rename from examples/Basic/OpenGLWidget.cpp rename to examples/common/OpenGLWidget.cpp diff --git a/examples/Basic/OpenGLWidget.h b/examples/common/OpenGLWidget.h similarity index 100% rename from examples/Basic/OpenGLWidget.h rename to examples/common/OpenGLWidget.h From 34f57911a741603d404ef06c7dda2816b9d9df46 Mon Sep 17 00:00:00 2001 From: David Williams Date: Fri, 23 May 2014 22:18:17 +0200 Subject: [PATCH 15/72] Converting OpenGLExample to use common OpenGLWidget. --- examples/OpenGL/CMakeLists.txt | 8 +- .../OpenGL/OpenGLImmediateModeSupport.cpp | 65 ----- examples/OpenGL/OpenGLImmediateModeSupport.h | 34 --- examples/OpenGL/OpenGLSupport.cpp | 66 ----- examples/OpenGL/OpenGLSupport.h | 40 --- .../OpenGLVertexBufferObjectSupport.cpp | 126 --------- .../OpenGL/OpenGLVertexBufferObjectSupport.h | 42 --- examples/OpenGL/OpenGLWidget.cpp | 246 ------------------ examples/OpenGL/OpenGLWidget.h | 99 ------- examples/OpenGL/main.cpp | 14 +- 10 files changed, 12 insertions(+), 728 deletions(-) delete mode 100644 examples/OpenGL/OpenGLImmediateModeSupport.cpp delete mode 100644 examples/OpenGL/OpenGLImmediateModeSupport.h delete mode 100644 examples/OpenGL/OpenGLSupport.cpp delete mode 100644 examples/OpenGL/OpenGLSupport.h delete mode 100644 examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp delete mode 100644 examples/OpenGL/OpenGLVertexBufferObjectSupport.h delete mode 100644 examples/OpenGL/OpenGLWidget.cpp delete mode 100644 examples/OpenGL/OpenGLWidget.h diff --git a/examples/OpenGL/CMakeLists.txt b/examples/OpenGL/CMakeLists.txt index 5cd1ed55..dde5a41b 100644 --- a/examples/OpenGL/CMakeLists.txt +++ b/examples/OpenGL/CMakeLists.txt @@ -26,18 +26,12 @@ PROJECT(OpenGLExample) #Projects source files SET(SRC_FILES main.cpp - OpenGLImmediateModeSupport.cpp - OpenGLSupport.cpp - OpenGLVertexBufferObjectSupport.cpp - OpenGLWidget.cpp + ../common/OpenGLWidget.cpp Shapes.cpp ) #Projects headers files SET(INC_FILES - OpenGLImmediateModeSupport.h - OpenGLSupport.h - OpenGLVertexBufferObjectSupport.h OpenGLWidget.h Shapes.h ) diff --git a/examples/OpenGL/OpenGLImmediateModeSupport.cpp b/examples/OpenGL/OpenGLImmediateModeSupport.cpp deleted file mode 100644 index ab2522bd..00000000 --- a/examples/OpenGL/OpenGLImmediateModeSupport.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#include "OpenGLImmediateModeSupport.h" -#include "OpenGLSupport.h" - -#include "PolyVoxCore/Mesh.h" - -using namespace PolyVox; -using namespace std; - -void renderRegionImmediateMode(PolyVox::Mesh >& mesh, unsigned int uLodLevel) -{ - const vector >& vecVertices = mesh.getVertices(); - const vector& vecIndices = mesh.getIndices(); - - int beginIndex = mesh.m_vecLodRecords[uLodLevel].beginIndex; - int endIndex = mesh.m_vecLodRecords[uLodLevel].endIndex; - - glBegin(GL_TRIANGLES); - //for(vector::const_iterator iterIndex = vecIndices.begin(); iterIndex != vecIndices.end(); ++iterIndex) - for(int index = beginIndex; index < endIndex; ++index) - { - const MarchingCubesVertex & vertex = vecVertices[vecIndices[index]]; - const Vector3DFloat& v3dVertexPos = vertex.getPosition(); - //const Vector3DFloat v3dRegionOffset(uRegionX * g_uRegionSideLength, uRegionY * g_uRegionSideLength, uRegionZ * g_uRegionSideLength); - const Vector3DFloat v3dFinalVertexPos = v3dVertexPos + static_cast(mesh.m_Region.getLowerCorner()); - - - - - uint8_t material = static_cast(static_cast(vertex.getMaterial().getMaterial()) + 0.5); - //uint8_t material = 1; - - - OpenGLColour colour = convertMaterialIDToColour(material); - - glColor3f(colour.red, colour.green, colour.blue); - glNormal3f(vertex.getNormal().getX(), vertex.getNormal().getY(), vertex.getNormal().getZ()); - glVertex3f(v3dFinalVertexPos.getX(), v3dFinalVertexPos.getY(), v3dFinalVertexPos.getZ()); - - - } - glEnd(); -} \ No newline at end of file diff --git a/examples/OpenGL/OpenGLImmediateModeSupport.h b/examples/OpenGL/OpenGLImmediateModeSupport.h deleted file mode 100644 index 3bc45a2b..00000000 --- a/examples/OpenGL/OpenGLImmediateModeSupport.h +++ /dev/null @@ -1,34 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#ifndef __OpenGLExample_OpenGLImmediateModeSupport_H__ -#define __OpenGLExample_OpenGLImmediateModeSupport_H__ - -#include "PolyVoxCore/MaterialDensityPair.h" -#include "PolyVoxCore/PolyVoxForwardDeclarations.h" - -#include "glew/glew.h" - -void renderRegionImmediateMode(PolyVox::Mesh >& mesh, unsigned int uLodLevel); - -#endif //__OpenGLExample_OpenGLImmediateModeSupport_H__ diff --git a/examples/OpenGL/OpenGLSupport.cpp b/examples/OpenGL/OpenGLSupport.cpp deleted file mode 100644 index 73efb444..00000000 --- a/examples/OpenGL/OpenGLSupport.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#include "OpenGLSupport.h" - -using namespace PolyVox; - -OpenGLColour convertMaterialIDToColour(uint8_t materialID) -{ - OpenGLColour colour; - - switch(materialID) - { - case 1: - colour.red = 1.0f; - colour.green = 0.0f; - colour.blue = 0.0f; - break; - case 2: - colour.red = 0.0f; - colour.green = 1.0f; - colour.blue = 0.0f; - break; - case 3: - colour.red = 0.0f; - colour.green = 0.0f; - colour.blue = 1.0f; - break; - case 4: - colour.red = 1.0f; - colour.green = 1.0f; - colour.blue = 0.0f; - break; - case 5: - colour.red = 1.0f; - colour.green = 0.0f; - colour.blue = 1.0f; - break; - default: - colour.red = 1.0f; - colour.green = 1.0f; - colour.blue = 1.0f; - } - - return colour; -} \ No newline at end of file diff --git a/examples/OpenGL/OpenGLSupport.h b/examples/OpenGL/OpenGLSupport.h deleted file mode 100644 index 2d4d1185..00000000 --- a/examples/OpenGL/OpenGLSupport.h +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#ifndef __OpenGLExample_OpenGLSupport_H__ -#define __OpenGLExample_OpenGLSupport_H__ - -#include "PolyVoxCore/PolyVoxForwardDeclarations.h" - -#include "glew/glew.h" - -struct OpenGLColour -{ - GLfloat red; - GLfloat green; - GLfloat blue; -}; - -OpenGLColour convertMaterialIDToColour(uint8_t materialID); - -#endif //__OpenGLExample_OpenGLSupport_H__ \ No newline at end of file diff --git a/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp b/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp deleted file mode 100644 index 17e9e138..00000000 --- a/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#include "OpenGLSupport.h" -#include "OpenGLVertexBufferObjectSupport.h" - -#include "PolyVoxCore/MaterialDensityPair.h" -#include "PolyVoxCore/Mesh.h" - -using namespace PolyVox; -using namespace std; - -OpenGLMesh BuildOpenGLMesh(const Mesh >& mesh) -{ - //Represents our filled in OpenGL vertex and index buffer objects. - OpenGLMesh result; - - //The source - result.sourceMesh = &mesh; - - //Convienient access to the vertices and indices - const vector >& vecVertices = mesh.getVertices(); - const vector& vecIndices = mesh.getIndices(); - - //If we have any indices... - if(!vecIndices.empty()) - { - //Create an OpenGL index buffer - glGenBuffers(1, &result.indexBuffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, result.indexBuffer); - - //Get a pointer to the first index - GLvoid* pIndices = (GLvoid*)(&(vecIndices[0])); - - //Fill the OpenGL index buffer with our data. - glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), pIndices, GL_STATIC_DRAW); - } - - result.noOfIndices = vecIndices.size(); - - glGenBuffers(1, &result.vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, result.vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(GLfloat) * 9, 0, GL_STATIC_DRAW); - GLfloat* ptr = (GLfloat*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE); - - for (vector >::const_iterator iterVertex = vecVertices.begin(); iterVertex != vecVertices.end(); ++iterVertex) - { - const MarchingCubesVertex & vertex = *iterVertex; - const Vector3DFloat& v3dVertexPos = vertex.getPosition(); - //const Vector3DFloat v3dRegionOffset(uRegionX * g_uRegionSideLength, uRegionY * g_uRegionSideLength, uRegionZ * g_uRegionSideLength); - const Vector3DFloat v3dFinalVertexPos = v3dVertexPos + static_cast(mesh.m_Region.getLowerCorner()); - - *ptr = v3dFinalVertexPos.getX(); - ptr++; - *ptr = v3dFinalVertexPos.getY(); - ptr++; - *ptr = v3dFinalVertexPos.getZ(); - ptr++; - - *ptr = vertex.getNormal().getX(); - ptr++; - *ptr = vertex.getNormal().getY(); - ptr++; - *ptr = vertex.getNormal().getZ(); - ptr++; - - uint8_t material = static_cast(vertex.getMaterial().getMaterial() + 0.5); - //uint8_t material = 1; - - OpenGLColour colour = convertMaterialIDToColour(material); - - *ptr = colour.red; - ptr++; - *ptr = colour.green; - ptr++; - *ptr = colour.blue; - ptr++; - } - - glUnmapBuffer(GL_ARRAY_BUFFER); - - return result; -} - -void renderRegionVertexBufferObject(const OpenGLMesh& openGLMesh, unsigned int uLodLevel) -{ - int beginIndex = openGLMesh.sourceMesh->m_vecLodRecords[uLodLevel].beginIndex; - int endIndex = openGLMesh.sourceMesh->m_vecLodRecords[uLodLevel].endIndex; - glBindBuffer(GL_ARRAY_BUFFER, openGLMesh.vertexBuffer); - glVertexPointer(3, GL_FLOAT, 36, 0); - glNormalPointer(GL_FLOAT, 36, (GLvoid*)12); - glColorPointer(3, GL_FLOAT, 36, (GLvoid*)24); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, openGLMesh.indexBuffer); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - - //glDrawElements(GL_TRIANGLES, openGLMesh.noOfIndices, GL_UNSIGNED_INT, 0); - glDrawRangeElements(GL_TRIANGLES, beginIndex, endIndex-1, endIndex - beginIndex,/* openGLMesh.noOfIndices,*/ GL_UNSIGNED_INT, 0); - - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); -} \ No newline at end of file diff --git a/examples/OpenGL/OpenGLVertexBufferObjectSupport.h b/examples/OpenGL/OpenGLVertexBufferObjectSupport.h deleted file mode 100644 index e82a8c29..00000000 --- a/examples/OpenGL/OpenGLVertexBufferObjectSupport.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#ifndef __OpenGLExample_OpenGLVertexBufferObjectSupport_H__ -#define __OpenGLExample_OpenGLVertexBufferObjectSupport_H__ - -#include "PolyVoxCore/PolyVoxForwardDeclarations.h" - -#include "glew/glew.h" - -struct OpenGLMesh -{ - GLulong noOfIndices; - GLuint indexBuffer; - GLuint vertexBuffer; - const PolyVox::Mesh >* sourceMesh; -}; - -OpenGLMesh BuildOpenGLMesh(const PolyVox::Mesh >& mesh); -void renderRegionVertexBufferObject(const OpenGLMesh& openGLMesh, unsigned int uLodLevel); - -#endif //__OpenGLExample_OpenGLVertexBufferObjectSupport_H__ diff --git a/examples/OpenGL/OpenGLWidget.cpp b/examples/OpenGL/OpenGLWidget.cpp deleted file mode 100644 index 38c107a9..00000000 --- a/examples/OpenGL/OpenGLWidget.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#include "OpenGLWidget.h" - -#include - -#include "PolyVoxCore/GradientEstimators.h" -#include "PolyVoxCore/MaterialDensityPair.h" -#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h" - -//Some namespaces we need -using namespace std; -using namespace PolyVox; -using namespace std; - -OpenGLWidget::OpenGLWidget(QWidget *parent) - :QGLWidget(parent) - ,m_volData(0) -{ - m_xRotation = 0; - m_yRotation = 0; - m_uRegionSideLength = 32; - - timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(update())); - timer->start(0); -} - -void OpenGLWidget::setVolume(PolyVox::LargeVolume* volData) -{ - //First we free anything from the previous volume (if there was one). - m_mapOpenGLMeshes.clear(); - m_mapMeshes.clear(); - m_volData = volData; - - //If we have any volume data then generate the new surface patches. - if(m_volData != 0) - { - m_uVolumeWidthInRegions = volData->getWidth() / m_uRegionSideLength; - m_uVolumeHeightInRegions = volData->getHeight() / m_uRegionSideLength; - m_uVolumeDepthInRegions = volData->getDepth() / m_uRegionSideLength; - - //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) - { - std::cout << "uRegionZ = " << uRegionZ << " of " << m_uVolumeDepthInRegions << std::endl; - for(uint16_t uRegionY = 0; uRegionY < m_uVolumeHeightInRegions; ++uRegionY) - { - for(uint16_t uRegionX = 0; uRegionX < m_uVolumeWidthInRegions; ++uRegionX) - { - //Compute the extents of the current region - //FIXME - This is a little complex? PolyVox could - //provide more functions for dealing with regions? - int32_t regionStartX = uRegionX * m_uRegionSideLength; - int32_t regionStartY = uRegionY * m_uRegionSideLength; - int32_t regionStartZ = uRegionZ * m_uRegionSideLength; - - int32_t regionEndX = regionStartX + m_uRegionSideLength; - int32_t regionEndY = regionStartY + m_uRegionSideLength; - int32_t regionEndZ = regionStartZ + m_uRegionSideLength; - - Vector3DInt32 regLowerCorner(regionStartX, regionStartY, regionStartZ); - Vector3DInt32 regUpperCorner(regionEndX, regionEndY, regionEndZ); - - //Extract the surface for this region - //extractSurface(m_volData, 0, PolyVox::Region(regLowerCorner, regUpperCorner), meshCurrent); - - std::shared_ptr< Mesh > > mesh(new Mesh >); - MarchingCubesSurfaceExtractor< LargeVolume > surfaceExtractor(volData, PolyVox::Region(regLowerCorner, regUpperCorner), mesh.get()); - surfaceExtractor.execute(); - - //decimatedMesh->generateAveragedFaceNormals(true); - - //computeNormalsForVertices(m_volData, *(decimatedMesh.get()), SOBEL_SMOOTHED); - //*meshCurrent = getSmoothedSurface(*meshCurrent); - //mesh->smooth(0.3f); - //meshCurrent->generateAveragedFaceNormals(true); - - if(mesh->m_vecTriangleIndices.size() > 0) - { - - - Vector3DUint8 v3dRegPos(uRegionX,uRegionY,uRegionZ); - if(m_bUseOpenGLVertexBufferObjects) - { - OpenGLMesh openGLMesh = BuildOpenGLMesh(*(mesh.get())); - m_mapOpenGLMeshes.insert(make_pair(v3dRegPos, openGLMesh)); - } - //else - //{ - m_mapMeshes.insert(make_pair(v3dRegPos, mesh)); - //} - //delete meshCurrent; - } - } - } - } - - //Projection matrix is dependant on volume size, so we need to set it up again. - setupProjectionMatrix(); - } -} - -void OpenGLWidget::initializeGL() -{ - m_bUseOpenGLVertexBufferObjects = true; - if(m_bUseOpenGLVertexBufferObjects) - { - //We need GLEW to access recent OpenGL functionality - GLenum err = glewInit(); - if (GLEW_OK != err) - { - /* Problem: glewInit failed, something is seriously wrong. */ - cout << "GLEW Error: " << glewGetErrorString(err) << endl; - } - } - - glShadeModel(GL_SMOOTH); // Enable Smooth Shading - glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background - glClearDepth(1.0f); // Depth Buffer Setup - glEnable(GL_DEPTH_TEST); // Enables Depth Testing - glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do - glEnable ( GL_COLOR_MATERIAL ); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - - glEnable(GL_LIGHTING); - glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - glEnable(GL_LIGHT0); - - //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - glShadeModel(GL_SMOOTH); -} - -void OpenGLWidget::resizeGL(int w, int h) -{ - //Setup the viewport based on the window size - glViewport(0, 0, w, h); - - //Projection matrix is also dependant on the size of the current volume. - if(m_volData) - { - setupProjectionMatrix(); - } -} - -void OpenGLWidget::paintGL() -{ - if(m_volData) - { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer - - glMatrixMode(GL_MODELVIEW); // Select The Model View Matrix - glLoadIdentity(); // Reset The Current Modelview Matrix - - //Moves the camera back so we can see the volume - glTranslatef(0.0f, 0.0f, -m_volData->getDiagonalLength()); - - glRotatef(m_xRotation, 1.0f, 0.0f, 0.0f); - glRotatef(m_yRotation, 0.0f, 1.0f, 0.0f); - - //Centre the volume on the origin - glTranslatef(-g_uVolumeSideLength/2,-g_uVolumeSideLength/2,-g_uVolumeSideLength/2); - - for(uint16_t uRegionZ = 0; uRegionZ < m_uVolumeDepthInRegions; ++uRegionZ) - { - for(uint16_t uRegionY = 0; uRegionY < m_uVolumeHeightInRegions; ++uRegionY) - { - for(uint16_t uRegionX = 0; uRegionX < m_uVolumeWidthInRegions; ++uRegionX) - { - Vector3DUint8 v3dRegPos(uRegionX,uRegionY,uRegionZ); - if(m_mapMeshes.find(v3dRegPos) != m_mapMeshes.end()) - { - std::shared_ptr< Mesh > > meshCurrent = m_mapMeshes[v3dRegPos]; - unsigned int uLodLevel = 0; //meshCurrent->m_vecLodRecords.size() - 1; - if(m_bUseOpenGLVertexBufferObjects) - { - renderRegionVertexBufferObject(m_mapOpenGLMeshes[v3dRegPos], uLodLevel); - } - else - { - renderRegionImmediateMode(*meshCurrent, uLodLevel); - } - } - } - } - } - - GLenum errCode; - const GLubyte *errString; - - if ((errCode = glGetError()) != GL_NO_ERROR) - { - errString = gluErrorString(errCode); - cout << "OpenGL Error: " << errString << endl; - } - } -} - -void OpenGLWidget::mousePressEvent(QMouseEvent* event) -{ - m_CurrentMousePos = event->pos(); - m_LastFrameMousePos = m_CurrentMousePos; -} - -void OpenGLWidget::mouseMoveEvent(QMouseEvent* event) -{ - m_CurrentMousePos = event->pos(); - QPoint diff = m_CurrentMousePos - m_LastFrameMousePos; - m_xRotation += diff.x(); - m_yRotation += diff.y(); - m_LastFrameMousePos = m_CurrentMousePos;; -} - -void OpenGLWidget::setupProjectionMatrix(void) -{ - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - - float frustumSize = m_volData->getDiagonalLength() / 2.0f; - float aspect = static_cast(width()) / static_cast(height()); - - glOrtho(frustumSize*aspect, -frustumSize*aspect, frustumSize, -frustumSize, 1.0, 5000); -} diff --git a/examples/OpenGL/OpenGLWidget.h b/examples/OpenGL/OpenGLWidget.h deleted file mode 100644 index 3511ac75..00000000 --- a/examples/OpenGL/OpenGLWidget.h +++ /dev/null @@ -1,99 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#ifndef __PolyVox_OpenGLWidget_H__ -#define __PolyVox_OpenGLWidget_H__ - -#include "glew/glew.h" - -#include -#include - -#include "PolyVoxCore/LargeVolume.h" -#include "PolyVoxCore/Mesh.h" -#include "PolyVoxCore/Impl/Utility.h" - -#include "OpenGLImmediateModeSupport.h" -#include "OpenGLVertexBufferObjectSupport.h" -#include "Shapes.h" - -const int32_t g_uVolumeSideLength = 128; - -struct Vector3DUint8Compare -{ - bool operator() (const PolyVox::Vector3DUint8& a, const PolyVox::Vector3DUint8& b) const - { - const uint32_t size = 3; - for(uint32_t ct = 0; ct < size; ++ct) - { - if (a.getElement(ct) < b.getElement(ct)) - return true; - if (b.getElement(ct) < a.getElement(ct)) - return false; - } - return false; - } -}; - -class OpenGLWidget : public QGLWidget - { - - public: - OpenGLWidget(QWidget *parent); - - void setVolume(PolyVox::LargeVolume* volData); - - void mouseMoveEvent(QMouseEvent* event); - void mousePressEvent(QMouseEvent* event); - - protected: - void initializeGL(); - void resizeGL(int w, int h); - void paintGL(); - - private: - void setupProjectionMatrix(void); - QPoint m_LastFrameMousePos; - QPoint m_CurrentMousePos; - - int m_xRotation; - int m_yRotation; - - QTimer *timer; - - bool m_bUseOpenGLVertexBufferObjects; - - //Creates a volume 128x128x128 - PolyVox::LargeVolume* m_volData; - - //Rather than storing one big mesh, the volume is broken into regions and a mesh is stored for each region - std::map m_mapOpenGLMeshes; - std::map > >, Vector3DUint8Compare> m_mapMeshes; - - unsigned int m_uRegionSideLength; - unsigned int m_uVolumeWidthInRegions; - unsigned int m_uVolumeHeightInRegions; - unsigned int m_uVolumeDepthInRegions; - }; - -#endif //__PolyVox_OpenGLWidget_H__ diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index ab70e957..e27987db 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -22,6 +22,7 @@ freely, subject to the following restrictions: *******************************************************************************/ #include "PolyVoxCore/FilePager.h" +#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h" #include "PolyVoxCore/MaterialDensityPair.h" #include "PolyVoxCore/LargeVolume.h" #include "PolyVoxCore/LowPassFilter.h" @@ -30,8 +31,6 @@ freely, subject to the following restrictions: #include "PolyVoxCore/Mesh.h" #include "PolyVoxCore/Impl/Utility.h" -#include "OpenGLImmediateModeSupport.h" -#include "OpenGLVertexBufferObjectSupport.h" #include "Shapes.h" #include "OpenGLWidget.h" @@ -48,6 +47,8 @@ using namespace std; using namespace PolyVox; using namespace std; +const int32_t g_uVolumeSideLength = 128; + int main(int argc, char *argv[]) { RLEBlockCompressor* compressor = new RLEBlockCompressor(); @@ -98,9 +99,16 @@ int main(int argc, char *argv[]) QTime time; time.start(); - openGLWidget.setVolume(&volData); + //openGLWidget.setVolume(&volData); cout << endl << "Time taken = " << time.elapsed() / 1000.0f << "s" << endl << endl; + auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion()); + + //Pass the surface to the OpenGL window + openGLWidget.addMesh(mesh); + //openGLWidget.addMesh(mesh2); + openGLWidget.setViewableRegion(volData.getEnclosingRegion()); + //return 0; return app.exec(); From 6cbb2d44bfbfa37c71a3c6b0fcfbe069c5c69315 Mon Sep 17 00:00:00 2001 From: David Williams Date: Fri, 23 May 2014 22:44:58 +0200 Subject: [PATCH 16/72] Work on making OpenGLExample work with common example framework. --- examples/OpenGL/main.cpp | 56 +++++++++++++++++++++++++++----- examples/common/OpenGLWidget.cpp | 39 ++++++++++------------ examples/common/OpenGLWidget.h | 11 ++++++- 3 files changed, 74 insertions(+), 32 deletions(-) diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index e27987db..962079f4 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -81,15 +81,6 @@ int main(int argc, char *argv[]) createCubeInVolume(volData, Vector3DInt32(midPos-10, 1, midPos-10), Vector3DInt32(midPos+10, maxPos-1, midPos+10), MaterialDensityPair44::getMaxDensity()); createCubeInVolume(volData, Vector3DInt32(midPos-10, midPos-10 ,1), Vector3DInt32(midPos+10, midPos+10, maxPos-1), MaterialDensityPair44::getMaxDensity()); - //I've removed this smoothing because it doesn't really make sense to apply a low pass filter to a volume with material values. - //I could implement the mathematical operators for MaterialDensityPair in such a way that they ignores the materials but this - //seems to be setting a bad example. Users can add this operators in their own classes if they want smoothing. - //RawVolume tempVolume(PolyVox::Region(0,0,0,128, 128, 128)); - //LowPassFilter< LargeVolume, RawVolume > pass1(&volData, PolyVox::Region(Vector3DInt32(62, 62, 62), Vector3DInt32(126, 126, 126)), &tempVolume, PolyVox::Region(Vector3DInt32(62, 62, 62), Vector3DInt32(126, 126, 126)), 3); - //pass1.executeSAT(); - //LowPassFilter< RawVolume, LargeVolume > pass2(&tempVolume, PolyVox::Region(Vector3DInt32(62, 62, 62), Vector3DInt32(126, 126, 126)), &volData, PolyVox::Region(Vector3DInt32(62, 62, 62), Vector3DInt32(126, 126, 126)), 3); - //pass2.executeSAT(); - QApplication app(argc, argv); OpenGLWidget openGLWidget(0); @@ -97,6 +88,53 @@ int main(int argc, char *argv[]) openGLWidget.show(); + QGLShaderProgram* shader = new QGLShaderProgram; + + if (!shader->addShaderFromSourceCode(QGLShader::Vertex, R"( + #version 140 + + in vec4 position; //This will be the position of the vertex in model-space + + uniform mat4 cameraToClipMatrix; + uniform mat4 worldToCameraMatrix; + uniform mat4 modelToWorldMatrix; + + out vec4 worldPosition; //This is being passed to the fragment shader to calculate the normals + + void main() + { + worldPosition = modelToWorldMatrix * position; + vec4 cameraPosition = worldToCameraMatrix * worldPosition; + gl_Position = cameraToClipMatrix * cameraPosition; + } + )")) + { + std::cerr << shader->log().toStdString() << std::endl; + exit(EXIT_FAILURE); + } + + if (!shader->addShaderFromSourceCode(QGLShader::Fragment, R"( + #version 130 + + in vec4 worldPosition; //Passed in from the vertex shader + + out vec4 outputColor; + + void main() + { + vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz))); + + float color = clamp(abs(dot(normalize(normal.xyz), vec3(0.9,0.1,0.5))), 0, 1); + outputColor = vec4(1.0, 1.0, 1.0, 1.0); + } + )")) + { + std::cerr << shader->log().toStdString() << std::endl; + exit(EXIT_FAILURE); + } + + openGLWidget.setShader(shader); + QTime time; time.start(); //openGLWidget.setVolume(&volData); diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index 78dbff0c..1088d9fe 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -50,8 +50,10 @@ void OpenGLWidget::initializeGL() glDepthMask(GL_TRUE); glDepthFunc(GL_LEQUAL); glDepthRange(0.0, 1.0); + + shader = new QGLShaderProgram; - if (!shader.addShaderFromSourceCode(QGLShader::Vertex, R"( + if (!shader->addShaderFromSourceCode(QGLShader::Vertex, R"( #version 140 in vec4 position; //This will be the position of the vertex in model-space @@ -70,11 +72,11 @@ void OpenGLWidget::initializeGL() } )")) { - std::cerr << shader.log().toStdString() << std::endl; + std::cerr << shader->log().toStdString() << std::endl; exit(EXIT_FAILURE); } - if (!shader.addShaderFromSourceCode(QGLShader::Fragment, R"( + if (!shader->addShaderFromSourceCode(QGLShader::Fragment, R"( #version 130 in vec4 worldPosition; //Passed in from the vertex shader @@ -90,15 +92,15 @@ void OpenGLWidget::initializeGL() } )")) { - std::cerr << shader.log().toStdString() << std::endl; + std::cerr << shader->log().toStdString() << std::endl; exit(EXIT_FAILURE); } - shader.bindAttributeLocation("position", 0); + shader->bindAttributeLocation("position", 0); - if(!shader.link()) + if (!shader->link()) { - std::cerr << shader.log().toStdString() << std::endl; + std::cerr << shader->log().toStdString() << std::endl; exit(EXIT_FAILURE); } @@ -114,12 +116,8 @@ void OpenGLWidget::resizeGL(int w, int h) float zNear = 1.0; float zFar = 1000.0; - QMatrix4x4 cameraToClipMatrix{}; + cameraToClipMatrix.setToIdentity(); cameraToClipMatrix.frustum(-aspectRatio, aspectRatio, -1, 1, zNear, zFar); - - shader.bind(); - shader.setUniformValue("cameraToClipMatrix", cameraToClipMatrix); - shader.release(); } void OpenGLWidget::paintGL() @@ -127,13 +125,16 @@ void OpenGLWidget::paintGL() //Clear the screen glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - shader.bind(); + shader->bind(); + + shader->setUniformValue("worldToCameraMatrix", worldToCameraMatrix); + shader->setUniformValue("cameraToClipMatrix", cameraToClipMatrix); for (OpenGLMeshData meshData : mMeshData) { QMatrix4x4 modelToWorldMatrix{}; modelToWorldMatrix.translate(meshData.translation.getX(), meshData.translation.getY(), meshData.translation.getZ()); // Centre the model on the origin - shader.setUniformValue("modelToWorldMatrix", modelToWorldMatrix); // Update to the latest camera matrix + shader->setUniformValue("modelToWorldMatrix", modelToWorldMatrix); // Update to the latest camera matrix glBindVertexArray(meshData.vertexArrayObject); @@ -142,7 +143,7 @@ void OpenGLWidget::paintGL() glBindVertexArray(0); } - shader.release(); + shader->release(); GLenum errCode = glGetError(); if(errCode != GL_NO_ERROR) @@ -174,21 +175,15 @@ void OpenGLWidget::mouseMoveEvent(QMouseEvent* event) void OpenGLWidget::setupWorldToCameraMatrix() { - shader.bind(); - QVector3D lowerCorner(m_viewableRegion.getLowerX(), m_viewableRegion.getLowerY(), m_viewableRegion.getLowerZ()); QVector3D upperCorner(m_viewableRegion.getUpperX(), m_viewableRegion.getUpperY(), m_viewableRegion.getUpperZ()); QVector3D centerPoint = (lowerCorner + upperCorner) * 0.5; float fDiagonalLength = (upperCorner - lowerCorner).length(); - QMatrix4x4 worldToCameraMatrix{}; + worldToCameraMatrix.setToIdentity(); worldToCameraMatrix.translate(0, 0, -fDiagonalLength / 2.0f); //Move the camera back by the required amount worldToCameraMatrix.rotate(m_xRotation, 0, 1, 0); //rotate around y-axis worldToCameraMatrix.rotate(m_yRotation, 1, 0, 0); //rotate around x-axis worldToCameraMatrix.translate(-centerPoint); //centre the model on the origin - - shader.setUniformValue("worldToCameraMatrix", worldToCameraMatrix); - - shader.release(); } \ No newline at end of file diff --git a/examples/common/OpenGLWidget.h b/examples/common/OpenGLWidget.h index 2d9cc6d6..d80b7a70 100644 --- a/examples/common/OpenGLWidget.h +++ b/examples/common/OpenGLWidget.h @@ -53,6 +53,11 @@ public: // The viewable region can be adjusted so that this example framework can be use for different volume sizes. void setViewableRegion(PolyVox::Region viewableRegion); + void setShader(QGLShaderProgram* shader) + { + this->shader = shader; + } + // Convert a SurfaceMesh to OpenGL index/vertex buffers. Inlined because it's templatised. template void addMesh(const MeshType& surfaceMesh) @@ -107,7 +112,11 @@ private: // Index/vertex buffer data std::vector mMeshData; - QGLShaderProgram shader; + QGLShaderProgram* shader; + + // Matrices + QMatrix4x4 worldToCameraMatrix; + QMatrix4x4 cameraToClipMatrix; // Mouse data QPoint m_LastFrameMousePos; From f65edddd816d780aba3ffe36e7379b3678f79ea1 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sat, 24 May 2014 08:38:18 +0200 Subject: [PATCH 17/72] Tidying up. --- examples/common/OpenGLWidget.h | 4 ++-- library/PolyVoxCore/include/PolyVoxCore/Mesh.h | 5 ++++- library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h | 10 ++++++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/examples/common/OpenGLWidget.h b/examples/common/OpenGLWidget.h index d80b7a70..96102a99 100644 --- a/examples/common/OpenGLWidget.h +++ b/examples/common/OpenGLWidget.h @@ -77,7 +77,7 @@ public: //The GL_ARRAY_BUFFER will contain the list of vertex positions glGenBuffers(1, &(meshData.vertexBuffer)); glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(CubicVertex), vecVertices.data(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(MeshType::VertexType), vecVertices.data(), GL_STATIC_DRAW); //and GL_ELEMENT_ARRAY_BUFFER will contain the indices glGenBuffers(1, &(meshData.indexBuffer)); @@ -86,7 +86,7 @@ public: //We need to tell OpenGL how to understand the format of the vertex data glEnableVertexAttribArray(0); //We're talking about shader attribute '0' - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(CubicVertex), 0); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(MeshType::VertexType), 0); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) glBindVertexArray(0); diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h index 90ebbfac..bcb40576 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h @@ -45,10 +45,13 @@ namespace PolyVox int endIndex; //Let's put it just past the end STL style }; - template + template class Mesh { public: + + typedef _VertexType VertexType; + Mesh(); ~Mesh(); diff --git a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h index a5a24d79..e8d938ae 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h +++ b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h @@ -36,11 +36,14 @@ namespace PolyVox #ifdef SWIG class CubicVertex #else - template + template class POLYVOX_API CubicVertex #endif { public: + + typedef _VoxelType VoxelType; + CubicVertex() { } @@ -97,11 +100,14 @@ namespace PolyVox #ifdef SWIG class MarchingCubesVertex #else - template + template class POLYVOX_API MarchingCubesVertex #endif { public: + + typedef _VoxelType VoxelType; + MarchingCubesVertex() { } From aace1f2e36f49ba20e8947040826b1854f683089 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sat, 24 May 2014 09:38:01 +0200 Subject: [PATCH 18/72] Exposing normals to example framework. --- examples/OpenGL/main.cpp | 16 ++++++++++++---- examples/common/OpenGLWidget.cpp | 4 +++- examples/common/OpenGLWidget.h | 5 ++++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index 962079f4..b52b4860 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -93,17 +93,20 @@ int main(int argc, char *argv[]) if (!shader->addShaderFromSourceCode(QGLShader::Vertex, R"( #version 140 - in vec4 position; //This will be the position of the vertex in model-space + in vec4 position; // This will be the position of the vertex in model-space + in vec4 normal; // The normal data may not have been set uniform mat4 cameraToClipMatrix; uniform mat4 worldToCameraMatrix; uniform mat4 modelToWorldMatrix; out vec4 worldPosition; //This is being passed to the fragment shader to calculate the normals + out vec4 worldNormal; void main() { worldPosition = modelToWorldMatrix * position; + worldNormal = normal; vec4 cameraPosition = worldToCameraMatrix * worldPosition; gl_Position = cameraToClipMatrix * cameraPosition; } @@ -117,15 +120,20 @@ int main(int argc, char *argv[]) #version 130 in vec4 worldPosition; //Passed in from the vertex shader + in vec4 worldNormal; out vec4 outputColor; void main() { - vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz))); + //vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz))); + + vec3 normal = worldNormal.xyz; + + outputColor = vec4(normalize(normal.xyz), 1.0); - float color = clamp(abs(dot(normalize(normal.xyz), vec3(0.9,0.1,0.5))), 0, 1); - outputColor = vec4(1.0, 1.0, 1.0, 1.0); + //float color = clamp(abs(dot(normalize(normal.xyz), vec3(0.9,0.1,0.5))), 0, 1); + //outputColor = vec4(1.0, 0.5, color, 1.0); } )")) { diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index 1088d9fe..93d1a369 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -56,7 +56,7 @@ void OpenGLWidget::initializeGL() if (!shader->addShaderFromSourceCode(QGLShader::Vertex, R"( #version 140 - in vec4 position; //This will be the position of the vertex in model-space + in vec4 position; // This will be the position of the vertex in model-space uniform mat4 cameraToClipMatrix; uniform mat4 worldToCameraMatrix; @@ -80,6 +80,7 @@ void OpenGLWidget::initializeGL() #version 130 in vec4 worldPosition; //Passed in from the vertex shader + in vec4 worldNormal; out vec4 outputColor; @@ -97,6 +98,7 @@ void OpenGLWidget::initializeGL() } shader->bindAttributeLocation("position", 0); + shader->bindAttributeLocation("normal", 1); if (!shader->link()) { diff --git a/examples/common/OpenGLWidget.h b/examples/common/OpenGLWidget.h index 96102a99..eff6366a 100644 --- a/examples/common/OpenGLWidget.h +++ b/examples/common/OpenGLWidget.h @@ -86,7 +86,10 @@ public: //We need to tell OpenGL how to understand the format of the vertex data glEnableVertexAttribArray(0); //We're talking about shader attribute '0' - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(MeshType::VertexType), 0); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(MeshType::VertexType), (GLvoid*)(offsetof(MeshType::VertexType, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + + glEnableVertexAttribArray(1); //We're talking about shader attribute '1' + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(MeshType::VertexType), (GLvoid*)(offsetof(MeshType::VertexType, normal))); glBindVertexArray(0); From 07b9cf05fabcacf515bb4a1fc07afecd4178cbc6 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sat, 24 May 2014 21:09:26 +0200 Subject: [PATCH 19/72] Changed OpenGLExample to use MaterialDensityPair88 instead of MaterialDensityPair44. Added material to shaders. --- examples/OpenGL/Shapes.cpp | 12 ++++++------ examples/OpenGL/Shapes.h | 4 ++-- examples/OpenGL/main.cpp | 28 ++++++++++++++++++++++++---- examples/common/OpenGLWidget.cpp | 1 + examples/common/OpenGLWidget.h | 3 +++ 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/examples/OpenGL/Shapes.cpp b/examples/OpenGL/Shapes.cpp index 558530ba..7a66b988 100644 --- a/examples/OpenGL/Shapes.cpp +++ b/examples/OpenGL/Shapes.cpp @@ -27,7 +27,7 @@ freely, subject to the following restrictions: using namespace PolyVox; -void createSphereInVolume(LargeVolume& volData, float fRadius, uint8_t uValue) +void createSphereInVolume(LargeVolume& volData, float fRadius, uint8_t uValue) { //This vector hold the position of the center of the volume Vector3DInt32 v3dVolCenter = (volData.getEnclosingRegion().getUpperCorner() - volData.getEnclosingRegion().getLowerCorner()) / static_cast(2); @@ -48,17 +48,17 @@ void createSphereInVolume(LargeVolume& volData, float fRa //then we make it solid, otherwise we make it empty space. if(fDistToCenter <= fRadius) { - volData.setVoxelAt(x,y,z, MaterialDensityPair44(uValue, uValue > 0 ? MaterialDensityPair44::getMaxDensity() : MaterialDensityPair44::getMinDensity())); + volData.setVoxelAt(x,y,z, MaterialDensityPair88(uValue, uValue > 0 ? MaterialDensityPair88::getMaxDensity() : MaterialDensityPair88::getMinDensity())); } } } } } -void createCubeInVolume(LargeVolume& volData, Vector3DInt32 lowerCorner, Vector3DInt32 upperCorner, uint8_t uValue) +void createCubeInVolume(LargeVolume& volData, Vector3DInt32 lowerCorner, Vector3DInt32 upperCorner, uint8_t uValue) { - uint8_t maxDen = MaterialDensityPair44::getMaxDensity(); - uint8_t minDen = MaterialDensityPair44::getMinDensity(); + uint8_t maxDen = MaterialDensityPair88::getMaxDensity(); + uint8_t minDen = MaterialDensityPair88::getMinDensity(); //This three-level for loop iterates over every voxel between the specified corners for (int z = lowerCorner.getZ(); z <= upperCorner.getZ(); z++) { @@ -66,7 +66,7 @@ void createCubeInVolume(LargeVolume& volData, Vector3DInt { for (int x = lowerCorner.getX() ; x <= upperCorner.getX(); x++) { - volData.setVoxelAt(x,y,z, MaterialDensityPair44(uValue, uValue > 0 ? maxDen : minDen)); + volData.setVoxelAt(x,y,z, MaterialDensityPair88(uValue, uValue > 0 ? maxDen : minDen)); } } } diff --git a/examples/OpenGL/Shapes.h b/examples/OpenGL/Shapes.h index 93f047fd..712558fd 100644 --- a/examples/OpenGL/Shapes.h +++ b/examples/OpenGL/Shapes.h @@ -27,7 +27,7 @@ freely, subject to the following restrictions: #include "PolyVoxCore/LargeVolume.h" #include "PolyVoxCore/MaterialDensityPair.h" -void createSphereInVolume(PolyVox::LargeVolume& volData, float fRadius, uint8_t uValue); -void createCubeInVolume(PolyVox::LargeVolume& volData, PolyVox::Vector3DInt32 lowerCorner, PolyVox::Vector3DInt32 upperCorner, uint8_t uValue); +void createSphereInVolume(PolyVox::LargeVolume& volData, float fRadius, uint8_t uValue); +void createCubeInVolume(PolyVox::LargeVolume& volData, PolyVox::Vector3DInt32 lowerCorner, PolyVox::Vector3DInt32 upperCorner, uint8_t uValue); #endif //__OpenGLExample_Shapes_H__ \ No newline at end of file diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index b52b4860..03014c72 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -51,9 +51,9 @@ const int32_t g_uVolumeSideLength = 128; int main(int argc, char *argv[]) { - RLEBlockCompressor* compressor = new RLEBlockCompressor(); - FilePager* pager = new FilePager("./"); - LargeVolume volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(g_uVolumeSideLength-1, g_uVolumeSideLength-1, g_uVolumeSideLength-1)), compressor, pager); + RLEBlockCompressor* compressor = new RLEBlockCompressor(); + FilePager* pager = new FilePager("./"); + LargeVolume volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(g_uVolumeSideLength - 1, g_uVolumeSideLength - 1, g_uVolumeSideLength - 1)), compressor, pager); //Make our volume contain a sphere in the center. int32_t minPos = 0; @@ -95,6 +95,7 @@ int main(int argc, char *argv[]) in vec4 position; // This will be the position of the vertex in model-space in vec4 normal; // The normal data may not have been set + in vec2 material; uniform mat4 cameraToClipMatrix; uniform mat4 worldToCameraMatrix; @@ -102,11 +103,14 @@ int main(int argc, char *argv[]) out vec4 worldPosition; //This is being passed to the fragment shader to calculate the normals out vec4 worldNormal; + out vec2 outMaterial; void main() { + //material = vec2( worldPosition = modelToWorldMatrix * position; worldNormal = normal; + outMaterial = vec2(material.x, material.y); vec4 cameraPosition = worldToCameraMatrix * worldPosition; gl_Position = cameraToClipMatrix * cameraPosition; } @@ -121,6 +125,7 @@ int main(int argc, char *argv[]) in vec4 worldPosition; //Passed in from the vertex shader in vec4 worldNormal; + in vec2 outMaterial; out vec4 outputColor; @@ -130,7 +135,22 @@ int main(int argc, char *argv[]) vec3 normal = worldNormal.xyz; - outputColor = vec4(normalize(normal.xyz), 1.0); + if(outMaterial.x < 1.5) + { + outputColor = vec4(1.0, 0.0, 0.0, 1.0); + } + else if(outMaterial.x < 2.5) + { + outputColor = vec4(0.0, 1.0, 0.0, 1.0); + } + else if(outMaterial.x < 3.5) + { + outputColor = vec4(0.0, 0.0, 1.0, 1.0); + } + else + { + outputColor = vec4(1.0, 1.0, 0.0, 1.0); + } //float color = clamp(abs(dot(normalize(normal.xyz), vec3(0.9,0.1,0.5))), 0, 1); //outputColor = vec4(1.0, 0.5, color, 1.0); diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index 93d1a369..1777ba54 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -99,6 +99,7 @@ void OpenGLWidget::initializeGL() shader->bindAttributeLocation("position", 0); shader->bindAttributeLocation("normal", 1); + shader->bindAttributeLocation("material", 2); if (!shader->link()) { diff --git a/examples/common/OpenGLWidget.h b/examples/common/OpenGLWidget.h index eff6366a..521f239e 100644 --- a/examples/common/OpenGLWidget.h +++ b/examples/common/OpenGLWidget.h @@ -91,6 +91,9 @@ public: glEnableVertexAttribArray(1); //We're talking about shader attribute '1' glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(MeshType::VertexType), (GLvoid*)(offsetof(MeshType::VertexType, normal))); + glEnableVertexAttribArray(2); //We're talking about shader attribute '2' + glVertexAttribPointer(2, 2, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(MeshType::VertexType), (GLvoid*)(offsetof(MeshType::VertexType, material))); + glBindVertexArray(0); meshData.noOfIndices = vecIndices.size(); //Save this for the call to glDrawElements later From 99cf75e9027a0a427e9fd760bc91ad744b2cb448 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sat, 24 May 2014 22:53:10 +0200 Subject: [PATCH 20/72] Material now passed to shader as integer rather than float. --- examples/OpenGL/main.cpp | 14 +++++++------- examples/common/OpenGLWidget.h | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index 03014c72..4f4d9d15 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -95,7 +95,7 @@ int main(int argc, char *argv[]) in vec4 position; // This will be the position of the vertex in model-space in vec4 normal; // The normal data may not have been set - in vec2 material; + in ivec2 material; uniform mat4 cameraToClipMatrix; uniform mat4 worldToCameraMatrix; @@ -103,14 +103,14 @@ int main(int argc, char *argv[]) out vec4 worldPosition; //This is being passed to the fragment shader to calculate the normals out vec4 worldNormal; - out vec2 outMaterial; + flat out ivec2 outMaterial; void main() { //material = vec2( worldPosition = modelToWorldMatrix * position; worldNormal = normal; - outMaterial = vec2(material.x, material.y); + outMaterial = ivec2(material.x, material.y); vec4 cameraPosition = worldToCameraMatrix * worldPosition; gl_Position = cameraToClipMatrix * cameraPosition; } @@ -125,7 +125,7 @@ int main(int argc, char *argv[]) in vec4 worldPosition; //Passed in from the vertex shader in vec4 worldNormal; - in vec2 outMaterial; + flat in ivec2 outMaterial; out vec4 outputColor; @@ -135,15 +135,15 @@ int main(int argc, char *argv[]) vec3 normal = worldNormal.xyz; - if(outMaterial.x < 1.5) + if(outMaterial.x == 1) { outputColor = vec4(1.0, 0.0, 0.0, 1.0); } - else if(outMaterial.x < 2.5) + else if(outMaterial.x == 2) { outputColor = vec4(0.0, 1.0, 0.0, 1.0); } - else if(outMaterial.x < 3.5) + else if(outMaterial.x == 3) { outputColor = vec4(0.0, 0.0, 1.0, 1.0); } diff --git a/examples/common/OpenGLWidget.h b/examples/common/OpenGLWidget.h index 521f239e..a1c1c37c 100644 --- a/examples/common/OpenGLWidget.h +++ b/examples/common/OpenGLWidget.h @@ -92,7 +92,8 @@ public: glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(MeshType::VertexType), (GLvoid*)(offsetof(MeshType::VertexType, normal))); glEnableVertexAttribArray(2); //We're talking about shader attribute '2' - glVertexAttribPointer(2, 2, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(MeshType::VertexType), (GLvoid*)(offsetof(MeshType::VertexType, material))); + GLint size = (std::min)(sizeof(MeshType::VertexType::VoxelType), size_t(4)); + glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(MeshType::VertexType), (GLvoid*)(offsetof(MeshType::VertexType, material))); glBindVertexArray(0); From f78aad8abd7b09ab0ad1f94c9d8d41cb1247a4ae Mon Sep 17 00:00:00 2001 From: David Williams Date: Sat, 24 May 2014 22:58:31 +0200 Subject: [PATCH 21/72] Fixed colors to match previous version of the example. --- examples/OpenGL/main.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index 4f4d9d15..14315a95 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -135,21 +135,26 @@ int main(int argc, char *argv[]) vec3 normal = worldNormal.xyz; - if(outMaterial.x == 1) + switch(outMaterial.x) { + case 1: outputColor = vec4(1.0, 0.0, 0.0, 1.0); - } - else if(outMaterial.x == 2) - { + break; + case 2: outputColor = vec4(0.0, 1.0, 0.0, 1.0); - } - else if(outMaterial.x == 3) - { + break; + case 3: outputColor = vec4(0.0, 0.0, 1.0, 1.0); - } - else - { + break; + case 4: outputColor = vec4(1.0, 1.0, 0.0, 1.0); + break; + case 5: + outputColor = vec4(1.0, 0.0, 1.0, 1.0); + break; + default: + outputColor = vec4(1.0, 1.0, 1.0, 1.0); + break; } //float color = clamp(abs(dot(normalize(normal.xyz), vec3(0.9,0.1,0.5))), 0, 1); From eb39f0bb4c400d28953bd6c717d1b4d1046036de Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 25 May 2014 12:28:45 +0200 Subject: [PATCH 22/72] OpenGLExample is once again rendered as multiple separate mehses (but using the example framework this time). --- examples/OpenGL/main.cpp | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index 14315a95..4f0c0f2f 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -107,7 +107,6 @@ int main(int argc, char *argv[]) void main() { - //material = vec2( worldPosition = modelToWorldMatrix * position; worldNormal = normal; outMaterial = ivec2(material.x, material.y); @@ -173,14 +172,38 @@ int main(int argc, char *argv[]) //openGLWidget.setVolume(&volData); cout << endl << "Time taken = " << time.elapsed() / 1000.0f << "s" << endl << endl; - auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion()); + const int32_t extractedRegionSize = 32; + const int32_t gapBetweenRegions = 1; // Set this to '1' + int meshCounter = 0; + + for (int32_t z = 0; z < volData.getDepth(); z += extractedRegionSize) + { + for (int32_t y = 0; y < volData.getHeight(); y += extractedRegionSize) + { + for (int32_t x = 0; x < volData.getWidth(); x += extractedRegionSize) + { + // Specify the region to extract based on a starting position and the desired region sze. + Region regToExtract(x, y, z, x + extractedRegionSize, y + extractedRegionSize, z + extractedRegionSize); + + // If you uncomment this line you will be able to see that the volume is rendered as multiple seperate meshes. + //regToExtract.shrink(1); + + // Perform the extraction for this region of the volume + auto mesh = extractMarchingCubesMesh(&volData, regToExtract); + + //Pass the surface to the OpenGL window + openGLWidget.addMesh(mesh); + + meshCounter++; + } + } + } + + cout << "Rendering volume as " << meshCounter << " seperate meshes" << endl; + - //Pass the surface to the OpenGL window - openGLWidget.addMesh(mesh); - //openGLWidget.addMesh(mesh2); openGLWidget.setViewableRegion(volData.getEnclosingRegion()); - //return 0; return app.exec(); } From e80c88a5ec2207fac256773870fc6c52120cd4f9 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 25 May 2014 21:03:52 +0200 Subject: [PATCH 23/72] Paging example now uses the new example OpenGLWidget. --- examples/Paging/CMakeLists.txt | 2 +- examples/Paging/OpenGLWidget.cpp | 135 ------------------------------- examples/Paging/OpenGLWidget.h | 68 ---------------- examples/Paging/main.cpp | 2 +- 4 files changed, 2 insertions(+), 205 deletions(-) delete mode 100644 examples/Paging/OpenGLWidget.cpp delete mode 100644 examples/Paging/OpenGLWidget.h diff --git a/examples/Paging/CMakeLists.txt b/examples/Paging/CMakeLists.txt index e8020b2d..aa9b2899 100644 --- a/examples/Paging/CMakeLists.txt +++ b/examples/Paging/CMakeLists.txt @@ -26,7 +26,7 @@ PROJECT(PagingExample) #Projects source files SET(SRC_FILES main.cpp - OpenGLWidget.cpp + ../common/OpenGLWidget.cpp Perlin.cpp ) diff --git a/examples/Paging/OpenGLWidget.cpp b/examples/Paging/OpenGLWidget.cpp deleted file mode 100644 index fa2aa7be..00000000 --- a/examples/Paging/OpenGLWidget.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "OpenGLWidget.h" - -#include - -using namespace PolyVox; -using namespace std; - -OpenGLWidget::OpenGLWidget(QWidget *parent) - :QGLWidget(parent) - ,m_uBeginIndex(0) - ,m_uEndIndex(0) - ,noOfIndices(0) - ,m_xRotation(0) - ,m_yRotation(0) -{ -} - -void OpenGLWidget::setMeshToRender(const PolyVox::Mesh >& surfaceMesh) -{ - if((surfaceMesh.getNoOfIndices() == 0) || (surfaceMesh.getNoOfVertices() == 0)) - { - //We don't have a valid mesh - return; - } - - //Convienient access to the vertices and indices - const vector& vecIndices = surfaceMesh.getIndices(); - const vector >& vecVertices = surfaceMesh.getVertices(); - - //Build an OpenGL index buffer - glGenBuffers(1, &indexBuffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); - const GLvoid* pIndices = static_cast(&(vecIndices[0])); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), pIndices, GL_STATIC_DRAW); - - //Build an OpenGL vertex buffer - glGenBuffers(1, &vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); - const GLvoid* pVertices = static_cast(&(vecVertices[0])); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(CubicVertex), pVertices, GL_STATIC_DRAW); - - m_uBeginIndex = 0; - m_uEndIndex = vecIndices.size(); - noOfIndices = surfaceMesh.getNoOfIndices(); -} - -void OpenGLWidget::initializeGL() -{ - //We need GLEW to access recent OpenGL functionality - GLenum err = glewInit(); - if (GLEW_OK != err) - { - /* Problem: glewInit failed, something is seriously wrong. */ - std::cout << "GLEW Error: " << glewGetErrorString(err) << std::endl; - } - - //Set up the clear colour - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClearDepth(1.0f); - - //Enable the depth buffer - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - - //Enable smooth lighting - //glEnable(GL_LIGHTING); - //glEnable(GL_LIGHT0); - //glShadeModel(GL_SMOOTH); - - //We'll be rendering with index/vertex arrays - glEnableClientState(GL_VERTEX_ARRAY); - //glEnableClientState(GL_NORMAL_ARRAY); -} - -void OpenGLWidget::resizeGL(int w, int h) -{ - //Setup the viewport - glViewport(0, 0, w, h); - - //Set up the projection matrix - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - float frustumSize = 128.0f * 1.7f; //Half the volume diagonal - float aspect = static_cast(width()) / static_cast(height()); - glOrtho(frustumSize*aspect, -frustumSize*aspect, frustumSize, -frustumSize, 10.0, 10000); -} - -void OpenGLWidget::paintGL() -{ - if(noOfIndices == 0) - { - //Nothing to render - return; - } - - //Clear the screen - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - //Set up the viewing transformation - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.0f,0.0f,-5000.0f); //Centre volume and move back - glRotatef(m_xRotation, 1.0f, 0.0f, 0.0f); - glRotatef(m_yRotation, 0.0f, 1.0f, 0.0f); - glTranslatef(-128.0f,-128.0f,-128.0f); //Centre volume and move back - - //Bind the index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); - - //Bind the vertex buffer - glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); - glVertexPointer(3, GL_FLOAT, sizeof(CubicVertex), 0); - //glNormalPointer(GL_FLOAT, sizeof(CubicVertex), (GLvoid*)12); - - glDrawRangeElements(GL_TRIANGLES, m_uBeginIndex, m_uEndIndex-1, m_uEndIndex - m_uBeginIndex, GL_UNSIGNED_INT, 0); -} - -void OpenGLWidget::mousePressEvent(QMouseEvent* event) -{ - m_CurrentMousePos = event->pos(); - m_LastFrameMousePos = m_CurrentMousePos; - - update(); -} - -void OpenGLWidget::mouseMoveEvent(QMouseEvent* event) -{ - m_CurrentMousePos = event->pos(); - QPoint diff = m_CurrentMousePos - m_LastFrameMousePos; - m_xRotation += diff.x(); - m_yRotation += diff.y(); - m_LastFrameMousePos = m_CurrentMousePos; - - update(); -} diff --git a/examples/Paging/OpenGLWidget.h b/examples/Paging/OpenGLWidget.h deleted file mode 100644 index 63afbb97..00000000 --- a/examples/Paging/OpenGLWidget.h +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software -in a product, an acknowledgment in the product documentation would be -appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*******************************************************************************/ - -#ifndef __BasicExample_OpenGLWidget_H__ -#define __BasicExample_OpenGLWidget_H__ - -#include "PolyVoxCore/MaterialDensityPair.h" -#include "PolyVoxCore/Mesh.h" - -#include "glew/glew.h" - -#include - -class OpenGLWidget : public QGLWidget -{ -public: - //Constructor - OpenGLWidget(QWidget *parent); - - //Mouse handling - void mouseMoveEvent(QMouseEvent* event); - void mousePressEvent(QMouseEvent* event); - - //Convert a SrfaceMesh to OpenGL index/vertex buffers - void setMeshToRender(const PolyVox::Mesh >& surfaceMesh); - -protected: - //Qt OpenGL functions - void initializeGL(); - void resizeGL(int w, int h); - void paintGL(); - -private: - //Index/vertex buffer data - GLuint m_uBeginIndex; - GLuint m_uEndIndex; - GLuint noOfIndices; - GLuint indexBuffer; - GLuint vertexBuffer; - - //Mouse data - QPoint m_LastFrameMousePos; - QPoint m_CurrentMousePos; - int m_xRotation; - int m_yRotation; -}; - -#endif //__BasicExample_OpenGLWidget_H__ diff --git a/examples/Paging/main.cpp b/examples/Paging/main.cpp index 77c64d16..bc4fa222 100644 --- a/examples/Paging/main.cpp +++ b/examples/Paging/main.cpp @@ -190,7 +190,7 @@ int main(int argc, char *argv[]) std::cout << "#vertices: " << mesh.getNoOfVertices() << std::endl; //Pass the surface to the OpenGL window - openGLWidget.setMeshToRender(mesh); + openGLWidget.addMesh(mesh); //Run the message pump. return app.exec(); From 349dc2b0e638b182d64289e0d8168bf543f2e226 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 25 May 2014 21:06:44 +0200 Subject: [PATCH 24/72] Centered volume in viewport. --- examples/Paging/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/Paging/main.cpp b/examples/Paging/main.cpp index bc4fa222..3700c632 100644 --- a/examples/Paging/main.cpp +++ b/examples/Paging/main.cpp @@ -192,6 +192,8 @@ int main(int argc, char *argv[]) //Pass the surface to the OpenGL window openGLWidget.addMesh(mesh); + openGLWidget.setViewableRegion(reg); + //Run the message pump. return app.exec(); } From 6738c4fc9e9c5979b4a43b01738687422b0aaecf Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 25 May 2014 21:15:20 +0200 Subject: [PATCH 25/72] Smooth example now also uses new example OpenGLWidget. --- examples/SmoothLOD/CMakeLists.txt | 2 +- examples/SmoothLOD/OpenGLWidget.cpp | 195 ---------------------------- examples/SmoothLOD/OpenGLWidget.h | 74 ----------- examples/SmoothLOD/main.cpp | 6 +- 4 files changed, 5 insertions(+), 272 deletions(-) delete mode 100644 examples/SmoothLOD/OpenGLWidget.cpp delete mode 100644 examples/SmoothLOD/OpenGLWidget.h diff --git a/examples/SmoothLOD/CMakeLists.txt b/examples/SmoothLOD/CMakeLists.txt index 570cda55..55c9e934 100644 --- a/examples/SmoothLOD/CMakeLists.txt +++ b/examples/SmoothLOD/CMakeLists.txt @@ -26,7 +26,7 @@ PROJECT(SmoothLODExample) #Projects source files SET(SRC_FILES main.cpp - OpenGLWidget.cpp + ../common/OpenGLWidget.cpp ) #Projects headers files diff --git a/examples/SmoothLOD/OpenGLWidget.cpp b/examples/SmoothLOD/OpenGLWidget.cpp deleted file mode 100644 index d487f73b..00000000 --- a/examples/SmoothLOD/OpenGLWidget.cpp +++ /dev/null @@ -1,195 +0,0 @@ -#include "OpenGLWidget.h" - -#include - -using namespace PolyVox; -using namespace std; - -OpenGLWidget::OpenGLWidget(QWidget *parent) - :QGLWidget(parent) - ,m_uBeginIndex(0) - ,m_uEndIndex(0) - ,indexBuffer(0) - ,vertexBuffer(0) - - ,m_uBeginIndexLow(0) - ,m_uEndIndexLow(0) - ,indexBufferLow(0) - ,vertexBufferLow(0) - ,m_xRotation(0) - ,m_yRotation(0) -{ -} - -void OpenGLWidget::setMeshToRender(const PolyVox::Mesh >& surfaceMesh) -{ - //Convienient access to the vertices and indices - const vector& vecIndices = surfaceMesh.getIndices(); - const vector >& vecVertices = surfaceMesh.getVertices(); - - //Build an OpenGL index buffer - glGenBuffers(1, &indexBuffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); - const GLvoid* pIndices = static_cast(&(vecIndices[0])); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), pIndices, GL_STATIC_DRAW); - - //Build an OpenGL vertex buffer - glGenBuffers(1, &vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); - const GLvoid* pVertices = static_cast(&(vecVertices[0])); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(MarchingCubesVertex), pVertices, GL_STATIC_DRAW); - - m_uBeginIndex = 0; - m_uEndIndex = vecIndices.size(); -} - -void OpenGLWidget::setMeshToRenderLowLOD(const PolyVox::Mesh >& surfaceMesh) -{ - //Convienient access to the vertices and indices - const vector& vecIndices = surfaceMesh.getIndices(); - const vector >& vecVertices = surfaceMesh.getVertices(); - - //Build an OpenGL index buffer - glGenBuffers(1, &indexBufferLow); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferLow); - const GLvoid* pIndices = static_cast(&(vecIndices[0])); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), pIndices, GL_STATIC_DRAW); - - //Build an OpenGL vertex buffer - glGenBuffers(1, &vertexBufferLow); - glBindBuffer(GL_ARRAY_BUFFER, vertexBufferLow); - const GLvoid* pVertices = static_cast(&(vecVertices[0])); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(MarchingCubesVertex), pVertices, GL_STATIC_DRAW); - - m_uBeginIndexLow = 0; - m_uEndIndexLow = vecIndices.size(); -} - -void OpenGLWidget::initializeGL() -{ - //We need GLEW to access recent OpenGL functionality - std::cout << "Initialising GLEW..."; - GLenum result = glewInit(); - if (result == GLEW_OK) - { - std::cout << "success" << std::endl; - } - else - { - /* Problem: glewInit failed, something is seriously wrong. */ - std::cout << "failed" << std::endl; - std::cout << "Initialising GLEW failed with the following error: " << glewGetErrorString(result) << std::endl; - exit(EXIT_FAILURE); - } - - //Print out some information about the OpenGL implementation. - std::cout << "OpenGL Implementation Details:" << std::endl; - if(glGetString(GL_VENDOR)) - std::cout << "\tGL_VENDOR: " << glGetString(GL_VENDOR) << std::endl; - if(glGetString(GL_RENDERER)) - std::cout << "\tGL_RENDERER: " << glGetString(GL_RENDERER) << std::endl; - if(glGetString(GL_VERSION)) - std::cout << "\tGL_VERSION: " << glGetString(GL_VERSION) << std::endl; - if(glGetString(GL_SHADING_LANGUAGE_VERSION)) - std::cout << "\tGL_SHADING_LANGUAGE_VERSION: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl; - - //Check our version of OpenGL is recent enough. - //We need at least 1.5 for vertex buffer objects, - if (!GLEW_VERSION_1_5) - { - std::cout << "Error: You need OpenGL version 1.5 to run this example." << std::endl; - exit(EXIT_FAILURE); - } - - //Set up the clear colour - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClearDepth(1.0f); - - //Enable the depth buffer - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - - //Anable smooth lighting - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - glShadeModel(GL_SMOOTH); - - //We'll be rendering with index/vertex arrays - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - - glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); -} - -void OpenGLWidget::resizeGL(int w, int h) -{ - //Setup the viewport - glViewport(0, 0, w, h); - - //Set up the projection matrix - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - float frustumSize = 32.0f; //Half the volume size - float aspect = static_cast(width()) / static_cast(height()); - glOrtho(frustumSize*aspect, -frustumSize*aspect, frustumSize, -frustumSize, 1.0, 1000); -} - -void OpenGLWidget::paintGL() -{ - //Clear the screen - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - //Set up the viewing transformation - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.0f,0.0f,-100.0f); //Centre volume and move back - glRotatef(-m_xRotation, 0.0f, 1.0f, 0.0f); - glRotatef(-m_yRotation, 1.0f, 0.0f, 0.0f); - glTranslatef(-32.0f,-32.0f,-32.0f); //Centre volume and move back - - //Bind the index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); - - //Bind the vertex buffer - glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); - glVertexPointer(3, GL_FLOAT, sizeof(MarchingCubesVertex), 0); - glNormalPointer(GL_FLOAT, sizeof(MarchingCubesVertex), (GLvoid*)12); - - glDrawRangeElements(GL_TRIANGLES, m_uBeginIndex, m_uEndIndex-1, m_uEndIndex - m_uBeginIndex, GL_UNSIGNED_INT, 0); - - //Bind the index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferLow); - - //Bind the vertex buffer - glBindBuffer(GL_ARRAY_BUFFER, vertexBufferLow); - glVertexPointer(3, GL_FLOAT, sizeof(MarchingCubesVertex), 0); - glNormalPointer(GL_FLOAT, sizeof(MarchingCubesVertex), (GLvoid*)12); - - glDrawRangeElements(GL_TRIANGLES, m_uBeginIndexLow, m_uEndIndexLow-1, m_uEndIndexLow - m_uBeginIndexLow, GL_UNSIGNED_INT, 0); - - GLenum errCode = glGetError(); - if(errCode != GL_NO_ERROR) - { - //What has replaced getErrorString() in the latest OpenGL? - std::cout << "OpenGL Error: " << errCode << std::endl; - } -} - -void OpenGLWidget::mousePressEvent(QMouseEvent* event) -{ - m_CurrentMousePos = event->pos(); - m_LastFrameMousePos = m_CurrentMousePos; - - update(); -} - -void OpenGLWidget::mouseMoveEvent(QMouseEvent* event) -{ - m_CurrentMousePos = event->pos(); - QPoint diff = m_CurrentMousePos - m_LastFrameMousePos; - m_xRotation += diff.x(); - m_yRotation += diff.y(); - m_LastFrameMousePos = m_CurrentMousePos; - - update(); -} diff --git a/examples/SmoothLOD/OpenGLWidget.h b/examples/SmoothLOD/OpenGLWidget.h deleted file mode 100644 index af5b96ee..00000000 --- a/examples/SmoothLOD/OpenGLWidget.h +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software -in a product, an acknowledgment in the product documentation would be -appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*******************************************************************************/ - -#ifndef __BasicExample_OpenGLWidget_H__ -#define __BasicExample_OpenGLWidget_H__ - -#include "PolyVoxCore/Mesh.h" - -#include "glew/glew.h" - -#include - -class OpenGLWidget : public QGLWidget -{ -public: - //Constructor - OpenGLWidget(QWidget *parent); - - //Mouse handling - void mouseMoveEvent(QMouseEvent* event); - void mousePressEvent(QMouseEvent* event); - - //Convert a SrfaceMesh to OpenGL index/vertex buffers - void setMeshToRender(const PolyVox::Mesh >& surfaceMesh); - void setMeshToRenderLowLOD(const PolyVox::Mesh >& surfaceMesh); - -protected: - //Qt OpenGL functions - void initializeGL(); - void resizeGL(int w, int h); - void paintGL(); - -private: - //Index/vertex buffer data - GLuint m_uBeginIndex; - GLuint m_uEndIndex; - //GLuint noOfIndices; - GLuint indexBuffer; - GLuint vertexBuffer; - - GLuint m_uBeginIndexLow; - GLuint m_uEndIndexLow; - //GLuint noOfIndicesLow; - GLuint indexBufferLow; - GLuint vertexBufferLow; - - //Mouse data - QPoint m_LastFrameMousePos; - QPoint m_CurrentMousePos; - int m_xRotation; - int m_yRotation; -}; - -#endif //__BasicExample_OpenGLWidget_H__ diff --git a/examples/SmoothLOD/main.cpp b/examples/SmoothLOD/main.cpp index a0dc6dcd..e38dff25 100644 --- a/examples/SmoothLOD/main.cpp +++ b/examples/SmoothLOD/main.cpp @@ -98,8 +98,10 @@ int main(int argc, char *argv[]) meshHighLOD.translateVertices(Vector3DFloat(30, 0, 0)); //Pass the surface to the OpenGL window - openGLWidget.setMeshToRender(meshHighLOD); - openGLWidget.setMeshToRenderLowLOD(meshLowLOD); + openGLWidget.addMesh(meshHighLOD); + openGLWidget.addMesh(meshLowLOD); + + openGLWidget.setViewableRegion(volData.getEnclosingRegion()); //Run the message pump. return app.exec(); From b63a09cab34113f42fb172826ad5fd3510f0c584 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 25 May 2014 21:29:44 +0200 Subject: [PATCH 26/72] Changing the way the examples handle translation and scaling. --- examples/OpenGL/main.cpp | 2 +- examples/common/OpenGLWidget.h | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index 4f0c0f2f..3e5c5785 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -192,7 +192,7 @@ int main(int argc, char *argv[]) auto mesh = extractMarchingCubesMesh(&volData, regToExtract); //Pass the surface to the OpenGL window - openGLWidget.addMesh(mesh); + openGLWidget.addMesh(mesh, Vector3DInt32(x, y, z)); meshCounter++; } diff --git a/examples/common/OpenGLWidget.h b/examples/common/OpenGLWidget.h index a1c1c37c..fe13a23a 100644 --- a/examples/common/OpenGLWidget.h +++ b/examples/common/OpenGLWidget.h @@ -38,6 +38,7 @@ struct OpenGLMeshData GLuint vertexBuffer; GLuint vertexArrayObject; PolyVox::Vector3DInt32 translation; + float scale; }; class OpenGLWidget : public QGLWidget @@ -60,7 +61,7 @@ public: // Convert a SurfaceMesh to OpenGL index/vertex buffers. Inlined because it's templatised. template - void addMesh(const MeshType& surfaceMesh) + void addMesh(const MeshType& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f) { //Convienient access to the vertices and indices const auto& vecIndices = surfaceMesh.getIndices(); @@ -99,7 +100,8 @@ public: meshData.noOfIndices = vecIndices.size(); //Save this for the call to glDrawElements later - meshData.translation = surfaceMesh.m_Region.getLowerCorner(); + meshData.translation = translation; + meshData.scale = scale; mMeshData.push_back(meshData); } From 22869e48611dffc91a11f259e4c223c8d97a4b62 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 25 May 2014 21:36:41 +0200 Subject: [PATCH 27/72] More tweaks to scaling and translation. --- examples/SmoothLOD/main.cpp | 6 ++---- examples/common/OpenGLWidget.cpp | 5 +++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/examples/SmoothLOD/main.cpp b/examples/SmoothLOD/main.cpp index e38dff25..60b35c98 100644 --- a/examples/SmoothLOD/main.cpp +++ b/examples/SmoothLOD/main.cpp @@ -91,15 +91,13 @@ int main(int argc, char *argv[]) //Extract the surface auto meshLowLOD = extractMarchingCubesMesh(&volDataLowLOD, volDataLowLOD.getEnclosingRegion()); - meshLowLOD.scaleVertices(/*2.0f*/63.0f / 31.0f); //Extract the surface auto meshHighLOD = extractMarchingCubesMesh(&volData, PolyVox::Region(Vector3DInt32(30, 0, 0), Vector3DInt32(63, 63, 63))); - meshHighLOD.translateVertices(Vector3DFloat(30, 0, 0)); //Pass the surface to the OpenGL window - openGLWidget.addMesh(meshHighLOD); - openGLWidget.addMesh(meshLowLOD); + openGLWidget.addMesh(meshHighLOD, Vector3DInt32(30, 0, 0)); + openGLWidget.addMesh(meshLowLOD, Vector3DInt32(0, 0, 0), 63.0f / 31.0f); openGLWidget.setViewableRegion(volData.getEnclosingRegion()); diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index 1777ba54..c561d537 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -136,8 +136,9 @@ void OpenGLWidget::paintGL() for (OpenGLMeshData meshData : mMeshData) { QMatrix4x4 modelToWorldMatrix{}; - modelToWorldMatrix.translate(meshData.translation.getX(), meshData.translation.getY(), meshData.translation.getZ()); // Centre the model on the origin - shader->setUniformValue("modelToWorldMatrix", modelToWorldMatrix); // Update to the latest camera matrix + modelToWorldMatrix.translate(meshData.translation.getX(), meshData.translation.getY(), meshData.translation.getZ()); + modelToWorldMatrix.scale(meshData.scale); + shader->setUniformValue("modelToWorldMatrix", modelToWorldMatrix); glBindVertexArray(meshData.vertexArrayObject); From 499db6a1852f16cc53c89cd5ce74cf2c5d93269b Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 25 May 2014 21:43:37 +0200 Subject: [PATCH 28/72] Changed default shader to use normal as RGB (more useful for debugging). --- examples/common/OpenGLWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index c561d537..587ef1c5 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -89,7 +89,7 @@ void OpenGLWidget::initializeGL() vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz))); float color = clamp(abs(dot(normalize(normal.xyz), vec3(0.9,0.1,0.5))), 0, 1); - outputColor = vec4(1.0, 0.5, color, 1.0); + outputColor = vec4(abs(normal) * 0.5 + vec3(0.5, 0.5, 0.5), 1.0); } )")) { From ec08b28002bdfe40dd29fa80df7e6899c39acb3d Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 25 May 2014 21:45:28 +0200 Subject: [PATCH 29/72] Turned off back-face culling in examples, as this makes it easier to view certain shapes such as heightmaps. --- examples/common/OpenGLWidget.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index 587ef1c5..76bdff47 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -45,7 +45,6 @@ void OpenGLWidget::initializeGL() glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0f); - glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glDepthFunc(GL_LEQUAL); From b97bf5221494f7c9e2ec68e84cdfa61874eb0efa Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 25 May 2014 23:34:12 +0200 Subject: [PATCH 30/72] Tidying up. --- examples/OpenGL/main.cpp | 1 - examples/common/OpenGLWidget.cpp | 2 +- examples/common/OpenGLWidget.h | 14 ++++++++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index 3e5c5785..586b5197 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -173,7 +173,6 @@ int main(int argc, char *argv[]) cout << endl << "Time taken = " << time.elapsed() / 1000.0f << "s" << endl << endl; const int32_t extractedRegionSize = 32; - const int32_t gapBetweenRegions = 1; // Set this to '1' int meshCounter = 0; for (int32_t z = 0; z < volData.getDepth(); z += extractedRegionSize) diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index 76bdff47..380c6fe0 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -135,7 +135,7 @@ void OpenGLWidget::paintGL() for (OpenGLMeshData meshData : mMeshData) { QMatrix4x4 modelToWorldMatrix{}; - modelToWorldMatrix.translate(meshData.translation.getX(), meshData.translation.getY(), meshData.translation.getZ()); + modelToWorldMatrix.translate(meshData.translation); modelToWorldMatrix.scale(meshData.scale); shader->setUniformValue("modelToWorldMatrix", modelToWorldMatrix); diff --git a/examples/common/OpenGLWidget.h b/examples/common/OpenGLWidget.h index fe13a23a..755563fa 100644 --- a/examples/common/OpenGLWidget.h +++ b/examples/common/OpenGLWidget.h @@ -31,16 +31,21 @@ distribution. #include #include +// This structure holds all the data required +// to render one of our meshes through OpenGL. struct OpenGLMeshData { GLuint noOfIndices; GLuint indexBuffer; GLuint vertexBuffer; GLuint vertexArrayObject; - PolyVox::Vector3DInt32 translation; + QVector3D translation; float scale; }; +// Our OpenGLWidget is used by all the examples to render the extracted meshes. It is +// fairly specific to our needs (you probably won't want to use it in your own project) +// but should provide a useful illustration of how PolyVox meshes can be rendered. class OpenGLWidget : public QGLWidget { public: @@ -51,9 +56,11 @@ public: void mouseMoveEvent(QMouseEvent* event); void mousePressEvent(QMouseEvent* event); - // The viewable region can be adjusted so that this example framework can be use for different volume sizes. + // The viewable region can be adjusted so that this example framework can be used for different volume sizes. void setViewableRegion(PolyVox::Region viewableRegion); + // For our purposes we use a single shader for the whole volume, and + // this example framework is only meant to show a single volume at a time void setShader(QGLShaderProgram* shader) { this->shader = shader; @@ -100,14 +107,13 @@ public: meshData.noOfIndices = vecIndices.size(); //Save this for the call to glDrawElements later - meshData.translation = translation; + meshData.translation = QVector3D(translation.getX(), translation.getY(), translation.getZ()); meshData.scale = scale; mMeshData.push_back(meshData); } protected: - // Qt OpenGL functions void initializeGL(); From 9e835a1110889fdd9cc44176bdc8e77e1cf7e276 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 25 May 2014 23:40:55 +0200 Subject: [PATCH 31/72] Shader now passed by shared pointer. --- examples/OpenGL/main.cpp | 2 +- examples/common/OpenGLWidget.cpp | 35 ++++++++++++++++++-------------- examples/common/OpenGLWidget.h | 7 ++----- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index 586b5197..6ef88601 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -88,7 +88,7 @@ int main(int argc, char *argv[]) openGLWidget.show(); - QGLShaderProgram* shader = new QGLShaderProgram; + QSharedPointer shader(new QGLShaderProgram); if (!shader->addShaderFromSourceCode(QGLShader::Vertex, R"( #version 140 diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index 380c6fe0..15f16852 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -21,6 +21,11 @@ void OpenGLWidget::setViewableRegion(Region viewableRegion) setupWorldToCameraMatrix(); } +void OpenGLWidget::setShader(QSharedPointer shader) +{ + mShader = shader; +} + void OpenGLWidget::initializeGL() { GLenum err = glewInit(); @@ -50,9 +55,9 @@ void OpenGLWidget::initializeGL() glDepthFunc(GL_LEQUAL); glDepthRange(0.0, 1.0); - shader = new QGLShaderProgram; + mShader = QSharedPointer(new QGLShaderProgram); - if (!shader->addShaderFromSourceCode(QGLShader::Vertex, R"( + if (!mShader->addShaderFromSourceCode(QGLShader::Vertex, R"( #version 140 in vec4 position; // This will be the position of the vertex in model-space @@ -71,11 +76,11 @@ void OpenGLWidget::initializeGL() } )")) { - std::cerr << shader->log().toStdString() << std::endl; + std::cerr << mShader->log().toStdString() << std::endl; exit(EXIT_FAILURE); } - if (!shader->addShaderFromSourceCode(QGLShader::Fragment, R"( + if (!mShader->addShaderFromSourceCode(QGLShader::Fragment, R"( #version 130 in vec4 worldPosition; //Passed in from the vertex shader @@ -92,17 +97,17 @@ void OpenGLWidget::initializeGL() } )")) { - std::cerr << shader->log().toStdString() << std::endl; + std::cerr << mShader->log().toStdString() << std::endl; exit(EXIT_FAILURE); } - shader->bindAttributeLocation("position", 0); - shader->bindAttributeLocation("normal", 1); - shader->bindAttributeLocation("material", 2); + mShader->bindAttributeLocation("position", 0); + mShader->bindAttributeLocation("normal", 1); + mShader->bindAttributeLocation("material", 2); - if (!shader->link()) + if (!mShader->link()) { - std::cerr << shader->log().toStdString() << std::endl; + std::cerr << mShader->log().toStdString() << std::endl; exit(EXIT_FAILURE); } @@ -127,17 +132,17 @@ void OpenGLWidget::paintGL() //Clear the screen glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - shader->bind(); + mShader->bind(); - shader->setUniformValue("worldToCameraMatrix", worldToCameraMatrix); - shader->setUniformValue("cameraToClipMatrix", cameraToClipMatrix); + mShader->setUniformValue("worldToCameraMatrix", worldToCameraMatrix); + mShader->setUniformValue("cameraToClipMatrix", cameraToClipMatrix); for (OpenGLMeshData meshData : mMeshData) { QMatrix4x4 modelToWorldMatrix{}; modelToWorldMatrix.translate(meshData.translation); modelToWorldMatrix.scale(meshData.scale); - shader->setUniformValue("modelToWorldMatrix", modelToWorldMatrix); + mShader->setUniformValue("modelToWorldMatrix", modelToWorldMatrix); glBindVertexArray(meshData.vertexArrayObject); @@ -146,7 +151,7 @@ void OpenGLWidget::paintGL() glBindVertexArray(0); } - shader->release(); + mShader->release(); GLenum errCode = glGetError(); if(errCode != GL_NO_ERROR) diff --git a/examples/common/OpenGLWidget.h b/examples/common/OpenGLWidget.h index 755563fa..a56ed7f1 100644 --- a/examples/common/OpenGLWidget.h +++ b/examples/common/OpenGLWidget.h @@ -61,10 +61,7 @@ public: // For our purposes we use a single shader for the whole volume, and // this example framework is only meant to show a single volume at a time - void setShader(QGLShaderProgram* shader) - { - this->shader = shader; - } + void setShader(QSharedPointer shader); // Convert a SurfaceMesh to OpenGL index/vertex buffers. Inlined because it's templatised. template @@ -127,7 +124,7 @@ private: // Index/vertex buffer data std::vector mMeshData; - QGLShaderProgram* shader; + QSharedPointer mShader; // Matrices QMatrix4x4 worldToCameraMatrix; From 2a072f93478ed12c0bae4d8df7852d3362f18646 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 25 May 2014 23:44:37 +0200 Subject: [PATCH 32/72] Rearranged some functions. --- examples/common/OpenGLWidget.cpp | 55 +++++++++++++++++++------------- examples/common/OpenGLWidget.h | 22 ++++++------- 2 files changed, 43 insertions(+), 34 deletions(-) diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index 15f16852..a83fa70d 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -7,6 +7,9 @@ using namespace PolyVox; using namespace std; +//////////////////////////////////////////////////////////////////////////////// +// Public functions +//////////////////////////////////////////////////////////////////////////////// OpenGLWidget::OpenGLWidget(QWidget *parent) :QGLWidget(parent) ,m_viewableRegion(Region(0, 0, 0, 255, 255, 255)) @@ -15,17 +18,41 @@ OpenGLWidget::OpenGLWidget(QWidget *parent) { } +void OpenGLWidget::setShader(QSharedPointer shader) +{ + mShader = shader; +} + void OpenGLWidget::setViewableRegion(Region viewableRegion) { m_viewableRegion = viewableRegion; setupWorldToCameraMatrix(); } -void OpenGLWidget::setShader(QSharedPointer shader) +void OpenGLWidget::mousePressEvent(QMouseEvent* event) { - mShader = shader; + m_CurrentMousePos = event->pos(); + m_LastFrameMousePos = m_CurrentMousePos; + + update(); } +void OpenGLWidget::mouseMoveEvent(QMouseEvent* event) +{ + m_CurrentMousePos = event->pos(); + QPoint diff = m_CurrentMousePos - m_LastFrameMousePos; + m_xRotation += diff.x(); + m_yRotation += diff.y(); + m_LastFrameMousePos = m_CurrentMousePos; + + setupWorldToCameraMatrix(); + + update(); +} + +//////////////////////////////////////////////////////////////////////////////// +// Protected functions +//////////////////////////////////////////////////////////////////////////////// void OpenGLWidget::initializeGL() { GLenum err = glewInit(); @@ -160,27 +187,9 @@ void OpenGLWidget::paintGL() } } -void OpenGLWidget::mousePressEvent(QMouseEvent* event) -{ - m_CurrentMousePos = event->pos(); - m_LastFrameMousePos = m_CurrentMousePos; - - update(); -} - -void OpenGLWidget::mouseMoveEvent(QMouseEvent* event) -{ - m_CurrentMousePos = event->pos(); - QPoint diff = m_CurrentMousePos - m_LastFrameMousePos; - m_xRotation += diff.x(); - m_yRotation += diff.y(); - m_LastFrameMousePos = m_CurrentMousePos; - - setupWorldToCameraMatrix(); - - update(); -} - +//////////////////////////////////////////////////////////////////////////////// +// Private functions +//////////////////////////////////////////////////////////////////////////////// void OpenGLWidget::setupWorldToCameraMatrix() { QVector3D lowerCorner(m_viewableRegion.getLowerX(), m_viewableRegion.getLowerY(), m_viewableRegion.getLowerZ()); diff --git a/examples/common/OpenGLWidget.h b/examples/common/OpenGLWidget.h index a56ed7f1..af660909 100644 --- a/examples/common/OpenGLWidget.h +++ b/examples/common/OpenGLWidget.h @@ -52,17 +52,6 @@ public: // Constructor OpenGLWidget(QWidget *parent); - // Mouse handling - void mouseMoveEvent(QMouseEvent* event); - void mousePressEvent(QMouseEvent* event); - - // The viewable region can be adjusted so that this example framework can be used for different volume sizes. - void setViewableRegion(PolyVox::Region viewableRegion); - - // For our purposes we use a single shader for the whole volume, and - // this example framework is only meant to show a single volume at a time - void setShader(QSharedPointer shader); - // Convert a SurfaceMesh to OpenGL index/vertex buffers. Inlined because it's templatised. template void addMesh(const MeshType& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f) @@ -110,6 +99,17 @@ public: mMeshData.push_back(meshData); } + // For our purposes we use a single shader for the whole volume, and + // this example framework is only meant to show a single volume at a time + void setShader(QSharedPointer shader); + + // The viewable region can be adjusted so that this example framework can be used for different volume sizes. + void setViewableRegion(PolyVox::Region viewableRegion); + + // Mouse handling + void mouseMoveEvent(QMouseEvent* event); + void mousePressEvent(QMouseEvent* event); + protected: // Qt OpenGL functions From e9c8daa9cb0131539005bf1c854b86a6c303d86c Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 26 May 2014 16:31:12 +0200 Subject: [PATCH 33/72] Add comments and tidying. --- examples/common/OpenGLWidget.cpp | 9 +++++++-- examples/common/OpenGLWidget.h | 30 +++++++++++++++++++----------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index a83fa70d..f26c2237 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -26,27 +26,32 @@ void OpenGLWidget::setShader(QSharedPointer shader) void OpenGLWidget::setViewableRegion(Region viewableRegion) { m_viewableRegion = viewableRegion; + + // The user has specifed a new viewable region + // so we need to regenerate our camera matrix. setupWorldToCameraMatrix(); } void OpenGLWidget::mousePressEvent(QMouseEvent* event) { + // Initialise these variables which will be used when the mouse actually moves. m_CurrentMousePos = event->pos(); m_LastFrameMousePos = m_CurrentMousePos; - - update(); } void OpenGLWidget::mouseMoveEvent(QMouseEvent* event) { + // Update the x and y rotations based on the mouse movement. m_CurrentMousePos = event->pos(); QPoint diff = m_CurrentMousePos - m_LastFrameMousePos; m_xRotation += diff.x(); m_yRotation += diff.y(); m_LastFrameMousePos = m_CurrentMousePos; + // The camera rotation has changed so we need to regenerate the matrix. setupWorldToCameraMatrix(); + // Re-render. update(); } diff --git a/examples/common/OpenGLWidget.h b/examples/common/OpenGLWidget.h index af660909..d87b4161 100644 --- a/examples/common/OpenGLWidget.h +++ b/examples/common/OpenGLWidget.h @@ -52,11 +52,11 @@ public: // Constructor OpenGLWidget(QWidget *parent); - // Convert a SurfaceMesh to OpenGL index/vertex buffers. Inlined because it's templatised. + // Convert a PolyVox mesh to OpenGL index/vertex buffers. Inlined because it's templatised. template void addMesh(const MeshType& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f) { - //Convienient access to the vertices and indices + // Convienient access to the vertices and indices const auto& vecIndices = surfaceMesh.getIndices(); const auto& vecVertices = surfaceMesh.getVertices(); @@ -64,38 +64,46 @@ public: // to render our mesh. We copy the data from the PolyVox mesh into this structure. OpenGLMeshData meshData; - //Create the VAO for the mesh + // Create the VAO for the mesh glGenVertexArrays(1, &(meshData.vertexArrayObject)); glBindVertexArray(meshData.vertexArrayObject); - //The GL_ARRAY_BUFFER will contain the list of vertex positions + // The GL_ARRAY_BUFFER will contain the list of vertex positions glGenBuffers(1, &(meshData.vertexBuffer)); glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer); glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(MeshType::VertexType), vecVertices.data(), GL_STATIC_DRAW); - //and GL_ELEMENT_ARRAY_BUFFER will contain the indices + // and GL_ELEMENT_ARRAY_BUFFER will contain the indices glGenBuffers(1, &(meshData.indexBuffer)); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshData.indexBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), vecIndices.data(), GL_STATIC_DRAW); - //We need to tell OpenGL how to understand the format of the vertex data - glEnableVertexAttribArray(0); //We're talking about shader attribute '0' + // Every surface extractor outputs valid positions for the vertices, so tell OpenGL how these are laid out + glEnableVertexAttribArray(0); // Attrib '0' is the vertex positions glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(MeshType::VertexType), (GLvoid*)(offsetof(MeshType::VertexType, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) - glEnableVertexAttribArray(1); //We're talking about shader attribute '1' + // Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor + // does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the + // shader. This is mostly just to simplify this example code - in a real application you will know whether your + // chosen surface extractor generates normals and can skip uploading them if not. + glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals. glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(MeshType::VertexType), (GLvoid*)(offsetof(MeshType::VertexType, normal))); + // Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code + // we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here. glEnableVertexAttribArray(2); //We're talking about shader attribute '2' - GLint size = (std::min)(sizeof(MeshType::VertexType::VoxelType), size_t(4)); + GLint size = (std::min)(sizeof(MeshType::VertexType::VoxelType), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type) glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(MeshType::VertexType), (GLvoid*)(offsetof(MeshType::VertexType, material))); + // We're done uploading and can now unbind. glBindVertexArray(0); - meshData.noOfIndices = vecIndices.size(); //Save this for the call to glDrawElements later - + // A few additional properties can be copied across for use during rendering. + meshData.noOfIndices = vecIndices.size(); meshData.translation = QVector3D(translation.getX(), translation.getY(), translation.getZ()); meshData.scale = scale; + // Now add the mesh to the list of meshes to render. mMeshData.push_back(meshData); } From 4ae25d6b1e961f83fd280eb04982c47a0fd79e26 Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 26 May 2014 16:50:13 +0200 Subject: [PATCH 34/72] More commenting. --- examples/common/OpenGLWidget.cpp | 35 +++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index f26c2237..e0ea7de4 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -89,19 +89,25 @@ void OpenGLWidget::initializeGL() mShader = QSharedPointer(new QGLShaderProgram); + // This is basically a simple fallback vertex shader which does the most basic rendering possible. + // PolyVox examples are able to provide their own shaders to demonstrate certain effects if desired. if (!mShader->addShaderFromSourceCode(QGLShader::Vertex, R"( #version 140 in vec4 position; // This will be the position of the vertex in model-space + // The usual matrices are provided uniform mat4 cameraToClipMatrix; uniform mat4 worldToCameraMatrix; uniform mat4 modelToWorldMatrix; - out vec4 worldPosition; //This is being passed to the fragment shader to calculate the normals + // This will be used by the fragment shader to calculate flat-shaded normals. This is an unconventional approach + // but we use it in this example framework because not all surface extractor generate surface normals. + out vec4 worldPosition; void main() { + // Standard sequence of OpenGL transformations. worldPosition = modelToWorldMatrix * position; vec4 cameraPosition = worldToCameraMatrix * worldPosition; gl_Position = cameraToClipMatrix * cameraPosition; @@ -112,19 +118,26 @@ void OpenGLWidget::initializeGL() exit(EXIT_FAILURE); } + // This is basically a simple fallback fragment shader which does the most basic rendering possible. + // PolyVox examples are able to provide their own shaders to demonstrate certain effects if desired. if (!mShader->addShaderFromSourceCode(QGLShader::Fragment, R"( #version 130 - in vec4 worldPosition; //Passed in from the vertex shader + // Passed in from the vertex shader + in vec4 worldPosition; in vec4 worldNormal; + // the color that gets written to the display out vec4 outputColor; void main() { + // Again, for the purposes of these examples we cannot be sure that per-vertex normals are provided. A sensible fallback + // is to use this little trick to compute per-fragment flat-shaded normals from the world positions using derivative operations. vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz))); - float color = clamp(abs(dot(normalize(normal.xyz), vec3(0.9,0.1,0.5))), 0, 1); + // We are just using the normal as the output color, and making it lighter so it looks a bit nicer. + // Obviously a real shader would also do texuring, lighting, or whatever is required for the application. outputColor = vec4(abs(normal) * 0.5 + vec3(0.5, 0.5, 0.5), 1.0); } )")) @@ -133,7 +146,11 @@ void OpenGLWidget::initializeGL() exit(EXIT_FAILURE); } + // Bind the position semantic - this is defined in the vertex shader above. mShader->bindAttributeLocation("position", 0); + + // Bind the other semantics. Note that these don't actually exist in our example shader above! However, other + // example shaders may choose to provide them and having the binding code here does not seem to cause any problems. mShader->bindAttributeLocation("normal", 1); mShader->bindAttributeLocation("material", 2); @@ -143,6 +160,7 @@ void OpenGLWidget::initializeGL() exit(EXIT_FAILURE); } + // Initial setup of camera. setupWorldToCameraMatrix(); } @@ -164,27 +182,34 @@ void OpenGLWidget::paintGL() //Clear the screen glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + // Our example framework only uses a single shader for the scene (for all meshes). mShader->bind(); + // These two matrices are constant for all meshes. mShader->setUniformValue("worldToCameraMatrix", worldToCameraMatrix); mShader->setUniformValue("cameraToClipMatrix", cameraToClipMatrix); + // Iterate over each mesh which the user added to our list, and render it. for (OpenGLMeshData meshData : mMeshData) { + //Set up the model matrrix based on provided translation and scale. QMatrix4x4 modelToWorldMatrix{}; modelToWorldMatrix.translate(meshData.translation); modelToWorldMatrix.scale(meshData.scale); mShader->setUniformValue("modelToWorldMatrix", modelToWorldMatrix); + // Bind the vertex array for the current mesh glBindVertexArray(meshData.vertexArrayObject); - + // Draw the mesh glDrawElements(GL_TRIANGLES, meshData.noOfIndices, GL_UNSIGNED_INT, 0); - + // Unbind the vertex array. glBindVertexArray(0); } + // We're done with the shader for this frame. mShader->release(); + // Check for errors. GLenum errCode = glGetError(); if(errCode != GL_NO_ERROR) { From 40e528d782f2e4a5f25f7d47576c949c50edd756 Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 26 May 2014 17:00:26 +0200 Subject: [PATCH 35/72] Added lighting to OpenGL example. --- examples/OpenGL/main.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index 6ef88601..23736a0a 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -130,34 +130,38 @@ int main(int argc, char *argv[]) void main() { - //vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz))); - vec3 normal = worldNormal.xyz; + vec4 surfaceColor = vec4(0.0, 0.0, 0.0, 0.0); switch(outMaterial.x) { case 1: - outputColor = vec4(1.0, 0.0, 0.0, 1.0); + surfaceColor = vec4(1.0, 0.0, 0.0, 1.0); break; case 2: - outputColor = vec4(0.0, 1.0, 0.0, 1.0); + surfaceColor = vec4(0.0, 1.0, 0.0, 1.0); break; case 3: - outputColor = vec4(0.0, 0.0, 1.0, 1.0); + surfaceColor = vec4(0.0, 0.0, 1.0, 1.0); break; case 4: - outputColor = vec4(1.0, 1.0, 0.0, 1.0); + surfaceColor = vec4(1.0, 1.0, 0.0, 1.0); break; case 5: - outputColor = vec4(1.0, 0.0, 1.0, 1.0); + surfaceColor = vec4(1.0, 0.0, 1.0, 1.0); break; default: - outputColor = vec4(1.0, 1.0, 1.0, 1.0); + surfaceColor = vec4(1.0, 1.0, 1.0, 1.0); break; } - - //float color = clamp(abs(dot(normalize(normal.xyz), vec3(0.9,0.1,0.5))), 0, 1); - //outputColor = vec4(1.0, 0.5, color, 1.0); + + vec3 lightDir = vec3(1.0, 0.0, 0.0); + float diffuse = dot(lightDir, normal); + diffuse *= 0.6; + float ambient = 0.4; + float lightVal = diffuse + ambient; + + outputColor = surfaceColor * lightVal; } )")) { From fd3879faebc784cda49387d191590446b580b445 Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 26 May 2014 21:10:07 +0200 Subject: [PATCH 36/72] Tidying OpenGLExample shader code. --- examples/OpenGL/main.cpp | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index 23736a0a..f57b661e 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -102,16 +102,17 @@ int main(int argc, char *argv[]) uniform mat4 modelToWorldMatrix; out vec4 worldPosition; //This is being passed to the fragment shader to calculate the normals - out vec4 worldNormal; + out vec3 normalFromVS; flat out ivec2 outMaterial; void main() { worldPosition = modelToWorldMatrix * position; - worldNormal = normal; - outMaterial = ivec2(material.x, material.y); vec4 cameraPosition = worldToCameraMatrix * worldPosition; gl_Position = cameraToClipMatrix * cameraPosition; + + normalFromVS = normal.xyz; + outMaterial = ivec2(material.x, material.y); } )")) { @@ -123,16 +124,16 @@ int main(int argc, char *argv[]) #version 130 in vec4 worldPosition; //Passed in from the vertex shader - in vec4 worldNormal; + in vec3 normalFromVS; flat in ivec2 outMaterial; out vec4 outputColor; void main() { - vec3 normal = worldNormal.xyz; - vec4 surfaceColor = vec4(0.0, 0.0, 0.0, 0.0); - + // The first byte of our voxel data is the material. + // We use this to decide how to color the fragment. + vec4 surfaceColor; switch(outMaterial.x) { case 1: @@ -155,13 +156,15 @@ int main(int argc, char *argv[]) break; } - vec3 lightDir = vec3(1.0, 0.0, 0.0); - float diffuse = dot(lightDir, normal); - diffuse *= 0.6; - float ambient = 0.4; - float lightVal = diffuse + ambient; + // Quick and dirty lighting, obviously a real implementation + // should pass light properties as shader parameters, etc. + vec3 lightDir = vec3(0.0, 0.0, 1.0); + float diffuse = clamp(dot(lightDir, normalFromVS), 0.0, 1.0); + diffuse *= 0.7; // Dim the diffuse a bit + float ambient = 0.3; // Add some ambient + float lightIntensity = diffuse + ambient; // Compute the final light intensity - outputColor = surfaceColor * lightVal; + outputColor = surfaceColor * lightIntensity; //Compute final rendered color } )")) { From 5a23299634ae9c01414f3ad87e16c711494fdc28 Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 26 May 2014 21:14:54 +0200 Subject: [PATCH 37/72] More tidying shader code. --- examples/OpenGL/main.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index f57b661e..7e2451e1 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -103,16 +103,19 @@ int main(int argc, char *argv[]) out vec4 worldPosition; //This is being passed to the fragment shader to calculate the normals out vec3 normalFromVS; - flat out ivec2 outMaterial; + flat out ivec2 materialFromVS; void main() { - worldPosition = modelToWorldMatrix * position; - vec4 cameraPosition = worldToCameraMatrix * worldPosition; - gl_Position = cameraToClipMatrix * cameraPosition; + // Compute the usual OpenGL transformation to clip space. + gl_Position = cameraToClipMatrix * worldToCameraMatrix * modelToWorldMatrix * position; + // This example is demonstrating the marching cubes mesh, which does have per-vertex normals. We can + // just pass them through, though real code might want to deal with transforming normals appropriatly. normalFromVS = normal.xyz; - outMaterial = ivec2(material.x, material.y); + + // Nothing special here, we just pass the material through to the fragment shader. + materialFromVS = material; } )")) { @@ -125,7 +128,7 @@ int main(int argc, char *argv[]) in vec4 worldPosition; //Passed in from the vertex shader in vec3 normalFromVS; - flat in ivec2 outMaterial; + flat in ivec2 materialFromVS; out vec4 outputColor; @@ -134,7 +137,7 @@ int main(int argc, char *argv[]) // The first byte of our voxel data is the material. // We use this to decide how to color the fragment. vec4 surfaceColor; - switch(outMaterial.x) + switch(materialFromVS.x) { case 1: surfaceColor = vec4(1.0, 0.0, 0.0, 1.0); From ba58cff8158fc45b0ac0a0abce88ce78f1b2c2fa Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 26 May 2014 22:51:09 +0200 Subject: [PATCH 38/72] Removed use of 'R' raw string literals as CS 2012 doesn't support them. --- examples/OpenGL/main.cpp | 128 +++++++++++++++---------------- examples/common/OpenGLWidget.cpp | 70 ++++++++--------- 2 files changed, 99 insertions(+), 99 deletions(-) diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index 7e2451e1..27b0ac6b 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -90,86 +90,86 @@ int main(int argc, char *argv[]) QSharedPointer shader(new QGLShaderProgram); - if (!shader->addShaderFromSourceCode(QGLShader::Vertex, R"( - #version 140 + if (!shader->addShaderFromSourceCode(QGLShader::Vertex, + "#version 140\n" - in vec4 position; // This will be the position of the vertex in model-space - in vec4 normal; // The normal data may not have been set - in ivec2 material; + "in vec4 position; // This will be the position of the vertex in model-space\n" + "in vec4 normal; // The normal data may not have been set\n" + "in ivec2 material;\n" - uniform mat4 cameraToClipMatrix; - uniform mat4 worldToCameraMatrix; - uniform mat4 modelToWorldMatrix; + "uniform mat4 cameraToClipMatrix;\n" + "uniform mat4 worldToCameraMatrix;\n" + "uniform mat4 modelToWorldMatrix;\n" - out vec4 worldPosition; //This is being passed to the fragment shader to calculate the normals - out vec3 normalFromVS; - flat out ivec2 materialFromVS; + "out vec4 worldPosition; //This is being passed to the fragment shader to calculate the normals\n" + "out vec3 normalFromVS;\n" + "flat out ivec2 materialFromVS;\n" - void main() - { - // Compute the usual OpenGL transformation to clip space. - gl_Position = cameraToClipMatrix * worldToCameraMatrix * modelToWorldMatrix * position; + "void main()\n" + "{\n" + " // Compute the usual OpenGL transformation to clip space.\n" + " gl_Position = cameraToClipMatrix * worldToCameraMatrix * modelToWorldMatrix * position;\n" - // This example is demonstrating the marching cubes mesh, which does have per-vertex normals. We can - // just pass them through, though real code might want to deal with transforming normals appropriatly. - normalFromVS = normal.xyz; + " // This example is demonstrating the marching cubes mesh, which does have per-vertex normals. We can \n" + " // just pass them through, though real code might want to deal with transforming normals appropriatly.\n" + " normalFromVS = normal.xyz;\n" - // Nothing special here, we just pass the material through to the fragment shader. - materialFromVS = material; - } - )")) + " // Nothing special here, we just pass the material through to the fragment shader.\n" + " materialFromVS = material;\n" + "}\n" + )) { std::cerr << shader->log().toStdString() << std::endl; exit(EXIT_FAILURE); } - if (!shader->addShaderFromSourceCode(QGLShader::Fragment, R"( - #version 130 + if (!shader->addShaderFromSourceCode(QGLShader::Fragment, + "#version 130\n" - in vec4 worldPosition; //Passed in from the vertex shader - in vec3 normalFromVS; - flat in ivec2 materialFromVS; + "in vec4 worldPosition; //Passed in from the vertex shader\n" + "in vec3 normalFromVS;\n" + "flat in ivec2 materialFromVS;\n" - out vec4 outputColor; + "out vec4 outputColor;\n" - void main() - { - // The first byte of our voxel data is the material. - // We use this to decide how to color the fragment. - vec4 surfaceColor; - switch(materialFromVS.x) - { - case 1: - surfaceColor = vec4(1.0, 0.0, 0.0, 1.0); - break; - case 2: - surfaceColor = vec4(0.0, 1.0, 0.0, 1.0); - break; - case 3: - surfaceColor = vec4(0.0, 0.0, 1.0, 1.0); - break; - case 4: - surfaceColor = vec4(1.0, 1.0, 0.0, 1.0); - break; - case 5: - surfaceColor = vec4(1.0, 0.0, 1.0, 1.0); - break; - default: - surfaceColor = vec4(1.0, 1.0, 1.0, 1.0); - break; - } + "void main()\n" + "{\n" + " // The first byte of our voxel data is the material.\n" + " // We use this to decide how to color the fragment.\n" + " vec4 surfaceColor;\n" + " switch(materialFromVS.x)\n" + " {\n" + " case 1:\n" + " surfaceColor = vec4(1.0, 0.0, 0.0, 1.0);\n" + " break;\n" + " case 2:\n" + " surfaceColor = vec4(0.0, 1.0, 0.0, 1.0);\n" + " break;\n" + " case 3:\n" + " surfaceColor = vec4(0.0, 0.0, 1.0, 1.0);\n" + " break;\n" + " case 4:\n" + " surfaceColor = vec4(1.0, 1.0, 0.0, 1.0);\n" + " break;\n" + " case 5:\n" + " surfaceColor = vec4(1.0, 0.0, 1.0, 1.0);\n" + " break;\n" + " default:\n" + " surfaceColor = vec4(1.0, 1.0, 1.0, 1.0);\n" + " break;\n" + " }\n" - // Quick and dirty lighting, obviously a real implementation - // should pass light properties as shader parameters, etc. - vec3 lightDir = vec3(0.0, 0.0, 1.0); - float diffuse = clamp(dot(lightDir, normalFromVS), 0.0, 1.0); - diffuse *= 0.7; // Dim the diffuse a bit - float ambient = 0.3; // Add some ambient - float lightIntensity = diffuse + ambient; // Compute the final light intensity + " // Quick and dirty lighting, obviously a real implementation\n" + " // should pass light properties as shader parameters, etc.\n" + " vec3 lightDir = vec3(0.0, 0.0, 1.0);\n" + " float diffuse = clamp(dot(lightDir, normalFromVS), 0.0, 1.0);\n" + " diffuse *= 0.7; // Dim the diffuse a bit\n" + " float ambient = 0.3; // Add some ambient\n" + " float lightIntensity = diffuse + ambient; // Compute the final light intensity\n" - outputColor = surfaceColor * lightIntensity; //Compute final rendered color - } - )")) + " outputColor = surfaceColor * lightIntensity; //Compute final rendered color\n" + "}\n" + )) { std::cerr << shader->log().toStdString() << std::endl; exit(EXIT_FAILURE); diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index e0ea7de4..96cbe1ce 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -91,28 +91,28 @@ void OpenGLWidget::initializeGL() // This is basically a simple fallback vertex shader which does the most basic rendering possible. // PolyVox examples are able to provide their own shaders to demonstrate certain effects if desired. - if (!mShader->addShaderFromSourceCode(QGLShader::Vertex, R"( - #version 140 + if (!mShader->addShaderFromSourceCode(QGLShader::Vertex, + "#version 140\n" - in vec4 position; // This will be the position of the vertex in model-space + "in vec4 position; // This will be the position of the vertex in model-space\n" - // The usual matrices are provided - uniform mat4 cameraToClipMatrix; - uniform mat4 worldToCameraMatrix; - uniform mat4 modelToWorldMatrix; + "// The usual matrices are provided\n" + "uniform mat4 cameraToClipMatrix;\n" + "uniform mat4 worldToCameraMatrix;\n" + "uniform mat4 modelToWorldMatrix;\n" - // This will be used by the fragment shader to calculate flat-shaded normals. This is an unconventional approach - // but we use it in this example framework because not all surface extractor generate surface normals. - out vec4 worldPosition; + "// This will be used by the fragment shader to calculate flat-shaded normals. This is an unconventional approach\n" + "// but we use it in this example framework because not all surface extractor generate surface normals.\n" + "out vec4 worldPosition;\n" - void main() - { - // Standard sequence of OpenGL transformations. - worldPosition = modelToWorldMatrix * position; - vec4 cameraPosition = worldToCameraMatrix * worldPosition; - gl_Position = cameraToClipMatrix * cameraPosition; - } - )")) + "void main()\n" + "{\n" + " // Standard sequence of OpenGL transformations.\n" + " worldPosition = modelToWorldMatrix * position;\n" + " vec4 cameraPosition = worldToCameraMatrix * worldPosition;\n" + " gl_Position = cameraToClipMatrix * cameraPosition;\n" + "}\n" + )) { std::cerr << mShader->log().toStdString() << std::endl; exit(EXIT_FAILURE); @@ -120,27 +120,27 @@ void OpenGLWidget::initializeGL() // This is basically a simple fallback fragment shader which does the most basic rendering possible. // PolyVox examples are able to provide their own shaders to demonstrate certain effects if desired. - if (!mShader->addShaderFromSourceCode(QGLShader::Fragment, R"( - #version 130 + if (!mShader->addShaderFromSourceCode(QGLShader::Fragment, + "#version 130\n" - // Passed in from the vertex shader - in vec4 worldPosition; - in vec4 worldNormal; + "// Passed in from the vertex shader\n" + "in vec4 worldPosition;\n" + "in vec4 worldNormal;\n" - // the color that gets written to the display - out vec4 outputColor; + "// the color that gets written to the display\n" + "out vec4 outputColor;\n" - void main() - { - // Again, for the purposes of these examples we cannot be sure that per-vertex normals are provided. A sensible fallback - // is to use this little trick to compute per-fragment flat-shaded normals from the world positions using derivative operations. - vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz))); + "void main()\n" + "{\n" + " // Again, for the purposes of these examples we cannot be sure that per-vertex normals are provided. A sensible fallback \n" + " // is to use this little trick to compute per-fragment flat-shaded normals from the world positions using derivative operations.\n" + " vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz)));\n" - // We are just using the normal as the output color, and making it lighter so it looks a bit nicer. - // Obviously a real shader would also do texuring, lighting, or whatever is required for the application. - outputColor = vec4(abs(normal) * 0.5 + vec3(0.5, 0.5, 0.5), 1.0); - } - )")) + " // We are just using the normal as the output color, and making it lighter so it looks a bit nicer. \n" + " // Obviously a real shader would also do texuring, lighting, or whatever is required for the application.\n" + " outputColor = vec4(abs(normal) * 0.5 + vec3(0.5, 0.5, 0.5), 1.0);\n" + "}\n" + )) { std::cerr << mShader->log().toStdString() << std::endl; exit(EXIT_FAILURE); From 321d3eb7d4d0c1dc6c6bf060a4767afa2fa06e17 Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 26 May 2014 22:51:55 +0200 Subject: [PATCH 39/72] Removed initializer which isn't supported in VS 2012. --- examples/common/OpenGLWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index 96cbe1ce..ddc314eb 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -193,7 +193,7 @@ void OpenGLWidget::paintGL() for (OpenGLMeshData meshData : mMeshData) { //Set up the model matrrix based on provided translation and scale. - QMatrix4x4 modelToWorldMatrix{}; + QMatrix4x4 modelToWorldMatrix; modelToWorldMatrix.translate(meshData.translation); modelToWorldMatrix.scale(meshData.scale); mShader->setUniformValue("modelToWorldMatrix", modelToWorldMatrix); From 1d8fc25cb752d1a250c50dc794ffe9eff03ed932 Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 26 May 2014 23:14:29 +0200 Subject: [PATCH 40/72] Compile fixes for GCC/Linux --- examples/OpenGL/main.cpp | 2 +- examples/common/OpenGLWidget.cpp | 4 ++-- examples/common/OpenGLWidget.h | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index 27b0ac6b..c339fa0b 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -192,7 +192,7 @@ int main(int argc, char *argv[]) for (int32_t x = 0; x < volData.getWidth(); x += extractedRegionSize) { // Specify the region to extract based on a starting position and the desired region sze. - Region regToExtract(x, y, z, x + extractedRegionSize, y + extractedRegionSize, z + extractedRegionSize); + PolyVox::Region regToExtract(x, y, z, x + extractedRegionSize, y + extractedRegionSize, z + extractedRegionSize); // If you uncomment this line you will be able to see that the volume is rendered as multiple seperate meshes. //regToExtract.shrink(1); diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index ddc314eb..bc2d3e40 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -12,7 +12,7 @@ using namespace std; //////////////////////////////////////////////////////////////////////////////// OpenGLWidget::OpenGLWidget(QWidget *parent) :QGLWidget(parent) - ,m_viewableRegion(Region(0, 0, 0, 255, 255, 255)) + ,m_viewableRegion(PolyVox::Region(0, 0, 0, 255, 255, 255)) ,m_xRotation(0) ,m_yRotation(0) { @@ -23,7 +23,7 @@ void OpenGLWidget::setShader(QSharedPointer shader) mShader = shader; } -void OpenGLWidget::setViewableRegion(Region viewableRegion) +void OpenGLWidget::setViewableRegion(PolyVox::Region viewableRegion) { m_viewableRegion = viewableRegion; diff --git a/examples/common/OpenGLWidget.h b/examples/common/OpenGLWidget.h index d87b4161..eaff700a 100644 --- a/examples/common/OpenGLWidget.h +++ b/examples/common/OpenGLWidget.h @@ -71,7 +71,7 @@ public: // The GL_ARRAY_BUFFER will contain the list of vertex positions glGenBuffers(1, &(meshData.vertexBuffer)); glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(MeshType::VertexType), vecVertices.data(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(typename MeshType::VertexType), vecVertices.data(), GL_STATIC_DRAW); // and GL_ELEMENT_ARRAY_BUFFER will contain the indices glGenBuffers(1, &(meshData.indexBuffer)); @@ -80,20 +80,20 @@ public: // Every surface extractor outputs valid positions for the vertices, so tell OpenGL how these are laid out glEnableVertexAttribArray(0); // Attrib '0' is the vertex positions - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(MeshType::VertexType), (GLvoid*)(offsetof(MeshType::VertexType, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) // Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor // does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the // shader. This is mostly just to simplify this example code - in a real application you will know whether your // chosen surface extractor generates normals and can skip uploading them if not. glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals. - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(MeshType::VertexType), (GLvoid*)(offsetof(MeshType::VertexType, normal))); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, normal))); // Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code // we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here. glEnableVertexAttribArray(2); //We're talking about shader attribute '2' - GLint size = (std::min)(sizeof(MeshType::VertexType::VoxelType), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type) - glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(MeshType::VertexType), (GLvoid*)(offsetof(MeshType::VertexType, material))); + GLint size = (std::min)(sizeof(typename MeshType::VertexType::VoxelType), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type) + glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, material))); // We're done uploading and can now unbind. glBindVertexArray(0); From 140cbc0fc72971f329244e4a86059ab19794ee2e Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 27 May 2014 15:08:20 +0100 Subject: [PATCH 41/72] Move shader code to external files rather than embedded A bit of CMake code in each example copies the files to the correct location and Qt loads them from the application's binary directory. --- examples/Basic/CMakeLists.txt | 3 ++ examples/OpenGL/CMakeLists.txt | 3 ++ examples/Paging/CMakeLists.txt | 3 ++ examples/SmoothLOD/CMakeLists.txt | 3 ++ examples/common/OpenGLWidget.cpp | 46 ++----------------------------- examples/common/example.frag | 19 +++++++++++++ examples/common/example.vert | 20 ++++++++++++++ 7 files changed, 54 insertions(+), 43 deletions(-) create mode 100644 examples/common/example.frag create mode 100644 examples/common/example.vert diff --git a/examples/Basic/CMakeLists.txt b/examples/Basic/CMakeLists.txt index 30ca5f3e..4bf89fcb 100644 --- a/examples/Basic/CMakeLists.txt +++ b/examples/Basic/CMakeLists.txt @@ -55,6 +55,9 @@ ENDIF(MSVC) TARGET_LINK_LIBRARIES(BasicExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore) SET_PROPERTY(TARGET BasicExample PROPERTY FOLDER "Examples") +configure_file(../common/example.vert example.vert COPYONLY) +configure_file(../common/example.frag example.frag COPYONLY) + #Install - Only install the example in Windows IF(WIN32) INSTALL(TARGETS BasicExample diff --git a/examples/OpenGL/CMakeLists.txt b/examples/OpenGL/CMakeLists.txt index dde5a41b..90d91b99 100644 --- a/examples/OpenGL/CMakeLists.txt +++ b/examples/OpenGL/CMakeLists.txt @@ -57,6 +57,9 @@ ENDIF(MSVC) TARGET_LINK_LIBRARIES(OpenGLExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore) SET_PROPERTY(TARGET OpenGLExample PROPERTY FOLDER "Examples") +configure_file(../common/example.vert example.vert COPYONLY) +configure_file(../common/example.frag example.frag COPYONLY) + #Install - Only install the example in Windows IF(WIN32) INSTALL(TARGETS OpenGLExample diff --git a/examples/Paging/CMakeLists.txt b/examples/Paging/CMakeLists.txt index aa9b2899..54db88bd 100644 --- a/examples/Paging/CMakeLists.txt +++ b/examples/Paging/CMakeLists.txt @@ -57,6 +57,9 @@ ENDIF(MSVC) TARGET_LINK_LIBRARIES(PagingExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore) SET_PROPERTY(TARGET PagingExample PROPERTY FOLDER "Examples") +configure_file(../common/example.vert example.vert COPYONLY) +configure_file(../common/example.frag example.frag COPYONLY) + #Install - Only install the example in Windows IF(WIN32) INSTALL(TARGETS PagingExample diff --git a/examples/SmoothLOD/CMakeLists.txt b/examples/SmoothLOD/CMakeLists.txt index 55c9e934..c2fa3170 100644 --- a/examples/SmoothLOD/CMakeLists.txt +++ b/examples/SmoothLOD/CMakeLists.txt @@ -55,6 +55,9 @@ ENDIF(MSVC) TARGET_LINK_LIBRARIES(SmoothLODExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore) SET_PROPERTY(TARGET SmoothLODExample PROPERTY FOLDER "Examples") +configure_file(../common/example.vert example.vert COPYONLY) +configure_file(../common/example.frag example.frag COPYONLY) + #Install - Only install the example in Windows IF(WIN32) INSTALL(TARGETS SmoothLODExample diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index bc2d3e40..788d934d 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -2,6 +2,7 @@ #include #include +#include //#include using namespace PolyVox; @@ -91,28 +92,7 @@ void OpenGLWidget::initializeGL() // This is basically a simple fallback vertex shader which does the most basic rendering possible. // PolyVox examples are able to provide their own shaders to demonstrate certain effects if desired. - if (!mShader->addShaderFromSourceCode(QGLShader::Vertex, - "#version 140\n" - - "in vec4 position; // This will be the position of the vertex in model-space\n" - - "// The usual matrices are provided\n" - "uniform mat4 cameraToClipMatrix;\n" - "uniform mat4 worldToCameraMatrix;\n" - "uniform mat4 modelToWorldMatrix;\n" - - "// This will be used by the fragment shader to calculate flat-shaded normals. This is an unconventional approach\n" - "// but we use it in this example framework because not all surface extractor generate surface normals.\n" - "out vec4 worldPosition;\n" - - "void main()\n" - "{\n" - " // Standard sequence of OpenGL transformations.\n" - " worldPosition = modelToWorldMatrix * position;\n" - " vec4 cameraPosition = worldToCameraMatrix * worldPosition;\n" - " gl_Position = cameraToClipMatrix * cameraPosition;\n" - "}\n" - )) + if (!mShader->addShaderFromSourceFile(QGLShader::Vertex, QCoreApplication::applicationDirPath()+"/"+"example.vert")) { std::cerr << mShader->log().toStdString() << std::endl; exit(EXIT_FAILURE); @@ -120,27 +100,7 @@ void OpenGLWidget::initializeGL() // This is basically a simple fallback fragment shader which does the most basic rendering possible. // PolyVox examples are able to provide their own shaders to demonstrate certain effects if desired. - if (!mShader->addShaderFromSourceCode(QGLShader::Fragment, - "#version 130\n" - - "// Passed in from the vertex shader\n" - "in vec4 worldPosition;\n" - "in vec4 worldNormal;\n" - - "// the color that gets written to the display\n" - "out vec4 outputColor;\n" - - "void main()\n" - "{\n" - " // Again, for the purposes of these examples we cannot be sure that per-vertex normals are provided. A sensible fallback \n" - " // is to use this little trick to compute per-fragment flat-shaded normals from the world positions using derivative operations.\n" - " vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz)));\n" - - " // We are just using the normal as the output color, and making it lighter so it looks a bit nicer. \n" - " // Obviously a real shader would also do texuring, lighting, or whatever is required for the application.\n" - " outputColor = vec4(abs(normal) * 0.5 + vec3(0.5, 0.5, 0.5), 1.0);\n" - "}\n" - )) + if (!mShader->addShaderFromSourceFile(QGLShader::Fragment, QCoreApplication::applicationDirPath()+"/"+"example.frag")) { std::cerr << mShader->log().toStdString() << std::endl; exit(EXIT_FAILURE); diff --git a/examples/common/example.frag b/examples/common/example.frag new file mode 100644 index 00000000..c9cbf215 --- /dev/null +++ b/examples/common/example.frag @@ -0,0 +1,19 @@ +#version 130 + +// Passed in from the vertex shader +in vec4 worldPosition; +in vec4 worldNormal; + +// the color that gets written to the display +out vec4 outputColor; + +void main() +{ + // Again, for the purposes of these examples we cannot be sure that per-vertex normals are provided. A sensible fallback + // is to use this little trick to compute per-fragment flat-shaded normals from the world positions using derivative operations. + vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz))); + + // We are just using the normal as the output color, and making it lighter so it looks a bit nicer. + // Obviously a real shader would also do texuring, lighting, or whatever is required for the application. + outputColor = vec4(abs(normal) * 0.5 + vec3(0.5, 0.5, 0.5), 1.0); +} diff --git a/examples/common/example.vert b/examples/common/example.vert new file mode 100644 index 00000000..94d35f44 --- /dev/null +++ b/examples/common/example.vert @@ -0,0 +1,20 @@ +#version 140 + +in vec4 position; // This will be the position of the vertex in model-space + +// The usual matrices are provided +uniform mat4 cameraToClipMatrix; +uniform mat4 worldToCameraMatrix; +uniform mat4 modelToWorldMatrix; + +// This will be used by the fragment shader to calculate flat-shaded normals. This is an unconventional approach +// but we use it in this example framework because not all surface extractor generate surface normals. +out vec4 worldPosition; + +void main() +{ + // Standard sequence of OpenGL transformations. + worldPosition = modelToWorldMatrix * position; + vec4 cameraPosition = worldToCameraMatrix * worldPosition; + gl_Position = cameraToClipMatrix * cameraPosition; +} From 764c9ac97cf0efcfbe285625e388a11ae7a23d8b Mon Sep 17 00:00:00 2001 From: David Williams Date: Tue, 27 May 2014 17:05:15 +0200 Subject: [PATCH 42/72] Simplified vertex types to structs with public members. Added (currently dummy) decode methods. --- .../PolyVoxCore/CubicSurfaceExtractor.inl | 7 +- .../MarchingCubesSurfaceExtractor.inl | 18 ++- .../PolyVoxCore/include/PolyVoxCore/Mesh.h | 18 +++ .../PolyVoxCore/PolyVoxForwardDeclarations.h | 4 +- .../include/PolyVoxCore/VertexTypes.h | 150 +++++------------- tests/TestSurfaceExtractor.cpp | 22 +-- 6 files changed, 95 insertions(+), 124 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl index 5bc067a9..f62ce7ae 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl @@ -214,7 +214,10 @@ namespace PolyVox if(rEntry.iIndex == -1) { //No vertices matched and we've now hit an empty space. Fill it by creating a vertex. The 0.5f offset is because vertices set between voxels in order to build cubes around them. - rEntry.iIndex = m_meshCurrent->addVertex(CubicVertex(Vector3DFloat(static_cast(uX)-0.5f, static_cast(uY)-0.5f, static_cast(uZ)-0.5f), uMaterialIn)); + CubicVertex cubicVertex; + cubicVertex.position.setElements(static_cast(uX)-0.5f, static_cast(uY)-0.5f, static_cast(uZ)-0.5f); + cubicVertex.material = uMaterialIn; + rEntry.iIndex = m_meshCurrent->addVertex(cubicVertex); rEntry.uMaterial = uMaterialIn; return rEntry.iIndex; @@ -268,7 +271,7 @@ namespace PolyVox { //All four vertices of a given quad have the same material, //so just check that the first pair of vertices match. - if(m_meshCurrent->getVertices()[q1.vertices[0]].getMaterial() == m_meshCurrent->getVertices()[q2.vertices[0]].getMaterial()) + if(m_meshCurrent->getVertices()[q1.vertices[0]].material == m_meshCurrent->getVertices()[q2.vertices[0]].material) { //Now check whether quad 2 is adjacent to quad one by comparing vertices. //Adjacent quads must share two vertices, and the second quad could be to the diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl index 99998bf4..6b6a688b 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl @@ -459,7 +459,11 @@ namespace PolyVox // Allow the controller to decide how the material should be derived from the voxels. const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v100, fInterp); - const MarchingCubesVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); + MarchingCubesVertex surfaceVertex; + surfaceVertex.position = v3dPosition; + surfaceVertex.normal = v3dNormal; + surfaceVertex.material = uMaterial; + const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); m_pCurrentVertexIndicesX[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; @@ -488,7 +492,11 @@ namespace PolyVox // Allow the controller to decide how the material should be derived from the voxels. const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v010, fInterp); - MarchingCubesVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); + MarchingCubesVertex surfaceVertex; + surfaceVertex.position = v3dPosition; + surfaceVertex.normal = v3dNormal; + surfaceVertex.material = uMaterial; + uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); m_pCurrentVertexIndicesY[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; @@ -516,7 +524,11 @@ namespace PolyVox // Allow the controller to decide how the material should be derived from the voxels. const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v001, fInterp); - const MarchingCubesVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); + MarchingCubesVertex surfaceVertex; + surfaceVertex.position = v3dPosition; + surfaceVertex.normal = v3dNormal; + surfaceVertex.material = uMaterial; + const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); m_pCurrentVertexIndicesZ[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h index bcb40576..bad1a7fb 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h @@ -100,6 +100,24 @@ namespace PolyVox template std::shared_ptr< Mesh > extractSubset(Mesh& inputMesh, std::set setMaterials); + + template + Mesh< Vertex< typename MeshType::VertexType::VoxelType > > decode(const MeshType& mesh) + { + Mesh< Vertex< typename MeshType::VertexType::VoxelType > > result; + result.m_vecVertices.reserve(mesh.m_vecVertices.size()); + + for(uint32_t ct = 0; ct < mesh.m_vecVertices.size(); ct++) + { + result.m_vecVertices[ct] = decode(mesh.m_vecVertices[ct]); + } + + result.m_vecTriangleIndices = mesh.m_vecTriangleIndices; + + result.m_Region = mesh.m_Region; + + return result; + } } #include "PolyVoxCore/Mesh.inl" diff --git a/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h b/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h index 3d9ef742..49bd882c 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h +++ b/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h @@ -81,7 +81,7 @@ namespace PolyVox //////////////////////////////////////////////////////////////////////////////// // CubicVertex //////////////////////////////////////////////////////////////////////////////// - template class CubicVertex; + template struct CubicVertex; //////////////////////////////////////////////////////////////////////////////// // Density @@ -111,7 +111,7 @@ namespace PolyVox //////////////////////////////////////////////////////////////////////////////// // MarchingCubesVertex //////////////////////////////////////////////////////////////////////////////// - template class MarchingCubesVertex; + template struct MarchingCubesVertex; //////////////////////////////////////////////////////////////////////////////// // Material diff --git a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h index e8d938ae..1f421fd9 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h +++ b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h @@ -32,134 +32,72 @@ freely, subject to the following restrictions: #include namespace PolyVox -{ -#ifdef SWIG - class CubicVertex +{ + #ifdef SWIG + struct Vertex #else template - class POLYVOX_API CubicVertex + struct POLYVOX_API Vertex #endif { - public: - typedef _VoxelType VoxelType; - CubicVertex() - { - } - - CubicVertex(Vector3DFloat positionToSet, VoxelType materialToSet) - :position(positionToSet) - ,material(materialToSet) - { - } - - CubicVertex(Vector3DFloat positionToSet, Vector3DFloat normalToSet, VoxelType materialToSet) - :position(positionToSet) - ,normal(normalToSet) - ,material(materialToSet) - { - } - - VoxelType getMaterial(void) const - { - return material; - } - - const Vector3DFloat& getNormal(void) const - { - return normal; - } - - const Vector3DFloat& getPosition(void) const - { - return position; - } - - void setMaterial(VoxelType materialToSet) - { - material = materialToSet; - } - - void setNormal(const Vector3DFloat& normalToSet) - { - normal = normalToSet; - } - - void setPosition(const Vector3DFloat& positionToSet) - { - position = positionToSet; - } - - public: Vector3DFloat position; Vector3DFloat normal; VoxelType material; }; #ifdef SWIG - class MarchingCubesVertex + struct CubicVertex #else template - class POLYVOX_API MarchingCubesVertex + struct POLYVOX_API CubicVertex #endif { - public: - typedef _VoxelType VoxelType; - MarchingCubesVertex() - { - } - - MarchingCubesVertex(Vector3DFloat positionToSet, VoxelType materialToSet) - :position(positionToSet) - , material(materialToSet) - { - } - - MarchingCubesVertex(Vector3DFloat positionToSet, Vector3DFloat normalToSet, VoxelType materialToSet) - :position(positionToSet) - , normal(normalToSet) - , material(materialToSet) - { - } - - VoxelType getMaterial(void) const - { - return material; - } - - const Vector3DFloat& getNormal(void) const - { - return normal; - } - - const Vector3DFloat& getPosition(void) const - { - return position; - } - - void setMaterial(VoxelType materialToSet) - { - material = materialToSet; - } - - void setNormal(const Vector3DFloat& normalToSet) - { - normal = normalToSet; - } - - void setPosition(const Vector3DFloat& positionToSet) - { - position = positionToSet; - } - - public: Vector3DFloat position; Vector3DFloat normal; VoxelType material; }; + +#ifdef SWIG + struct MarchingCubesVertex +#else + template + struct POLYVOX_API MarchingCubesVertex +#endif + { + typedef _VoxelType VoxelType; + + Vector3DFloat position; + Vector3DFloat normal; + VoxelType material; + }; + + // Hopefully the compiler will implement the 'Return value optimization' here, but + // performance critical code will most likely decode the vertices in a shader anyway. + template + Vertex decode(const CubicVertex& cubicVertex) + { + Vertex result; + result.position = cubicVertex.position; + result.normal = cubicVertex.normal; + result.material = cubicVertex.material; + return result; + } + + // Hopefully the compiler will implement the 'Return value optimization' here, but + // performance critical code will most likely decode the vertices in a shader anyway. + template + Vertex decode(const MarchingCubesVertex& cubicVertex) + { + Vertex result; + result.position = cubicVertex.position; + result.normal = cubicVertex.normal; + result.material = cubicVertex.material; + return result; + } } #endif diff --git a/tests/TestSurfaceExtractor.cpp b/tests/TestSurfaceExtractor.cpp index 2189b9c2..e621fa99 100644 --- a/tests/TestSurfaceExtractor.cpp +++ b/tests/TestSurfaceExtractor.cpp @@ -172,58 +172,58 @@ void TestSurfaceExtractor::testExecute() } QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); + QCOMPARE(mesh.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); auto mesh1 = testForType(); QCOMPARE(mesh1.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh1.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh1.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); + QCOMPARE(mesh1.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); auto mesh2 = testForType(); QCOMPARE(mesh2.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh2.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh2.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); + QCOMPARE(mesh2.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); auto mesh3 = testForType(); QCOMPARE(mesh3.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh3.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh3.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); + QCOMPARE(mesh3.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); auto mesh4 = testForType(); QCOMPARE(mesh4.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh4.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh4.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); + QCOMPARE(mesh4.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); auto mesh5 = testForType(); QCOMPARE(mesh5.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh5.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh5.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); + QCOMPARE(mesh5.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); auto mesh6 = testForType(); QCOMPARE(mesh6.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh6.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh6.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); + QCOMPARE(mesh6.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); auto mesh7 = testForType(); QCOMPARE(mesh7.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh7.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh7.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); + QCOMPARE(mesh7.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); auto mesh8 = testForType(); QCOMPARE(mesh8.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh8.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh8.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); + QCOMPARE(mesh8.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); auto mesh9 = testForType(); QCOMPARE(mesh9.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh9.getNoOfIndices(), uExpectedIndices); - //QCOMPARE(mesh9.getVertices()[uMaterialToCheck].getMaterial(), fExpectedMaterial); + //QCOMPARE(mesh9.getVertices()[uMaterialToCheck].material, fExpectedMaterial); //Test whether the CustomSurfaceExtractor works. /*testCustomController(floatMesh); QCOMPARE(floatMesh.getNoOfVertices(), uExpectedVertices); QCOMPARE(floatMesh.getNoOfIndices(), uExpectedIndices); - QCOMPARE(floatMesh.getVertices()[uMaterialToCheck].getMaterial(), fNoMaterial);*/ + QCOMPARE(floatMesh.getVertices()[uMaterialToCheck].material, fNoMaterial);*/ } QTEST_MAIN(TestSurfaceExtractor) From 37ba9ab33870354268977c3e5384de207092d66b Mon Sep 17 00:00:00 2001 From: David Williams Date: Tue, 27 May 2014 23:01:38 +0200 Subject: [PATCH 43/72] CubicVertex now uses a more memory efficient representation which can be decoded on the CPU or GPU. --- examples/Basic/main.cpp | 7 ++++--- .../include/PolyVoxCore/CubicSurfaceExtractor.inl | 2 +- library/PolyVoxCore/include/PolyVoxCore/Mesh.h | 2 +- library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h | 9 +++++---- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index f123361b..a13da717 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -81,11 +81,12 @@ int main(int argc, char *argv[]) auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion()); //auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion()); - //auto mesh = extractCubicMesh(&volData, PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(31, 31, 31))); - //auto mesh2 = extractCubicMesh(&volData, PolyVox::Region(Vector3DInt32(32, 32, 32), Vector3DInt32(63, 63, 63))); + // The surface extractor outputs the mesh in an efficient compressed format which is not directly suitable for rendering. The easiest approach is to + // decode this on the CPU as shown below, though more advanced applications can upload the compressed mesh to the GPU and decompress in shader code. + auto decodedMesh = decode(mesh); //Pass the surface to the OpenGL window - openGLWidget.addMesh(mesh); + openGLWidget.addMesh(decodedMesh); //openGLWidget.addMesh(mesh2); openGLWidget.setViewableRegion(volData.getEnclosingRegion()); diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl index f62ce7ae..b152f90c 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl @@ -215,7 +215,7 @@ namespace PolyVox { //No vertices matched and we've now hit an empty space. Fill it by creating a vertex. The 0.5f offset is because vertices set between voxels in order to build cubes around them. CubicVertex cubicVertex; - cubicVertex.position.setElements(static_cast(uX)-0.5f, static_cast(uY)-0.5f, static_cast(uZ)-0.5f); + cubicVertex.position.setElements(static_cast(uX), static_cast(uY), static_cast(uZ)); cubicVertex.material = uMaterialIn; rEntry.iIndex = m_meshCurrent->addVertex(cubicVertex); rEntry.uMaterial = uMaterialIn; diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h index bad1a7fb..d23f7716 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h @@ -105,7 +105,7 @@ namespace PolyVox Mesh< Vertex< typename MeshType::VertexType::VoxelType > > decode(const MeshType& mesh) { Mesh< Vertex< typename MeshType::VertexType::VoxelType > > result; - result.m_vecVertices.reserve(mesh.m_vecVertices.size()); + result.m_vecVertices.resize(mesh.m_vecVertices.size()); for(uint32_t ct = 0; ct < mesh.m_vecVertices.size(); ct++) { diff --git a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h index 1f421fd9..fc53fc2e 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h +++ b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h @@ -56,8 +56,8 @@ namespace PolyVox { typedef _VoxelType VoxelType; - Vector3DFloat position; - Vector3DFloat normal; + Vector3DUint8 position; + uint8_t normal; VoxelType material; }; @@ -81,8 +81,9 @@ namespace PolyVox Vertex decode(const CubicVertex& cubicVertex) { Vertex result; - result.position = cubicVertex.position; - result.normal = cubicVertex.normal; + Vector3DUint8 temp = cubicVertex.position; // For some reason we can't cast Vector3DUint8 to Vector3DFloat - investigate why. + result.position = Vector3DFloat(temp.getX(), temp.getY(), temp.getZ()) - Vector3DFloat(0.5, 0.5, 0.5); + //result.normal = cubicVertex.normal; result.material = cubicVertex.material; return result; } From 35049b7a535ce94db3bc7ad1c9e863713cd370b1 Mon Sep 17 00:00:00 2001 From: David Williams Date: Tue, 27 May 2014 23:23:24 +0200 Subject: [PATCH 44/72] Throw exception if extracted region is too large. --- examples/Paging/main.cpp | 10 ++++++---- .../include/PolyVoxCore/CubicSurfaceExtractor.inl | 6 ++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/examples/Paging/main.cpp b/examples/Paging/main.cpp index 3700c632..ee2d2d23 100644 --- a/examples/Paging/main.cpp +++ b/examples/Paging/main.cpp @@ -186,13 +186,15 @@ int main(int argc, char *argv[]) std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl; //Extract the surface - auto mesh = extractCubicMesh(&volData, reg); + auto mesh = extractCubicMesh(&volData, reg2); std::cout << "#vertices: " << mesh.getNoOfVertices() << std::endl; - //Pass the surface to the OpenGL window - openGLWidget.addMesh(mesh); + auto decodedMesh = decode(mesh); - openGLWidget.setViewableRegion(reg); + //Pass the surface to the OpenGL window + openGLWidget.addMesh(decodedMesh); + + openGLWidget.setViewableRegion(reg2); //Run the message pump. return app.exec(); diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl index b152f90c..da7803cd 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl @@ -45,6 +45,12 @@ namespace PolyVox ,m_tBorderValue(tBorderValue) { m_funcIsQuadNeededCallback = isQuadNeeded; + + // This extractor has a limit as to how large the extracted region can be, because the vertex positions are encoded with a single byte per component. + int32_t maxReionDimension = 256; + POLYVOX_THROW_IF(region.getWidthInVoxels() > maxReionDimension, std::invalid_argument, "Requested extraction region exceeds maximum dimensions"); + POLYVOX_THROW_IF(region.getHeightInVoxels() > maxReionDimension, std::invalid_argument, "Requested extraction region exceeds maximum dimensions"); + POLYVOX_THROW_IF(region.getDepthInVoxels() > maxReionDimension, std::invalid_argument, "Requested extraction region exceeds maximum dimensions"); } template From c26686476d0dca9e8951c4e8a3242d77e93af16e Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Wed, 28 May 2014 10:29:05 +0100 Subject: [PATCH 45/72] Use Qt's resource system to store the shader source The shader source is included inside each comipled binary file. The OpenGL example also provides its own shader files which overrides the default. Common shader code is in the 'common' directory and each example's custom shader is alongside the example's C++ code. --- examples/Basic/CMakeLists.txt | 8 ++-- examples/OpenGL/CMakeLists.txt | 9 ++-- examples/OpenGL/main.cpp | 77 +----------------------------- examples/OpenGL/openglexample.frag | 45 +++++++++++++++++ examples/OpenGL/openglexample.qrc | 6 +++ examples/OpenGL/openglexample.vert | 26 ++++++++++ examples/Paging/CMakeLists.txt | 5 +- examples/SmoothLOD/CMakeLists.txt | 5 +- examples/common/OpenGLWidget.cpp | 4 +- examples/common/example.qrc | 6 +++ 10 files changed, 104 insertions(+), 87 deletions(-) create mode 100644 examples/OpenGL/openglexample.frag create mode 100644 examples/OpenGL/openglexample.qrc create mode 100644 examples/OpenGL/openglexample.vert create mode 100644 examples/common/example.qrc diff --git a/examples/Basic/CMakeLists.txt b/examples/Basic/CMakeLists.txt index 4bf89fcb..2d89215b 100644 --- a/examples/Basic/CMakeLists.txt +++ b/examples/Basic/CMakeLists.txt @@ -47,17 +47,17 @@ FIND_PACKAGE(OpenGL REQUIRED) INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR}) LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR}) +#This will include the shader files inside the compiled binary +QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc) + #Build -ADD_EXECUTABLE(BasicExample ${SRC_FILES}) +ADD_EXECUTABLE(BasicExample ${SRC_FILES} ${COMMON_RESOURCES_RCC}) IF(MSVC) SET_TARGET_PROPERTIES(BasicExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127") ENDIF(MSVC) TARGET_LINK_LIBRARIES(BasicExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore) SET_PROPERTY(TARGET BasicExample PROPERTY FOLDER "Examples") -configure_file(../common/example.vert example.vert COPYONLY) -configure_file(../common/example.frag example.frag COPYONLY) - #Install - Only install the example in Windows IF(WIN32) INSTALL(TARGETS BasicExample diff --git a/examples/OpenGL/CMakeLists.txt b/examples/OpenGL/CMakeLists.txt index 90d91b99..d6db1712 100644 --- a/examples/OpenGL/CMakeLists.txt +++ b/examples/OpenGL/CMakeLists.txt @@ -49,17 +49,18 @@ FIND_PACKAGE(OpenGL REQUIRED) INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR}) LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR}) +#This will include the shader files inside the compiled binary +QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc) +QT4_ADD_RESOURCES(OPENGLEXAMPLE_RESOURCES_RCC openglexample.qrc) + #Build -ADD_EXECUTABLE(OpenGLExample ${SRC_FILES}) +ADD_EXECUTABLE(OpenGLExample ${SRC_FILES} ${COMMON_RESOURCES_RCC} ${OPENGLEXAMPLE_RESOURCES_RCC}) IF(MSVC) SET_TARGET_PROPERTIES(OpenGLExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127") ENDIF(MSVC) TARGET_LINK_LIBRARIES(OpenGLExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore) SET_PROPERTY(TARGET OpenGLExample PROPERTY FOLDER "Examples") -configure_file(../common/example.vert example.vert COPYONLY) -configure_file(../common/example.frag example.frag COPYONLY) - #Install - Only install the example in Windows IF(WIN32) INSTALL(TARGETS OpenGLExample diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index c339fa0b..a4dc8ed4 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -90,86 +90,13 @@ int main(int argc, char *argv[]) QSharedPointer shader(new QGLShaderProgram); - if (!shader->addShaderFromSourceCode(QGLShader::Vertex, - "#version 140\n" - - "in vec4 position; // This will be the position of the vertex in model-space\n" - "in vec4 normal; // The normal data may not have been set\n" - "in ivec2 material;\n" - - "uniform mat4 cameraToClipMatrix;\n" - "uniform mat4 worldToCameraMatrix;\n" - "uniform mat4 modelToWorldMatrix;\n" - - "out vec4 worldPosition; //This is being passed to the fragment shader to calculate the normals\n" - "out vec3 normalFromVS;\n" - "flat out ivec2 materialFromVS;\n" - - "void main()\n" - "{\n" - " // Compute the usual OpenGL transformation to clip space.\n" - " gl_Position = cameraToClipMatrix * worldToCameraMatrix * modelToWorldMatrix * position;\n" - - " // This example is demonstrating the marching cubes mesh, which does have per-vertex normals. We can \n" - " // just pass them through, though real code might want to deal with transforming normals appropriatly.\n" - " normalFromVS = normal.xyz;\n" - - " // Nothing special here, we just pass the material through to the fragment shader.\n" - " materialFromVS = material;\n" - "}\n" - )) + if (!shader->addShaderFromSourceFile(QGLShader::Vertex, ":/openglexample.vert")) { std::cerr << shader->log().toStdString() << std::endl; exit(EXIT_FAILURE); } - if (!shader->addShaderFromSourceCode(QGLShader::Fragment, - "#version 130\n" - - "in vec4 worldPosition; //Passed in from the vertex shader\n" - "in vec3 normalFromVS;\n" - "flat in ivec2 materialFromVS;\n" - - "out vec4 outputColor;\n" - - "void main()\n" - "{\n" - " // The first byte of our voxel data is the material.\n" - " // We use this to decide how to color the fragment.\n" - " vec4 surfaceColor;\n" - " switch(materialFromVS.x)\n" - " {\n" - " case 1:\n" - " surfaceColor = vec4(1.0, 0.0, 0.0, 1.0);\n" - " break;\n" - " case 2:\n" - " surfaceColor = vec4(0.0, 1.0, 0.0, 1.0);\n" - " break;\n" - " case 3:\n" - " surfaceColor = vec4(0.0, 0.0, 1.0, 1.0);\n" - " break;\n" - " case 4:\n" - " surfaceColor = vec4(1.0, 1.0, 0.0, 1.0);\n" - " break;\n" - " case 5:\n" - " surfaceColor = vec4(1.0, 0.0, 1.0, 1.0);\n" - " break;\n" - " default:\n" - " surfaceColor = vec4(1.0, 1.0, 1.0, 1.0);\n" - " break;\n" - " }\n" - - " // Quick and dirty lighting, obviously a real implementation\n" - " // should pass light properties as shader parameters, etc.\n" - " vec3 lightDir = vec3(0.0, 0.0, 1.0);\n" - " float diffuse = clamp(dot(lightDir, normalFromVS), 0.0, 1.0);\n" - " diffuse *= 0.7; // Dim the diffuse a bit\n" - " float ambient = 0.3; // Add some ambient\n" - " float lightIntensity = diffuse + ambient; // Compute the final light intensity\n" - - " outputColor = surfaceColor * lightIntensity; //Compute final rendered color\n" - "}\n" - )) + if (!shader->addShaderFromSourceFile(QGLShader::Fragment, ":/openglexample.frag")) { std::cerr << shader->log().toStdString() << std::endl; exit(EXIT_FAILURE); diff --git a/examples/OpenGL/openglexample.frag b/examples/OpenGL/openglexample.frag new file mode 100644 index 00000000..75aa0e74 --- /dev/null +++ b/examples/OpenGL/openglexample.frag @@ -0,0 +1,45 @@ +#version 130 + +in vec4 worldPosition; //Passed in from the vertex shader +in vec3 normalFromVS; +flat in ivec2 materialFromVS; + +out vec4 outputColor; + +void main() +{ + // The first byte of our voxel data is the material. + // We use this to decide how to color the fragment. + vec4 surfaceColor; + switch(materialFromVS.x) + { + case 1: + surfaceColor = vec4(1.0, 0.0, 0.0, 1.0); + break; + case 2: + surfaceColor = vec4(0.0, 1.0, 0.0, 1.0); + break; + case 3: + surfaceColor = vec4(0.0, 0.0, 1.0, 1.0); + break; + case 4: + surfaceColor = vec4(1.0, 1.0, 0.0, 1.0); + break; + case 5: + surfaceColor = vec4(1.0, 0.0, 1.0, 1.0); + break; + default: + surfaceColor = vec4(1.0, 1.0, 1.0, 1.0); + break; + } + + // Quick and dirty lighting, obviously a real implementation + // should pass light properties as shader parameters, etc. + vec3 lightDir = vec3(0.0, 0.0, 1.0); + float diffuse = clamp(dot(lightDir, normalFromVS), 0.0, 1.0); + diffuse *= 0.7; // Dim the diffuse a bit + float ambient = 0.3; // Add some ambient + float lightIntensity = diffuse + ambient; // Compute the final light intensity + + outputColor = surfaceColor * lightIntensity; //Compute final rendered color +} diff --git a/examples/OpenGL/openglexample.qrc b/examples/OpenGL/openglexample.qrc new file mode 100644 index 00000000..128acb5a --- /dev/null +++ b/examples/OpenGL/openglexample.qrc @@ -0,0 +1,6 @@ + + + openglexample.vert + openglexample.frag + + diff --git a/examples/OpenGL/openglexample.vert b/examples/OpenGL/openglexample.vert new file mode 100644 index 00000000..381fac12 --- /dev/null +++ b/examples/OpenGL/openglexample.vert @@ -0,0 +1,26 @@ +#version 140 + +in vec4 position; // This will be the position of the vertex in model-space +in vec4 normal; // The normal data may not have been set +in ivec2 material; + +uniform mat4 cameraToClipMatrix; +uniform mat4 worldToCameraMatrix; +uniform mat4 modelToWorldMatrix; + +out vec4 worldPosition; //This is being passed to the fragment shader to calculate the normals +out vec3 normalFromVS; +flat out ivec2 materialFromVS; + +void main() +{ + // Compute the usual OpenGL transformation to clip space. + gl_Position = cameraToClipMatrix * worldToCameraMatrix * modelToWorldMatrix * position; + + // This example is demonstrating the marching cubes mesh, which does have per-vertex normals. We can + // just pass them through, though real code might want to deal with transforming normals appropriatly. + normalFromVS = normal.xyz; + + // Nothing special here, we just pass the material through to the fragment shader. + materialFromVS = material; +} diff --git a/examples/Paging/CMakeLists.txt b/examples/Paging/CMakeLists.txt index 54db88bd..3566e76e 100644 --- a/examples/Paging/CMakeLists.txt +++ b/examples/Paging/CMakeLists.txt @@ -49,8 +49,11 @@ FIND_PACKAGE(OpenGL REQUIRED) INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR}) LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR}) +#This will include the shader files inside the compiled binary +QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc) + #Build -ADD_EXECUTABLE(PagingExample ${SRC_FILES}) +ADD_EXECUTABLE(PagingExample ${SRC_FILES} ${COMMON_RESOURCES_RCC}) IF(MSVC) SET_TARGET_PROPERTIES(PagingExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127") ENDIF(MSVC) diff --git a/examples/SmoothLOD/CMakeLists.txt b/examples/SmoothLOD/CMakeLists.txt index c2fa3170..4a024664 100644 --- a/examples/SmoothLOD/CMakeLists.txt +++ b/examples/SmoothLOD/CMakeLists.txt @@ -47,8 +47,11 @@ FIND_PACKAGE(OpenGL REQUIRED) INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR}) LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR}) +#This will include the shader files inside the compiled binary +QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc) + #Build -ADD_EXECUTABLE(SmoothLODExample ${SRC_FILES}) +ADD_EXECUTABLE(SmoothLODExample ${SRC_FILES} ${COMMON_RESOURCES_RCC}) IF(MSVC) SET_TARGET_PROPERTIES(SmoothLODExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127") #All warnings ENDIF(MSVC) diff --git a/examples/common/OpenGLWidget.cpp b/examples/common/OpenGLWidget.cpp index 788d934d..439264bf 100644 --- a/examples/common/OpenGLWidget.cpp +++ b/examples/common/OpenGLWidget.cpp @@ -92,7 +92,7 @@ void OpenGLWidget::initializeGL() // This is basically a simple fallback vertex shader which does the most basic rendering possible. // PolyVox examples are able to provide their own shaders to demonstrate certain effects if desired. - if (!mShader->addShaderFromSourceFile(QGLShader::Vertex, QCoreApplication::applicationDirPath()+"/"+"example.vert")) + if (!mShader->addShaderFromSourceFile(QGLShader::Vertex, ":/example.vert")) { std::cerr << mShader->log().toStdString() << std::endl; exit(EXIT_FAILURE); @@ -100,7 +100,7 @@ void OpenGLWidget::initializeGL() // This is basically a simple fallback fragment shader which does the most basic rendering possible. // PolyVox examples are able to provide their own shaders to demonstrate certain effects if desired. - if (!mShader->addShaderFromSourceFile(QGLShader::Fragment, QCoreApplication::applicationDirPath()+"/"+"example.frag")) + if (!mShader->addShaderFromSourceFile(QGLShader::Fragment, ":/example.frag")) { std::cerr << mShader->log().toStdString() << std::endl; exit(EXIT_FAILURE); diff --git a/examples/common/example.qrc b/examples/common/example.qrc new file mode 100644 index 00000000..8efd5747 --- /dev/null +++ b/examples/common/example.qrc @@ -0,0 +1,6 @@ + + + example.vert + example.frag + + From e9ba998f2ff041d5df4b03968fee91a003f2fd4b Mon Sep 17 00:00:00 2001 From: David Williams Date: Wed, 28 May 2014 14:03:26 +0200 Subject: [PATCH 46/72] Changes to the folder organization of some files in Visual Studio (via CMake's source_group). --- examples/Basic/CMakeLists.txt | 8 +++----- examples/OpenGL/CMakeLists.txt | 8 +++----- examples/Paging/CMakeLists.txt | 8 +++----- examples/Python/CMakeLists.txt | 2 -- examples/SmoothLOD/CMakeLists.txt | 8 +++----- library/PolyVoxCore/CMakeLists.txt | 8 ++++---- library/PolyVoxUtil/CMakeLists.txt | 4 ++-- 7 files changed, 18 insertions(+), 28 deletions(-) diff --git a/examples/Basic/CMakeLists.txt b/examples/Basic/CMakeLists.txt index 2d89215b..c34dc96c 100644 --- a/examples/Basic/CMakeLists.txt +++ b/examples/Basic/CMakeLists.txt @@ -36,11 +36,6 @@ SET(INC_FILES add_definitions(-DGLEW_STATIC) -#"Sources" and "Headers" are the group names in Visual Studio. -#They may have other uses too... -SOURCE_GROUP("Sources" FILES ${SRC_FILES}) -SOURCE_GROUP("Headers" FILES ${INC_FILES}) - FIND_PACKAGE(OpenGL REQUIRED) #Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location) @@ -50,6 +45,9 @@ LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR}) #This will include the shader files inside the compiled binary QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc) +# Put the resources in a seperate folder in Visual Studio +SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC}) + #Build ADD_EXECUTABLE(BasicExample ${SRC_FILES} ${COMMON_RESOURCES_RCC}) IF(MSVC) diff --git a/examples/OpenGL/CMakeLists.txt b/examples/OpenGL/CMakeLists.txt index d6db1712..14e9f4d1 100644 --- a/examples/OpenGL/CMakeLists.txt +++ b/examples/OpenGL/CMakeLists.txt @@ -38,11 +38,6 @@ SET(INC_FILES add_definitions(-DGLEW_STATIC) -#"Sources" and "Headers" are the group names in Visual Studio. -#They may have other uses too... -SOURCE_GROUP("Sources" FILES ${SRC_FILES}) -SOURCE_GROUP("Headers" FILES ${INC_FILES}) - FIND_PACKAGE(OpenGL REQUIRED) #Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location) @@ -53,6 +48,9 @@ LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR}) QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc) QT4_ADD_RESOURCES(OPENGLEXAMPLE_RESOURCES_RCC openglexample.qrc) +# Put the resources in a seperate folder in Visual Studio +SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC} openglexample.qrc ${OPENGLEXAMPLE_RESOURCES_RCC}) + #Build ADD_EXECUTABLE(OpenGLExample ${SRC_FILES} ${COMMON_RESOURCES_RCC} ${OPENGLEXAMPLE_RESOURCES_RCC}) IF(MSVC) diff --git a/examples/Paging/CMakeLists.txt b/examples/Paging/CMakeLists.txt index 3566e76e..95a3ef8a 100644 --- a/examples/Paging/CMakeLists.txt +++ b/examples/Paging/CMakeLists.txt @@ -38,11 +38,6 @@ SET(INC_FILES add_definitions(-DGLEW_STATIC) -#"Sources" and "Headers" are the group names in Visual Studio. -#They may have other uses too... -SOURCE_GROUP("Sources" FILES ${SRC_FILES}) -SOURCE_GROUP("Headers" FILES ${INC_FILES}) - FIND_PACKAGE(OpenGL REQUIRED) #Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location) @@ -52,6 +47,9 @@ LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR}) #This will include the shader files inside the compiled binary QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc) +# Put the resources in a seperate folder in Visual Studio +SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC}) + #Build ADD_EXECUTABLE(PagingExample ${SRC_FILES} ${COMMON_RESOURCES_RCC}) IF(MSVC) diff --git a/examples/Python/CMakeLists.txt b/examples/Python/CMakeLists.txt index 1d101d6e..dd7176a7 100644 --- a/examples/Python/CMakeLists.txt +++ b/examples/Python/CMakeLists.txt @@ -21,6 +21,4 @@ PROJECT(PythonExample) -SOURCE_GROUP("Sources" FILES PythonExample.py) - configure_file(PythonExample.py PythonExample.py COPYONLY) diff --git a/examples/SmoothLOD/CMakeLists.txt b/examples/SmoothLOD/CMakeLists.txt index 4a024664..abdc59e5 100644 --- a/examples/SmoothLOD/CMakeLists.txt +++ b/examples/SmoothLOD/CMakeLists.txt @@ -36,11 +36,6 @@ SET(INC_FILES add_definitions(-DGLEW_STATIC) -#"Sources" and "Headers" are the group names in Visual Studio. -#They may have other uses too... -SOURCE_GROUP("Sources" FILES ${SRC_FILES}) -SOURCE_GROUP("Headers" FILES ${INC_FILES}) - FIND_PACKAGE(OpenGL REQUIRED) #Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location) @@ -50,6 +45,9 @@ LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR}) #This will include the shader files inside the compiled binary QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc) +# Put the resources in a seperate folder in Visual Studio +SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC}) + #Build ADD_EXECUTABLE(SmoothLODExample ${SRC_FILES} ${COMMON_RESOURCES_RCC}) IF(MSVC) diff --git a/library/PolyVoxCore/CMakeLists.txt b/library/PolyVoxCore/CMakeLists.txt index 42844fce..3fbb260b 100644 --- a/library/PolyVoxCore/CMakeLists.txt +++ b/library/PolyVoxCore/CMakeLists.txt @@ -130,11 +130,11 @@ SET(IMPL_INC_FILES #"Sources" and "Headers" are the group names in Visual Studio. #They may have other uses too... -SOURCE_GROUP("Sources" FILES ${CORE_SRC_FILES}) -SOURCE_GROUP("Headers" FILES ${CORE_INC_FILES}) +SOURCE_GROUP("Source Files" FILES ${CORE_SRC_FILES}) +SOURCE_GROUP("Header Files" FILES ${CORE_INC_FILES}) -SOURCE_GROUP("Sources\\Impl" FILES ${IMPL_SRC_FILES}) -SOURCE_GROUP("Headers\\Impl" FILES ${IMPL_INC_FILES}) +SOURCE_GROUP("Source Files\\Impl" FILES ${IMPL_SRC_FILES}) +SOURCE_GROUP("Header Files\\Impl" FILES ${IMPL_INC_FILES}) #Tell CMake the paths INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/include) diff --git a/library/PolyVoxUtil/CMakeLists.txt b/library/PolyVoxUtil/CMakeLists.txt index 7fbdb43e..2160dc5c 100644 --- a/library/PolyVoxUtil/CMakeLists.txt +++ b/library/PolyVoxUtil/CMakeLists.txt @@ -36,8 +36,8 @@ ADD_DEFINITIONS(-DPOLYVOX_SHARED_EXPORTS) #Export symbols in the .dll #"Sources" and "Headers" are the group names in Visual Studio. #They may have other uses too... -SOURCE_GROUP("Sources" FILES ${UTIL_SRC_FILES}) -SOURCE_GROUP("Headers" FILES ${UTIL_INC_FILES}) +SOURCE_GROUP("Source Files" FILES ${UTIL_SRC_FILES}) +SOURCE_GROUP("Header Files" FILES ${UTIL_INC_FILES}) #Tell CMake the paths INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include) From 85c5686ff9e48db239b783edececaf652c6b4b99 Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 29 May 2014 09:53:16 +0200 Subject: [PATCH 47/72] Work on more compact version of MarchingCubesVertex. --- examples/OpenGL/main.cpp | 5 ++++- .../PolyVoxCore/MarchingCubesSurfaceExtractor.inl | 9 ++++++--- library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h | 5 +++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index a4dc8ed4..a95d66e5 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -127,8 +127,11 @@ int main(int argc, char *argv[]) // Perform the extraction for this region of the volume auto mesh = extractMarchingCubesMesh(&volData, regToExtract); + // The returned mesh needs to be decoded to be appropriate for GPU rendering. + auto decodedMesh = decode(mesh); + //Pass the surface to the OpenGL window - openGLWidget.addMesh(mesh, Vector3DInt32(x, y, z)); + openGLWidget.addMesh(decodedMesh, Vector3DInt32(x, y, z)); meshCounter++; } diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl index 6b6a688b..bbe18ad2 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl @@ -446,6 +446,7 @@ namespace PolyVox const float fInterp = static_cast(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast(m_controller.convertToDensity(v100) - m_controller.convertToDensity(v000)); const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerX()) + fInterp, static_cast(iYVolSpace - m_regSizeInVoxels.getLowerY()), static_cast(iZVolSpace - m_regSizeInCells.getLowerZ())); + const Vector3DUint16 v3dPositionAsUint(static_cast(v3dPosition.getX() * 256.0f), static_cast(v3dPosition.getY() * 256.0f), static_cast(v3dPosition.getZ() * 256.0f)); Vector3DFloat v3dNormal = (n100*fInterp) + (n000*(1-fInterp)); @@ -460,7 +461,7 @@ namespace PolyVox const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v100, fInterp); MarchingCubesVertex surfaceVertex; - surfaceVertex.position = v3dPosition; + surfaceVertex.position = v3dPositionAsUint; surfaceVertex.normal = v3dNormal; surfaceVertex.material = uMaterial; @@ -479,6 +480,7 @@ namespace PolyVox const float fInterp = static_cast(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast(m_controller.convertToDensity(v010) - m_controller.convertToDensity(v000)); const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerX()), static_cast(iYVolSpace - m_regSizeInVoxels.getLowerY()) + fInterp, static_cast(iZVolSpace - m_regSizeInVoxels.getLowerZ())); + const Vector3DUint16 v3dPositionAsUint(static_cast(v3dPosition.getX() * 256.0f), static_cast(v3dPosition.getY() * 256.0f), static_cast(v3dPosition.getZ() * 256.0f)); Vector3DFloat v3dNormal = (n010*fInterp) + (n000*(1-fInterp)); @@ -493,7 +495,7 @@ namespace PolyVox const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v010, fInterp); MarchingCubesVertex surfaceVertex; - surfaceVertex.position = v3dPosition; + surfaceVertex.position = v3dPositionAsUint; surfaceVertex.normal = v3dNormal; surfaceVertex.material = uMaterial; @@ -512,6 +514,7 @@ namespace PolyVox const float fInterp = static_cast(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast(m_controller.convertToDensity(v001) - m_controller.convertToDensity(v000)); const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerX()), static_cast(iYVolSpace - m_regSizeInVoxels.getLowerY()), static_cast(iZVolSpace - m_regSizeInVoxels.getLowerZ()) + fInterp); + const Vector3DUint16 v3dPositionAsUint(static_cast(v3dPosition.getX() * 256.0f), static_cast(v3dPosition.getY() * 256.0f), static_cast(v3dPosition.getZ() * 256.0f)); Vector3DFloat v3dNormal = (n001*fInterp) + (n000*(1-fInterp)); // The gradient for a voxel can be zero (e.g. solid voxel surrounded by empty ones) and so @@ -525,7 +528,7 @@ namespace PolyVox const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v001, fInterp); MarchingCubesVertex surfaceVertex; - surfaceVertex.position = v3dPosition; + surfaceVertex.position = v3dPositionAsUint; surfaceVertex.normal = v3dNormal; surfaceVertex.material = uMaterial; diff --git a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h index fc53fc2e..1044f472 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h +++ b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h @@ -70,7 +70,7 @@ namespace PolyVox { typedef _VoxelType VoxelType; - Vector3DFloat position; + Vector3DUint16 position; Vector3DFloat normal; VoxelType material; }; @@ -94,7 +94,8 @@ namespace PolyVox Vertex decode(const MarchingCubesVertex& cubicVertex) { Vertex result; - result.position = cubicVertex.position; + result.position = Vector3DFloat(cubicVertex.position.getX(), cubicVertex.position.getY(), cubicVertex.position.getZ()); + result.position *= (1.0 / 256.0); result.normal = cubicVertex.normal; result.material = cubicVertex.material; return result; From 2090b0087c8a95ead22fcd66e1a93224f062fa82 Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 29 May 2014 11:39:29 +0200 Subject: [PATCH 48/72] Vertices now carry general purpose 'data' rather than a 'material', though the data will be treated as a material in many cases. This is part of making the architecture more generic and involves some renaming. --- examples/SmoothLOD/main.cpp | 8 +++-- examples/common/OpenGLWidget.h | 4 +-- .../PolyVoxCore/CubicSurfaceExtractor.inl | 6 ++-- .../MarchingCubesSurfaceExtractor.inl | 6 ++-- .../PolyVoxCore/include/PolyVoxCore/Mesh.h | 4 +-- .../include/PolyVoxCore/VertexTypes.h | 34 +++++++++---------- tests/TestSurfaceExtractor.cpp | 24 ++++++------- 7 files changed, 45 insertions(+), 41 deletions(-) diff --git a/examples/SmoothLOD/main.cpp b/examples/SmoothLOD/main.cpp index 60b35c98..01c2fdaf 100644 --- a/examples/SmoothLOD/main.cpp +++ b/examples/SmoothLOD/main.cpp @@ -91,13 +91,17 @@ int main(int argc, char *argv[]) //Extract the surface auto meshLowLOD = extractMarchingCubesMesh(&volDataLowLOD, volDataLowLOD.getEnclosingRegion()); + // The returned mesh needs to be decoded to be appropriate for GPU rendering. + auto decodedMeshLowLOD = decode(meshLowLOD); //Extract the surface auto meshHighLOD = extractMarchingCubesMesh(&volData, PolyVox::Region(Vector3DInt32(30, 0, 0), Vector3DInt32(63, 63, 63))); + // The returned mesh needs to be decoded to be appropriate for GPU rendering. + auto decodedMeshHighLOD = decode(meshHighLOD); //Pass the surface to the OpenGL window - openGLWidget.addMesh(meshHighLOD, Vector3DInt32(30, 0, 0)); - openGLWidget.addMesh(meshLowLOD, Vector3DInt32(0, 0, 0), 63.0f / 31.0f); + openGLWidget.addMesh(decodedMeshHighLOD, Vector3DInt32(30, 0, 0)); + openGLWidget.addMesh(decodedMeshLowLOD, Vector3DInt32(0, 0, 0), 63.0f / 31.0f); openGLWidget.setViewableRegion(volData.getEnclosingRegion()); diff --git a/examples/common/OpenGLWidget.h b/examples/common/OpenGLWidget.h index eaff700a..930cb3d8 100644 --- a/examples/common/OpenGLWidget.h +++ b/examples/common/OpenGLWidget.h @@ -92,8 +92,8 @@ public: // Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code // we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here. glEnableVertexAttribArray(2); //We're talking about shader attribute '2' - GLint size = (std::min)(sizeof(typename MeshType::VertexType::VoxelType), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type) - glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, material))); + GLint size = (std::min)(sizeof(typename MeshType::VertexType::DataType), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type) + glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, data))); // We're done uploading and can now unbind. glBindVertexArray(0); diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl index da7803cd..7fe9286b 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl @@ -222,7 +222,7 @@ namespace PolyVox //No vertices matched and we've now hit an empty space. Fill it by creating a vertex. The 0.5f offset is because vertices set between voxels in order to build cubes around them. CubicVertex cubicVertex; cubicVertex.position.setElements(static_cast(uX), static_cast(uY), static_cast(uZ)); - cubicVertex.material = uMaterialIn; + cubicVertex.data = uMaterialIn; rEntry.iIndex = m_meshCurrent->addVertex(cubicVertex); rEntry.uMaterial = uMaterialIn; @@ -275,9 +275,9 @@ namespace PolyVox template bool CubicSurfaceExtractor::mergeQuads(Quad& q1, Quad& q2) { - //All four vertices of a given quad have the same material, + //All four vertices of a given quad have the same data, //so just check that the first pair of vertices match. - if(m_meshCurrent->getVertices()[q1.vertices[0]].material == m_meshCurrent->getVertices()[q2.vertices[0]].material) + if (m_meshCurrent->getVertices()[q1.vertices[0]].data == m_meshCurrent->getVertices()[q2.vertices[0]].data) { //Now check whether quad 2 is adjacent to quad one by comparing vertices. //Adjacent quads must share two vertices, and the second quad could be to the diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl index bbe18ad2..1b50431e 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl @@ -463,7 +463,7 @@ namespace PolyVox MarchingCubesVertex surfaceVertex; surfaceVertex.position = v3dPositionAsUint; surfaceVertex.normal = v3dNormal; - surfaceVertex.material = uMaterial; + surfaceVertex.data = uMaterial; const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); m_pCurrentVertexIndicesX[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; @@ -497,7 +497,7 @@ namespace PolyVox MarchingCubesVertex surfaceVertex; surfaceVertex.position = v3dPositionAsUint; surfaceVertex.normal = v3dNormal; - surfaceVertex.material = uMaterial; + surfaceVertex.data = uMaterial; uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); m_pCurrentVertexIndicesY[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; @@ -530,7 +530,7 @@ namespace PolyVox MarchingCubesVertex surfaceVertex; surfaceVertex.position = v3dPositionAsUint; surfaceVertex.normal = v3dNormal; - surfaceVertex.material = uMaterial; + surfaceVertex.data = uMaterial; const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); m_pCurrentVertexIndicesZ[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h index d23f7716..f0ce39ea 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h @@ -102,9 +102,9 @@ namespace PolyVox std::shared_ptr< Mesh > extractSubset(Mesh& inputMesh, std::set setMaterials); template - Mesh< Vertex< typename MeshType::VertexType::VoxelType > > decode(const MeshType& mesh) + Mesh< Vertex< typename MeshType::VertexType::DataType > > decode(const MeshType& mesh) { - Mesh< Vertex< typename MeshType::VertexType::VoxelType > > result; + Mesh< Vertex< typename MeshType::VertexType::DataType > > result; result.m_vecVertices.resize(mesh.m_vecVertices.size()); for(uint32_t ct = 0; ct < mesh.m_vecVertices.size(); ct++) diff --git a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h index 1044f472..dcab6c17 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h +++ b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h @@ -36,68 +36,68 @@ namespace PolyVox #ifdef SWIG struct Vertex #else - template + template struct POLYVOX_API Vertex #endif { - typedef _VoxelType VoxelType; + typedef _DataType DataType; Vector3DFloat position; Vector3DFloat normal; - VoxelType material; + DataType data; }; #ifdef SWIG struct CubicVertex #else - template + template struct POLYVOX_API CubicVertex #endif { - typedef _VoxelType VoxelType; + typedef _DataType DataType; Vector3DUint8 position; uint8_t normal; - VoxelType material; + DataType data; }; #ifdef SWIG struct MarchingCubesVertex #else - template + template struct POLYVOX_API MarchingCubesVertex #endif { - typedef _VoxelType VoxelType; + typedef _DataType DataType; Vector3DUint16 position; Vector3DFloat normal; - VoxelType material; + DataType data; }; // Hopefully the compiler will implement the 'Return value optimization' here, but // performance critical code will most likely decode the vertices in a shader anyway. - template - Vertex decode(const CubicVertex& cubicVertex) + template + Vertex decode(const CubicVertex& cubicVertex) { - Vertex result; + Vertex result; Vector3DUint8 temp = cubicVertex.position; // For some reason we can't cast Vector3DUint8 to Vector3DFloat - investigate why. result.position = Vector3DFloat(temp.getX(), temp.getY(), temp.getZ()) - Vector3DFloat(0.5, 0.5, 0.5); //result.normal = cubicVertex.normal; - result.material = cubicVertex.material; + result.data = cubicVertex.data; return result; } // Hopefully the compiler will implement the 'Return value optimization' here, but // performance critical code will most likely decode the vertices in a shader anyway. - template - Vertex decode(const MarchingCubesVertex& cubicVertex) + template + Vertex decode(const MarchingCubesVertex& cubicVertex) { - Vertex result; + Vertex result; result.position = Vector3DFloat(cubicVertex.position.getX(), cubicVertex.position.getY(), cubicVertex.position.getZ()); result.position *= (1.0 / 256.0); result.normal = cubicVertex.normal; - result.material = cubicVertex.material; + result.data = cubicVertex.data; return result; } } diff --git a/tests/TestSurfaceExtractor.cpp b/tests/TestSurfaceExtractor.cpp index e621fa99..682fa0dc 100644 --- a/tests/TestSurfaceExtractor.cpp +++ b/tests/TestSurfaceExtractor.cpp @@ -162,7 +162,7 @@ void TestSurfaceExtractor::testExecute() const static uint32_t uExpectedVertices = 4731; const static uint32_t uExpectedIndices = 12810; const static uint32_t uMaterialToCheck = 3000; - const static float fExpectedMaterial = 42.0f; + const static float fExpectedData = 42.0f; const static float fNoMaterial = 1.0f; Mesh > mesh; @@ -172,58 +172,58 @@ void TestSurfaceExtractor::testExecute() } QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); + QCOMPARE(mesh.getVertices()[uMaterialToCheck].data, static_cast(fExpectedData)); auto mesh1 = testForType(); QCOMPARE(mesh1.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh1.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh1.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); + QCOMPARE(mesh1.getVertices()[uMaterialToCheck].data, static_cast(fExpectedData)); auto mesh2 = testForType(); QCOMPARE(mesh2.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh2.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh2.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); + QCOMPARE(mesh2.getVertices()[uMaterialToCheck].data, static_cast(fExpectedData)); auto mesh3 = testForType(); QCOMPARE(mesh3.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh3.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh3.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); + QCOMPARE(mesh3.getVertices()[uMaterialToCheck].data, static_cast(fExpectedData)); auto mesh4 = testForType(); QCOMPARE(mesh4.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh4.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh4.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); + QCOMPARE(mesh4.getVertices()[uMaterialToCheck].data, static_cast(fExpectedData)); auto mesh5 = testForType(); QCOMPARE(mesh5.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh5.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh5.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); + QCOMPARE(mesh5.getVertices()[uMaterialToCheck].data, static_cast(fExpectedData)); auto mesh6 = testForType(); QCOMPARE(mesh6.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh6.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh6.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); + QCOMPARE(mesh6.getVertices()[uMaterialToCheck].data, static_cast(fExpectedData)); auto mesh7 = testForType(); QCOMPARE(mesh7.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh7.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh7.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); + QCOMPARE(mesh7.getVertices()[uMaterialToCheck].data, static_cast(fExpectedData)); auto mesh8 = testForType(); QCOMPARE(mesh8.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh8.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh8.getVertices()[uMaterialToCheck].material, static_cast(fNoMaterial)); + QCOMPARE(mesh8.getVertices()[uMaterialToCheck].data, static_cast(fExpectedData)); auto mesh9 = testForType(); QCOMPARE(mesh9.getNoOfVertices(), uExpectedVertices); QCOMPARE(mesh9.getNoOfIndices(), uExpectedIndices); - //QCOMPARE(mesh9.getVertices()[uMaterialToCheck].material, fExpectedMaterial); + //QCOMPARE(mesh9.getVertices()[uMaterialToCheck].data, fExpectedMaterial); //Test whether the CustomSurfaceExtractor works. /*testCustomController(floatMesh); QCOMPARE(floatMesh.getNoOfVertices(), uExpectedVertices); QCOMPARE(floatMesh.getNoOfIndices(), uExpectedIndices); - QCOMPARE(floatMesh.getVertices()[uMaterialToCheck].material, fNoMaterial);*/ + QCOMPARE(floatMesh.getVertices()[uMaterialToCheck].data, fExpectedData);*/ } QTEST_MAIN(TestSurfaceExtractor) From b635e9d29dd51e23b572eb99d599ae9688a4c923 Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 29 May 2014 12:20:33 +0200 Subject: [PATCH 49/72] Copied BasicExample as base for new 'DecodeOnGPU' example. --- CMakeLists.txt | 1 + examples/DecodeOnGPU/CMakeLists.txt | 74 ++++++++++++++++++++++ examples/DecodeOnGPU/main.cpp | 95 +++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 examples/DecodeOnGPU/CMakeLists.txt create mode 100644 examples/DecodeOnGPU/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6691be4a..ae1cdeb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,6 +72,7 @@ IF(ENABLE_EXAMPLES AND QT_QTOPENGL_FOUND) ADD_SUBDIRECTORY(examples/Paging) ADD_SUBDIRECTORY(examples/OpenGL) ADD_SUBDIRECTORY(examples/SmoothLOD) + ADD_SUBDIRECTORY(examples/DecodeOnGPU) ADD_SUBDIRECTORY(examples/Python) SET(BUILD_EXAMPLES ON) ELSE() diff --git a/examples/DecodeOnGPU/CMakeLists.txt b/examples/DecodeOnGPU/CMakeLists.txt new file mode 100644 index 00000000..fb298715 --- /dev/null +++ b/examples/DecodeOnGPU/CMakeLists.txt @@ -0,0 +1,74 @@ +# Copyright (c) 2010-2012 David Williams +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source +# distribution. + +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +PROJECT(DecodeOnGPUExample) + +#Projects source files +SET(SRC_FILES + main.cpp + ../common/OpenGLWidget.cpp +) + +#Projects headers files +SET(INC_FILES + OpenGLWidget.h +) + +add_definitions(-DGLEW_STATIC) + +FIND_PACKAGE(OpenGL REQUIRED) + +#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location) +INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR}) +LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR}) + +#This will include the shader files inside the compiled binary +QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc) + +# Put the resources in a seperate folder in Visual Studio +SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC}) + +#Build +ADD_EXECUTABLE(DecodeOnGPUExample ${SRC_FILES} ${COMMON_RESOURCES_RCC}) +IF(MSVC) + SET_TARGET_PROPERTIES(DecodeOnGPUExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127") +ENDIF(MSVC) +TARGET_LINK_LIBRARIES(DecodeOnGPUExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore) +SET_PROPERTY(TARGET DecodeOnGPUExample PROPERTY FOLDER "Examples") + +#Install - Only install the example in Windows +IF(WIN32) + INSTALL(TARGETS DecodeOnGPUExample + RUNTIME DESTINATION Examples/OpenGL/bin + LIBRARY DESTINATION Examples/OpenGL/lib + ARCHIVE DESTINATION Examples/OpenGL/lib + COMPONENT example + ) + + #.dlls should be installed in shared builds. + #INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release) + #INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release) + + #INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug) + #INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug) +ENDIF(WIN32) diff --git a/examples/DecodeOnGPU/main.cpp b/examples/DecodeOnGPU/main.cpp new file mode 100644 index 00000000..a13da717 --- /dev/null +++ b/examples/DecodeOnGPU/main.cpp @@ -0,0 +1,95 @@ +/******************************************************************************* +Copyright (c) 2005-2009 David Williams + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*******************************************************************************/ + +#include "OpenGLWidget.h" + +#include "PolyVoxCore/CubicSurfaceExtractor.h" +#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h" +#include "PolyVoxCore/Mesh.h" +#include "PolyVoxCore/SimpleVolume.h" + +#include + +//Use the PolyVox namespace +using namespace PolyVox; + +void createSphereInVolume(SimpleVolume& volData, float fRadius) +{ + //This vector hold the position of the center of the volume + Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2); + + //This three-level for loop iterates over every voxel in the volume + for (int z = 0; z < volData.getDepth(); z++) + { + for (int y = 0; y < volData.getHeight(); y++) + { + for (int x = 0; x < volData.getWidth(); x++) + { + //Store our current position as a vector... + Vector3DFloat v3dCurrentPos(x,y,z); + //And compute how far the current position is from the center of the volume + float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length(); + + uint8_t uVoxelValue = 0; + + //If the current voxel is less than 'radius' units from the center then we make it solid. + if(fDistToCenter <= fRadius) + { + //Our new voxel value + uVoxelValue = 255; + } + + //Wrte the voxel value into the volume + volData.setVoxelAt(x, y, z, uVoxelValue); + } + } + } +} + +int main(int argc, char *argv[]) +{ + //Create and show the Qt OpenGL window + QApplication app(argc, argv); + OpenGLWidget openGLWidget(0); + openGLWidget.show(); + + //Create an empty volume and then place a sphere in it + SimpleVolume volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(63, 63, 63))); + createSphereInVolume(volData, 30); + + // Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see. + auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion()); + //auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion()); + + // The surface extractor outputs the mesh in an efficient compressed format which is not directly suitable for rendering. The easiest approach is to + // decode this on the CPU as shown below, though more advanced applications can upload the compressed mesh to the GPU and decompress in shader code. + auto decodedMesh = decode(mesh); + + //Pass the surface to the OpenGL window + openGLWidget.addMesh(decodedMesh); + //openGLWidget.addMesh(mesh2); + openGLWidget.setViewableRegion(volData.getEnclosingRegion()); + + //Run the message pump. + return app.exec(); +} \ No newline at end of file From f945fd4ce4feb4f5b0af60510fe656e36f0a836f Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 29 May 2014 12:38:43 +0200 Subject: [PATCH 50/72] Work on example to decode vertices on the GPU. --- examples/DecodeOnGPU/main.cpp | 57 ++++++++++++++++++++++++++++++++-- examples/common/OpenGLWidget.h | 19 +++++++----- 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/examples/DecodeOnGPU/main.cpp b/examples/DecodeOnGPU/main.cpp index a13da717..83950b1b 100644 --- a/examples/DecodeOnGPU/main.cpp +++ b/examples/DecodeOnGPU/main.cpp @@ -66,6 +66,58 @@ void createSphereInVolume(SimpleVolume& volData, float fRadius) } } +OpenGLMeshData buildOpenGLMeshData(const PolyVox::Mesh< PolyVox::Vertex< uint8_t > >& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f) +{ + // Convienient access to the vertices and indices + const auto& vecIndices = surfaceMesh.getIndices(); + const auto& vecVertices = surfaceMesh.getVertices(); + + // This struct holds the OpenGL properties (buffer handles, etc) which will be used + // to render our mesh. We copy the data from the PolyVox mesh into this structure. + OpenGLMeshData meshData; + + // Create the VAO for the mesh + glGenVertexArrays(1, &(meshData.vertexArrayObject)); + glBindVertexArray(meshData.vertexArrayObject); + + // The GL_ARRAY_BUFFER will contain the list of vertex positions + glGenBuffers(1, &(meshData.vertexBuffer)); + glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(Vertex< uint8_t >), vecVertices.data(), GL_STATIC_DRAW); + + // and GL_ELEMENT_ARRAY_BUFFER will contain the indices + glGenBuffers(1, &(meshData.indexBuffer)); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshData.indexBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), vecIndices.data(), GL_STATIC_DRAW); + + // Every surface extractor outputs valid positions for the vertices, so tell OpenGL how these are laid out + glEnableVertexAttribArray(0); // Attrib '0' is the vertex positions + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex< uint8_t >), (GLvoid*)(offsetof(Vertex< uint8_t >, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + + // Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor + // does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the + // shader. This is mostly just to simplify this example code - in a real application you will know whether your + // chosen surface extractor generates normals and can skip uploading them if not. + glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals. + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex< uint8_t >), (GLvoid*)(offsetof(Vertex< uint8_t >, normal))); + + // Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code + // we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here. + glEnableVertexAttribArray(2); //We're talking about shader attribute '2' + GLint size = (std::min)(sizeof(uint8_t), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type) + glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(Vertex< uint8_t >), (GLvoid*)(offsetof(Vertex< uint8_t >, data))); + + // We're done uploading and can now unbind. + glBindVertexArray(0); + + // A few additional properties can be copied across for use during rendering. + meshData.noOfIndices = vecIndices.size(); + meshData.translation = QVector3D(translation.getX(), translation.getY(), translation.getZ()); + meshData.scale = scale; + + return meshData; +} + int main(int argc, char *argv[]) { //Create and show the Qt OpenGL window @@ -86,8 +138,9 @@ int main(int argc, char *argv[]) auto decodedMesh = decode(mesh); //Pass the surface to the OpenGL window - openGLWidget.addMesh(decodedMesh); - //openGLWidget.addMesh(mesh2); + OpenGLMeshData meshData = buildOpenGLMeshData(decodedMesh); + openGLWidget.addMeshData(meshData); + openGLWidget.setViewableRegion(volData.getEnclosingRegion()); //Run the message pump. diff --git a/examples/common/OpenGLWidget.h b/examples/common/OpenGLWidget.h index 930cb3d8..a0150556 100644 --- a/examples/common/OpenGLWidget.h +++ b/examples/common/OpenGLWidget.h @@ -53,8 +53,8 @@ public: OpenGLWidget(QWidget *parent); // Convert a PolyVox mesh to OpenGL index/vertex buffers. Inlined because it's templatised. - template - void addMesh(const MeshType& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f) + template + void addMesh(const PolyVox::Mesh< PolyVox::Vertex< DataType > >& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f) { // Convienient access to the vertices and indices const auto& vecIndices = surfaceMesh.getIndices(); @@ -71,7 +71,7 @@ public: // The GL_ARRAY_BUFFER will contain the list of vertex positions glGenBuffers(1, &(meshData.vertexBuffer)); glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(typename MeshType::VertexType), vecVertices.data(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(Vertex< DataType >), vecVertices.data(), GL_STATIC_DRAW); // and GL_ELEMENT_ARRAY_BUFFER will contain the indices glGenBuffers(1, &(meshData.indexBuffer)); @@ -80,20 +80,20 @@ public: // Every surface extractor outputs valid positions for the vertices, so tell OpenGL how these are laid out glEnableVertexAttribArray(0); // Attrib '0' is the vertex positions - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex< DataType >), (GLvoid*)(offsetof(Vertex< DataType >, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) // Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor // does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the // shader. This is mostly just to simplify this example code - in a real application you will know whether your // chosen surface extractor generates normals and can skip uploading them if not. glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals. - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, normal))); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex< DataType >), (GLvoid*)(offsetof(Vertex< DataType >, normal))); // Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code // we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here. glEnableVertexAttribArray(2); //We're talking about shader attribute '2' - GLint size = (std::min)(sizeof(typename MeshType::VertexType::DataType), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type) - glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, data))); + GLint size = (std::min)(sizeof(DataType), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type) + glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(Vertex< DataType >), (GLvoid*)(offsetof(Vertex< DataType >, data))); // We're done uploading and can now unbind. glBindVertexArray(0); @@ -104,6 +104,11 @@ public: meshData.scale = scale; // Now add the mesh to the list of meshes to render. + addMeshData(meshData); + } + + void addMeshData(OpenGLMeshData meshData) + { mMeshData.push_back(meshData); } From 8604d1209eb2e2ebbd260b65c27f550887b9c95a Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 29 May 2014 14:23:22 +0200 Subject: [PATCH 51/72] Initial version of decoding shaders. --- examples/DecodeOnGPU/CMakeLists.txt | 5 +++-- examples/DecodeOnGPU/decode.frag | 19 +++++++++++++++++++ examples/DecodeOnGPU/decode.qrc | 6 ++++++ examples/DecodeOnGPU/decode.vert | 20 ++++++++++++++++++++ examples/DecodeOnGPU/main.cpp | 16 ++++++++++++++++ 5 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 examples/DecodeOnGPU/decode.frag create mode 100644 examples/DecodeOnGPU/decode.qrc create mode 100644 examples/DecodeOnGPU/decode.vert diff --git a/examples/DecodeOnGPU/CMakeLists.txt b/examples/DecodeOnGPU/CMakeLists.txt index fb298715..07f87101 100644 --- a/examples/DecodeOnGPU/CMakeLists.txt +++ b/examples/DecodeOnGPU/CMakeLists.txt @@ -44,12 +44,13 @@ LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR}) #This will include the shader files inside the compiled binary QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc) +QT4_ADD_RESOURCES(DECODE_RESOURCES_RCC decode.qrc) # Put the resources in a seperate folder in Visual Studio -SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC}) +SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC} decode.qrc ${DECODE_RESOURCES_RCC}) #Build -ADD_EXECUTABLE(DecodeOnGPUExample ${SRC_FILES} ${COMMON_RESOURCES_RCC}) +ADD_EXECUTABLE(DecodeOnGPUExample ${SRC_FILES} ${COMMON_RESOURCES_RCC} ${DECODE_RESOURCES_RCC}) IF(MSVC) SET_TARGET_PROPERTIES(DecodeOnGPUExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127") ENDIF(MSVC) diff --git a/examples/DecodeOnGPU/decode.frag b/examples/DecodeOnGPU/decode.frag new file mode 100644 index 00000000..c9cbf215 --- /dev/null +++ b/examples/DecodeOnGPU/decode.frag @@ -0,0 +1,19 @@ +#version 130 + +// Passed in from the vertex shader +in vec4 worldPosition; +in vec4 worldNormal; + +// the color that gets written to the display +out vec4 outputColor; + +void main() +{ + // Again, for the purposes of these examples we cannot be sure that per-vertex normals are provided. A sensible fallback + // is to use this little trick to compute per-fragment flat-shaded normals from the world positions using derivative operations. + vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz))); + + // We are just using the normal as the output color, and making it lighter so it looks a bit nicer. + // Obviously a real shader would also do texuring, lighting, or whatever is required for the application. + outputColor = vec4(abs(normal) * 0.5 + vec3(0.5, 0.5, 0.5), 1.0); +} diff --git a/examples/DecodeOnGPU/decode.qrc b/examples/DecodeOnGPU/decode.qrc new file mode 100644 index 00000000..f29bc1ad --- /dev/null +++ b/examples/DecodeOnGPU/decode.qrc @@ -0,0 +1,6 @@ + + + decode.vert + decode.frag + + diff --git a/examples/DecodeOnGPU/decode.vert b/examples/DecodeOnGPU/decode.vert new file mode 100644 index 00000000..94d35f44 --- /dev/null +++ b/examples/DecodeOnGPU/decode.vert @@ -0,0 +1,20 @@ +#version 140 + +in vec4 position; // This will be the position of the vertex in model-space + +// The usual matrices are provided +uniform mat4 cameraToClipMatrix; +uniform mat4 worldToCameraMatrix; +uniform mat4 modelToWorldMatrix; + +// This will be used by the fragment shader to calculate flat-shaded normals. This is an unconventional approach +// but we use it in this example framework because not all surface extractor generate surface normals. +out vec4 worldPosition; + +void main() +{ + // Standard sequence of OpenGL transformations. + worldPosition = modelToWorldMatrix * position; + vec4 cameraPosition = worldToCameraMatrix * worldPosition; + gl_Position = cameraToClipMatrix * cameraPosition; +} diff --git a/examples/DecodeOnGPU/main.cpp b/examples/DecodeOnGPU/main.cpp index 83950b1b..3a36fd48 100644 --- a/examples/DecodeOnGPU/main.cpp +++ b/examples/DecodeOnGPU/main.cpp @@ -125,6 +125,22 @@ int main(int argc, char *argv[]) OpenGLWidget openGLWidget(0); openGLWidget.show(); + QSharedPointer shader(new QGLShaderProgram); + + if (!shader->addShaderFromSourceFile(QGLShader::Vertex, ":/decode.vert")) + { + std::cerr << shader->log().toStdString() << std::endl; + exit(EXIT_FAILURE); + } + + if (!shader->addShaderFromSourceFile(QGLShader::Fragment, ":/decode.frag")) + { + std::cerr << shader->log().toStdString() << std::endl; + exit(EXIT_FAILURE); + } + + openGLWidget.setShader(shader); + //Create an empty volume and then place a sphere in it SimpleVolume volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(63, 63, 63))); createSphereInVolume(volData, 30); From e40eb6d7620b572ee10572f26fb8a625fe5da1be Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 29 May 2014 19:29:15 +0200 Subject: [PATCH 52/72] Work on GPU decoding. --- examples/DecodeOnGPU/decode.vert | 7 ++++-- examples/DecodeOnGPU/main.cpp | 22 +++++++++++-------- .../MarchingCubesSurfaceExtractor.inl | 12 +++++----- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/examples/DecodeOnGPU/decode.vert b/examples/DecodeOnGPU/decode.vert index 94d35f44..de61bc42 100644 --- a/examples/DecodeOnGPU/decode.vert +++ b/examples/DecodeOnGPU/decode.vert @@ -1,6 +1,6 @@ #version 140 -in vec4 position; // This will be the position of the vertex in model-space +in uvec4 position; // This will be the position of the vertex in model-space // The usual matrices are provided uniform mat4 cameraToClipMatrix; @@ -13,8 +13,11 @@ out vec4 worldPosition; void main() { + vec4 decodedPosition = position; + decodedPosition.xyz = decodedPosition.xyz * (1.0 / 256.0); + // Standard sequence of OpenGL transformations. - worldPosition = modelToWorldMatrix * position; + worldPosition = modelToWorldMatrix * decodedPosition; vec4 cameraPosition = worldToCameraMatrix * worldPosition; gl_Position = cameraToClipMatrix * cameraPosition; } diff --git a/examples/DecodeOnGPU/main.cpp b/examples/DecodeOnGPU/main.cpp index 3a36fd48..fd1e0b16 100644 --- a/examples/DecodeOnGPU/main.cpp +++ b/examples/DecodeOnGPU/main.cpp @@ -66,7 +66,7 @@ void createSphereInVolume(SimpleVolume& volData, float fRadius) } } -OpenGLMeshData buildOpenGLMeshData(const PolyVox::Mesh< PolyVox::Vertex< uint8_t > >& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f) +OpenGLMeshData buildOpenGLMeshData(const PolyVox::Mesh< PolyVox::MarchingCubesVertex< uint8_t > >& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f) { // Convienient access to the vertices and indices const auto& vecIndices = surfaceMesh.getIndices(); @@ -83,7 +83,7 @@ OpenGLMeshData buildOpenGLMeshData(const PolyVox::Mesh< PolyVox::Vertex< uint8_t // The GL_ARRAY_BUFFER will contain the list of vertex positions glGenBuffers(1, &(meshData.vertexBuffer)); glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(Vertex< uint8_t >), vecVertices.data(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(MarchingCubesVertex< uint8_t >), vecVertices.data(), GL_STATIC_DRAW); // and GL_ELEMENT_ARRAY_BUFFER will contain the indices glGenBuffers(1, &(meshData.indexBuffer)); @@ -92,20 +92,20 @@ OpenGLMeshData buildOpenGLMeshData(const PolyVox::Mesh< PolyVox::Vertex< uint8_t // Every surface extractor outputs valid positions for the vertices, so tell OpenGL how these are laid out glEnableVertexAttribArray(0); // Attrib '0' is the vertex positions - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex< uint8_t >), (GLvoid*)(offsetof(Vertex< uint8_t >, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + glVertexAttribIPointer(0, 3, GL_UNSIGNED_SHORT, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) // Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor // does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the // shader. This is mostly just to simplify this example code - in a real application you will know whether your // chosen surface extractor generates normals and can skip uploading them if not. glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals. - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex< uint8_t >), (GLvoid*)(offsetof(Vertex< uint8_t >, normal))); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, normal))); // Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code // we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here. glEnableVertexAttribArray(2); //We're talking about shader attribute '2' GLint size = (std::min)(sizeof(uint8_t), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type) - glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(Vertex< uint8_t >), (GLvoid*)(offsetof(Vertex< uint8_t >, data))); + glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, data))); // We're done uploading and can now unbind. glBindVertexArray(0); @@ -133,12 +133,16 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } + std::cout << shader->log().toStdString() << std::endl; + if (!shader->addShaderFromSourceFile(QGLShader::Fragment, ":/decode.frag")) { std::cerr << shader->log().toStdString() << std::endl; exit(EXIT_FAILURE); } + std::cout << shader->log().toStdString() << std::endl; + openGLWidget.setShader(shader); //Create an empty volume and then place a sphere in it @@ -146,15 +150,15 @@ int main(int argc, char *argv[]) createSphereInVolume(volData, 30); // Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see. - auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion()); - //auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion()); + //auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion()); + auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion()); // The surface extractor outputs the mesh in an efficient compressed format which is not directly suitable for rendering. The easiest approach is to // decode this on the CPU as shown below, though more advanced applications can upload the compressed mesh to the GPU and decompress in shader code. - auto decodedMesh = decode(mesh); + //auto decodedMesh = decode(mesh); //Pass the surface to the OpenGL window - OpenGLMeshData meshData = buildOpenGLMeshData(decodedMesh); + OpenGLMeshData meshData = buildOpenGLMeshData(mesh); openGLWidget.addMeshData(meshData); openGLWidget.setViewableRegion(volData.getEnclosingRegion()); diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl index 1b50431e..3fedba49 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl @@ -446,7 +446,7 @@ namespace PolyVox const float fInterp = static_cast(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast(m_controller.convertToDensity(v100) - m_controller.convertToDensity(v000)); const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerX()) + fInterp, static_cast(iYVolSpace - m_regSizeInVoxels.getLowerY()), static_cast(iZVolSpace - m_regSizeInCells.getLowerZ())); - const Vector3DUint16 v3dPositionAsUint(static_cast(v3dPosition.getX() * 256.0f), static_cast(v3dPosition.getY() * 256.0f), static_cast(v3dPosition.getZ() * 256.0f)); + const Vector3DUint16 v3dScaledPosition(static_cast(v3dPosition.getX() * 256.0f), static_cast(v3dPosition.getY() * 256.0f), static_cast(v3dPosition.getZ() * 256.0f)); Vector3DFloat v3dNormal = (n100*fInterp) + (n000*(1-fInterp)); @@ -461,7 +461,7 @@ namespace PolyVox const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v100, fInterp); MarchingCubesVertex surfaceVertex; - surfaceVertex.position = v3dPositionAsUint; + surfaceVertex.position = v3dScaledPosition; surfaceVertex.normal = v3dNormal; surfaceVertex.data = uMaterial; @@ -480,7 +480,7 @@ namespace PolyVox const float fInterp = static_cast(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast(m_controller.convertToDensity(v010) - m_controller.convertToDensity(v000)); const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerX()), static_cast(iYVolSpace - m_regSizeInVoxels.getLowerY()) + fInterp, static_cast(iZVolSpace - m_regSizeInVoxels.getLowerZ())); - const Vector3DUint16 v3dPositionAsUint(static_cast(v3dPosition.getX() * 256.0f), static_cast(v3dPosition.getY() * 256.0f), static_cast(v3dPosition.getZ() * 256.0f)); + const Vector3DUint16 v3dScaledPosition(static_cast(v3dPosition.getX() * 256.0f), static_cast(v3dPosition.getY() * 256.0f), static_cast(v3dPosition.getZ() * 256.0f)); Vector3DFloat v3dNormal = (n010*fInterp) + (n000*(1-fInterp)); @@ -495,7 +495,7 @@ namespace PolyVox const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v010, fInterp); MarchingCubesVertex surfaceVertex; - surfaceVertex.position = v3dPositionAsUint; + surfaceVertex.position = v3dScaledPosition; surfaceVertex.normal = v3dNormal; surfaceVertex.data = uMaterial; @@ -514,7 +514,7 @@ namespace PolyVox const float fInterp = static_cast(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast(m_controller.convertToDensity(v001) - m_controller.convertToDensity(v000)); const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerX()), static_cast(iYVolSpace - m_regSizeInVoxels.getLowerY()), static_cast(iZVolSpace - m_regSizeInVoxels.getLowerZ()) + fInterp); - const Vector3DUint16 v3dPositionAsUint(static_cast(v3dPosition.getX() * 256.0f), static_cast(v3dPosition.getY() * 256.0f), static_cast(v3dPosition.getZ() * 256.0f)); + const Vector3DUint16 v3dScaledPosition(static_cast(v3dPosition.getX() * 256.0f), static_cast(v3dPosition.getY() * 256.0f), static_cast(v3dPosition.getZ() * 256.0f)); Vector3DFloat v3dNormal = (n001*fInterp) + (n000*(1-fInterp)); // The gradient for a voxel can be zero (e.g. solid voxel surrounded by empty ones) and so @@ -528,7 +528,7 @@ namespace PolyVox const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v001, fInterp); MarchingCubesVertex surfaceVertex; - surfaceVertex.position = v3dPositionAsUint; + surfaceVertex.position = v3dScaledPosition; surfaceVertex.normal = v3dNormal; surfaceVertex.data = uMaterial; From a6a1c4dbb74c2c10baf4fef120a4206a3fd31b52 Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 29 May 2014 19:34:43 +0200 Subject: [PATCH 53/72] Getting ready to decode normal. --- examples/DecodeOnGPU/decode.frag | 4 ++-- examples/DecodeOnGPU/decode.vert | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/DecodeOnGPU/decode.frag b/examples/DecodeOnGPU/decode.frag index c9cbf215..fb576125 100644 --- a/examples/DecodeOnGPU/decode.frag +++ b/examples/DecodeOnGPU/decode.frag @@ -11,9 +11,9 @@ void main() { // Again, for the purposes of these examples we cannot be sure that per-vertex normals are provided. A sensible fallback // is to use this little trick to compute per-fragment flat-shaded normals from the world positions using derivative operations. - vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz))); + //vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz))); // We are just using the normal as the output color, and making it lighter so it looks a bit nicer. // Obviously a real shader would also do texuring, lighting, or whatever is required for the application. - outputColor = vec4(abs(normal) * 0.5 + vec3(0.5, 0.5, 0.5), 1.0); + outputColor = vec4(abs(worldNormal.xyz) * 0.5 + vec3(0.5, 0.5, 0.5), 1.0); } diff --git a/examples/DecodeOnGPU/decode.vert b/examples/DecodeOnGPU/decode.vert index de61bc42..00675617 100644 --- a/examples/DecodeOnGPU/decode.vert +++ b/examples/DecodeOnGPU/decode.vert @@ -1,6 +1,7 @@ #version 140 in uvec4 position; // This will be the position of the vertex in model-space +in vec4 normal; // The usual matrices are provided uniform mat4 cameraToClipMatrix; @@ -10,12 +11,15 @@ uniform mat4 modelToWorldMatrix; // This will be used by the fragment shader to calculate flat-shaded normals. This is an unconventional approach // but we use it in this example framework because not all surface extractor generate surface normals. out vec4 worldPosition; +out vec4 worldNormal; void main() { vec4 decodedPosition = position; decodedPosition.xyz = decodedPosition.xyz * (1.0 / 256.0); + worldNormal = normal; + // Standard sequence of OpenGL transformations. worldPosition = modelToWorldMatrix * decodedPosition; vec4 cameraPosition = worldToCameraMatrix * worldPosition; From 2c916300eaabbc550e5b741faa6c0dc751b59961 Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 29 May 2014 21:45:26 +0200 Subject: [PATCH 54/72] Work on encoded marching cubes normals. --- .../MarchingCubesSurfaceExtractor.inl | 33 +++++++++++++++++-- .../include/PolyVoxCore/VertexTypes.h | 17 +++++++--- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl index 3fedba49..9514e22e 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl @@ -457,12 +457,21 @@ namespace PolyVox v3dNormal.normalise(); } + v3dNormal += Vector3DFloat(1.0f, 1.0f, 1.0f); + uint16_t encodedX = static_cast(roundToNearestInteger(v3dNormal.getX() * 15.5f)); + uint16_t encodedY = static_cast(roundToNearestInteger(v3dNormal.getY() * 15.5f)); + uint16_t encodedZ = static_cast(roundToNearestInteger(v3dNormal.getZ() * 15.5f)); + POLYVOX_ASSERT(encodedX < 32, "Encoded value out of range"); + POLYVOX_ASSERT(encodedY < 32, "Encoded value out of range"); + POLYVOX_ASSERT(encodedZ < 32, "Encoded value out of range"); + uint16_t encodedNormal = (encodedX << 10) | (encodedY << 5) | encodedZ; + // Allow the controller to decide how the material should be derived from the voxels. const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v100, fInterp); MarchingCubesVertex surfaceVertex; surfaceVertex.position = v3dScaledPosition; - surfaceVertex.normal = v3dNormal; + surfaceVertex.normal = encodedNormal; surfaceVertex.data = uMaterial; const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); @@ -491,12 +500,21 @@ namespace PolyVox v3dNormal.normalise(); } + v3dNormal += Vector3DFloat(1.0f, 1.0f, 1.0f); + uint16_t encodedX = static_cast(roundToNearestInteger(v3dNormal.getX() * 15.5f)); + uint16_t encodedY = static_cast(roundToNearestInteger(v3dNormal.getY() * 15.5f)); + uint16_t encodedZ = static_cast(roundToNearestInteger(v3dNormal.getZ() * 15.5f)); + POLYVOX_ASSERT(encodedX < 32, "Encoded value out of range"); + POLYVOX_ASSERT(encodedY < 32, "Encoded value out of range"); + POLYVOX_ASSERT(encodedZ < 32, "Encoded value out of range"); + uint16_t encodedNormal = (encodedX << 10) | (encodedY << 5) | encodedZ; + // Allow the controller to decide how the material should be derived from the voxels. const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v010, fInterp); MarchingCubesVertex surfaceVertex; surfaceVertex.position = v3dScaledPosition; - surfaceVertex.normal = v3dNormal; + surfaceVertex.normal = encodedNormal; surfaceVertex.data = uMaterial; uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); @@ -524,12 +542,21 @@ namespace PolyVox v3dNormal.normalise(); } + v3dNormal += Vector3DFloat(1.0f, 1.0f, 1.0f); + uint16_t encodedX = static_cast(roundToNearestInteger(v3dNormal.getX() * 15.5f)); + uint16_t encodedY = static_cast(roundToNearestInteger(v3dNormal.getY() * 15.5f)); + uint16_t encodedZ = static_cast(roundToNearestInteger(v3dNormal.getZ() * 15.5f)); + POLYVOX_ASSERT(encodedX < 32, "Encoded value out of range"); + POLYVOX_ASSERT(encodedY < 32, "Encoded value out of range"); + POLYVOX_ASSERT(encodedZ < 32, "Encoded value out of range"); + uint16_t encodedNormal = (encodedX << 10) | (encodedY << 5) | encodedZ; + // Allow the controller to decide how the material should be derived from the voxels. const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v001, fInterp); MarchingCubesVertex surfaceVertex; surfaceVertex.position = v3dScaledPosition; - surfaceVertex.normal = v3dNormal; + surfaceVertex.normal = encodedNormal; surfaceVertex.data = uMaterial; const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); diff --git a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h index dcab6c17..a4c31b27 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h +++ b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h @@ -71,7 +71,7 @@ namespace PolyVox typedef _DataType DataType; Vector3DUint16 position; - Vector3DFloat normal; + uint16_t normal; DataType data; }; @@ -91,13 +91,20 @@ namespace PolyVox // Hopefully the compiler will implement the 'Return value optimization' here, but // performance critical code will most likely decode the vertices in a shader anyway. template - Vertex decode(const MarchingCubesVertex& cubicVertex) + Vertex decode(const MarchingCubesVertex& marchingCubesVertex) { Vertex result; - result.position = Vector3DFloat(cubicVertex.position.getX(), cubicVertex.position.getY(), cubicVertex.position.getZ()); + result.position = Vector3DFloat(marchingCubesVertex.position.getX(), marchingCubesVertex.position.getY(), marchingCubesVertex.position.getZ()); result.position *= (1.0 / 256.0); - result.normal = cubicVertex.normal; - result.data = cubicVertex.data; + + uint16_t encodedX = (marchingCubesVertex.normal >> 10) & 0x1F; + uint16_t encodedY = (marchingCubesVertex.normal >> 5) & 0x1F; + uint16_t encodedZ = (marchingCubesVertex.normal) & 0x1F; + result.normal = Vector3DFloat(encodedX, encodedY, encodedZ); + result.normal /= 15.5f; + result.normal -= Vector3DFloat(1.0f, 1.0f, 1.0f); + + result.data = marchingCubesVertex.data; return result; } } From 224c27de5092735a930515939cb9eec6b27b9a06 Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 29 May 2014 23:31:36 +0200 Subject: [PATCH 55/72] Got normal decoding working in shader. --- examples/DecodeOnGPU/decode.vert | 10 ++++++++-- examples/DecodeOnGPU/main.cpp | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/DecodeOnGPU/decode.vert b/examples/DecodeOnGPU/decode.vert index 00675617..5164468a 100644 --- a/examples/DecodeOnGPU/decode.vert +++ b/examples/DecodeOnGPU/decode.vert @@ -1,7 +1,7 @@ #version 140 in uvec4 position; // This will be the position of the vertex in model-space -in vec4 normal; +in uint normal; // The usual matrices are provided uniform mat4 cameraToClipMatrix; @@ -18,7 +18,13 @@ void main() vec4 decodedPosition = position; decodedPosition.xyz = decodedPosition.xyz * (1.0 / 256.0); - worldNormal = normal; + uint encodedX = (normal >> 10u) & 0x1Fu; + uint encodedY = (normal >> 5u) & 0x1Fu; + uint encodedZ = (normal) & 0x1Fu; + worldNormal.xyz = vec3(encodedX, encodedY, encodedZ); + worldNormal.xyz = worldNormal.xyz / 15.5; + worldNormal.xyz = worldNormal.xyz - vec3(1.0, 1.0, 1.0); + worldNormal.w = 1.0; // Standard sequence of OpenGL transformations. worldPosition = modelToWorldMatrix * decodedPosition; diff --git a/examples/DecodeOnGPU/main.cpp b/examples/DecodeOnGPU/main.cpp index fd1e0b16..f286efc2 100644 --- a/examples/DecodeOnGPU/main.cpp +++ b/examples/DecodeOnGPU/main.cpp @@ -99,7 +99,7 @@ OpenGLMeshData buildOpenGLMeshData(const PolyVox::Mesh< PolyVox::MarchingCubesVe // shader. This is mostly just to simplify this example code - in a real application you will know whether your // chosen surface extractor generates normals and can skip uploading them if not. glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals. - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, normal))); + glVertexAttribIPointer(1, 1, GL_UNSIGNED_SHORT, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, normal))); // Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code // we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here. From 4f1863eccbe349b304297a65170c744cad847a7d Mon Sep 17 00:00:00 2001 From: David Williams Date: Fri, 30 May 2014 16:36:24 +0200 Subject: [PATCH 56/72] Removed apparently-incorrect use of logging statements (crashing under Visual Studio). --- examples/DecodeOnGPU/main.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/DecodeOnGPU/main.cpp b/examples/DecodeOnGPU/main.cpp index f286efc2..3826543d 100644 --- a/examples/DecodeOnGPU/main.cpp +++ b/examples/DecodeOnGPU/main.cpp @@ -133,16 +133,12 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - std::cout << shader->log().toStdString() << std::endl; - if (!shader->addShaderFromSourceFile(QGLShader::Fragment, ":/decode.frag")) { std::cerr << shader->log().toStdString() << std::endl; exit(EXIT_FAILURE); } - std::cout << shader->log().toStdString() << std::endl; - openGLWidget.setShader(shader); //Create an empty volume and then place a sphere in it From 78ac1d12b55f589e68996bbc9777350548944d5a Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 1 Jun 2014 17:01:36 +0200 Subject: [PATCH 57/72] The new, more compact vertex types are specific to their respective surface extractors, so they belong in the corresponding source files. --- .../PolyVoxCore/CubicSurfaceExtractor.h | 28 +++++++++ .../MarchingCubesSurfaceExtractor.h | 35 +++++++++++ .../include/PolyVoxCore/VertexTypes.h | 61 ------------------- 3 files changed, 63 insertions(+), 61 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h index 03e973a3..efd001e4 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h @@ -32,9 +32,37 @@ freely, subject to the following restrictions: #include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these? #include "PolyVoxCore/DefaultIsQuadNeeded.h" #include "PolyVoxCore/Mesh.h" +#include "PolyVoxCore/VertexTypes.h" namespace PolyVox { +#ifdef SWIG + struct CubicVertex +#else + template + struct POLYVOX_API CubicVertex +#endif + { + typedef _DataType DataType; + + Vector3DUint8 position; + uint8_t normal; + DataType data; + }; + + // Hopefully the compiler will implement the 'Return value optimization' here, but + // performance critical code will most likely decode the vertices in a shader anyway. + template + Vertex decode(const CubicVertex& cubicVertex) + { + Vertex result; + Vector3DUint8 temp = cubicVertex.position; // For some reason we can't cast Vector3DUint8 to Vector3DFloat - investigate why. + result.position = Vector3DFloat(temp.getX(), temp.getY(), temp.getZ()) - Vector3DFloat(0.5, 0.5, 0.5); + //result.normal = cubicVertex.normal; + result.data = cubicVertex.data; + return result; + } + /// The CubicSurfaceExtractor creates a mesh in which each voxel appears to be rendered as a cube //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// Introduction diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h index 6510ac5c..a609326f 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h @@ -31,9 +31,44 @@ freely, subject to the following restrictions: #include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these? #include "PolyVoxCore/Mesh.h" #include "PolyVoxCore/DefaultMarchingCubesController.h" +#include "PolyVoxCore/VertexTypes.h" namespace PolyVox { +#ifdef SWIG + struct MarchingCubesVertex +#else + template + struct POLYVOX_API MarchingCubesVertex +#endif + { + typedef _DataType DataType; + + Vector3DUint16 position; + uint16_t normal; + DataType data; + }; + + // Hopefully the compiler will implement the 'Return value optimization' here, but + // performance critical code will most likely decode the vertices in a shader anyway. + template + Vertex decode(const MarchingCubesVertex& marchingCubesVertex) + { + Vertex result; + result.position = Vector3DFloat(marchingCubesVertex.position.getX(), marchingCubesVertex.position.getY(), marchingCubesVertex.position.getZ()); + result.position *= (1.0 / 256.0); + + uint16_t encodedX = (marchingCubesVertex.normal >> 10) & 0x1F; + uint16_t encodedY = (marchingCubesVertex.normal >> 5) & 0x1F; + uint16_t encodedZ = (marchingCubesVertex.normal) & 0x1F; + result.normal = Vector3DFloat(encodedX, encodedY, encodedZ); + result.normal /= 15.5f; + result.normal -= Vector3DFloat(1.0f, 1.0f, 1.0f); + + result.data = marchingCubesVertex.data; + return result; + } + template< typename VolumeType, typename Controller = DefaultMarchingCubesController > class MarchingCubesSurfaceExtractor { diff --git a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h index a4c31b27..964ff88d 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h +++ b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h @@ -46,67 +46,6 @@ namespace PolyVox Vector3DFloat normal; DataType data; }; - -#ifdef SWIG - struct CubicVertex -#else - template - struct POLYVOX_API CubicVertex -#endif - { - typedef _DataType DataType; - - Vector3DUint8 position; - uint8_t normal; - DataType data; - }; - -#ifdef SWIG - struct MarchingCubesVertex -#else - template - struct POLYVOX_API MarchingCubesVertex -#endif - { - typedef _DataType DataType; - - Vector3DUint16 position; - uint16_t normal; - DataType data; - }; - - // Hopefully the compiler will implement the 'Return value optimization' here, but - // performance critical code will most likely decode the vertices in a shader anyway. - template - Vertex decode(const CubicVertex& cubicVertex) - { - Vertex result; - Vector3DUint8 temp = cubicVertex.position; // For some reason we can't cast Vector3DUint8 to Vector3DFloat - investigate why. - result.position = Vector3DFloat(temp.getX(), temp.getY(), temp.getZ()) - Vector3DFloat(0.5, 0.5, 0.5); - //result.normal = cubicVertex.normal; - result.data = cubicVertex.data; - return result; - } - - // Hopefully the compiler will implement the 'Return value optimization' here, but - // performance critical code will most likely decode the vertices in a shader anyway. - template - Vertex decode(const MarchingCubesVertex& marchingCubesVertex) - { - Vertex result; - result.position = Vector3DFloat(marchingCubesVertex.position.getX(), marchingCubesVertex.position.getY(), marchingCubesVertex.position.getZ()); - result.position *= (1.0 / 256.0); - - uint16_t encodedX = (marchingCubesVertex.normal >> 10) & 0x1F; - uint16_t encodedY = (marchingCubesVertex.normal >> 5) & 0x1F; - uint16_t encodedZ = (marchingCubesVertex.normal) & 0x1F; - result.normal = Vector3DFloat(encodedX, encodedY, encodedZ); - result.normal /= 15.5f; - result.normal -= Vector3DFloat(1.0f, 1.0f, 1.0f); - - result.data = marchingCubesVertex.data; - return result; - } } #endif From 392ccab7034c9c67437bf552e4ce57e7db2da853 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 1 Jun 2014 17:23:08 +0200 Subject: [PATCH 58/72] Tidying decoding code. --- .../MarchingCubesSurfaceExtractor.h | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h index a609326f..78a48aac 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h @@ -49,23 +49,33 @@ namespace PolyVox DataType data; }; - // Hopefully the compiler will implement the 'Return value optimization' here, but - // performance critical code will most likely decode the vertices in a shader anyway. + Vector3DFloat decode(const Vector3DUint16& position) + { + Vector3DFloat result(position.getX(), position.getY(), position.getZ()); + result *= (1.0f / 256.0f); // Division is compile-time constant + return result; + } + + Vector3DFloat decode(const uint16_t normal) + { + uint16_t x = (normal >> 10) & 0x1F; + uint16_t y = (normal >> 5) & 0x1F; + uint16_t z = (normal) & 0x1F; + + Vector3DFloat result(x, y, z); + result *= (1.0f / 15.5f); // Division is compile-time constant + result -= Vector3DFloat(1.0f, 1.0f, 1.0f); + + return result; + } + template Vertex decode(const MarchingCubesVertex& marchingCubesVertex) { Vertex result; - result.position = Vector3DFloat(marchingCubesVertex.position.getX(), marchingCubesVertex.position.getY(), marchingCubesVertex.position.getZ()); - result.position *= (1.0 / 256.0); - - uint16_t encodedX = (marchingCubesVertex.normal >> 10) & 0x1F; - uint16_t encodedY = (marchingCubesVertex.normal >> 5) & 0x1F; - uint16_t encodedZ = (marchingCubesVertex.normal) & 0x1F; - result.normal = Vector3DFloat(encodedX, encodedY, encodedZ); - result.normal /= 15.5f; - result.normal -= Vector3DFloat(1.0f, 1.0f, 1.0f); - - result.data = marchingCubesVertex.data; + result.position = decode(marchingCubesVertex.position); + result.normal = decode(marchingCubesVertex.normal); + result.data = marchingCubesVertex.data; // Data is not encoded return result; } From b259b60de29f2f9ba456a10c10fa8bd0ad0636f8 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 1 Jun 2014 17:35:00 +0200 Subject: [PATCH 59/72] Tidying/commenting. --- .../include/PolyVoxCore/CubicSurfaceExtractor.h | 2 ++ .../PolyVoxCore/MarchingCubesSurfaceExtractor.h | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h index efd001e4..489942c5 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h @@ -47,6 +47,8 @@ namespace PolyVox Vector3DUint8 position; uint8_t normal; + + // User data DataType data; }; diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h index 78a48aac..7b39828e 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h @@ -44,11 +44,19 @@ namespace PolyVox { typedef _DataType DataType; + // Each component of the position is stored using 8.8 fixed-point encoding. Vector3DUint16 position; + + // Each component of the normal is encoded using 5 bits of this variable. + // The 16 bits are -xxxxxyyyyyzzzzz (note the left-most bit is currently + // unused). Some extra shifting and scaling is required to make it signed. uint16_t normal; + + // User data DataType data; }; + /// Decodes a position from a MarchingCubesVertex Vector3DFloat decode(const Vector3DUint16& position) { Vector3DFloat result(position.getX(), position.getY(), position.getZ()); @@ -56,19 +64,27 @@ namespace PolyVox return result; } + /// Decodes a normal from a MarchingCubesVertex Vector3DFloat decode(const uint16_t normal) { + // Get normal components in the range 0 to 31 uint16_t x = (normal >> 10) & 0x1F; uint16_t y = (normal >> 5) & 0x1F; uint16_t z = (normal) & 0x1F; + // Build the resulting vector Vector3DFloat result(x, y, z); + + // Convert to range 0.0 to 2.0 result *= (1.0f / 15.5f); // Division is compile-time constant + + // Convert to range -1.0 to 1.0 result -= Vector3DFloat(1.0f, 1.0f, 1.0f); return result; } + /// Decodes a MarchingCubesVertex by converting it into a regular Vertex which can then be directly used for rendering. template Vertex decode(const MarchingCubesVertex& marchingCubesVertex) { From 80d9feb5eab692162c7deeae53a044d8a43859aa Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 1 Jun 2014 21:54:31 +0200 Subject: [PATCH 60/72] Made functions inline as they are defined in headers. --- .../include/PolyVoxCore/MarchingCubesSurfaceExtractor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h index 7b39828e..6e115319 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h @@ -57,7 +57,7 @@ namespace PolyVox }; /// Decodes a position from a MarchingCubesVertex - Vector3DFloat decode(const Vector3DUint16& position) + inline Vector3DFloat decode(const Vector3DUint16& position) { Vector3DFloat result(position.getX(), position.getY(), position.getZ()); result *= (1.0f / 256.0f); // Division is compile-time constant @@ -65,7 +65,7 @@ namespace PolyVox } /// Decodes a normal from a MarchingCubesVertex - Vector3DFloat decode(const uint16_t normal) + inline Vector3DFloat decode(const uint16_t normal) { // Get normal components in the range 0 to 31 uint16_t x = (normal >> 10) & 0x1F; From 4fa2400ef27d67e62a18623e42e1500c7a27d1df Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 2 Jun 2014 08:25:18 +0200 Subject: [PATCH 61/72] Comments and tidying. --- .../PolyVoxCore/CubicSurfaceExtractor.h | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h index 489942c5..6c3b7898 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h @@ -45,23 +45,33 @@ namespace PolyVox { typedef _DataType DataType; + // Each component of the position is stored as a single unsigned byte. + // The true position is found by offseting each component by 0.5f. Vector3DUint8 position; - uint8_t normal; + + // Currently unused and just serves as passing + uint8_t unused; // User data DataType data; }; - // Hopefully the compiler will implement the 'Return value optimization' here, but - // performance critical code will most likely decode the vertices in a shader anyway. + /// Decodes a position from a CubicVertex + inline Vector3DFloat decode(const Vector3DUint8& position) + { + Vector3DFloat result(position.getX(), position.getY(), position.getZ()); + result -= 0.5f; // Apply the required offset + return result; + } + + /// Decodes a MarchingCubesVertex by converting it into a regular Vertex which can then be directly used for rendering. template Vertex decode(const CubicVertex& cubicVertex) { Vertex result; - Vector3DUint8 temp = cubicVertex.position; // For some reason we can't cast Vector3DUint8 to Vector3DFloat - investigate why. - result.position = Vector3DFloat(temp.getX(), temp.getY(), temp.getZ()) - Vector3DFloat(0.5, 0.5, 0.5); - //result.normal = cubicVertex.normal; - result.data = cubicVertex.data; + result.position = decode(cubicVertex.position); + result.normal.setElements(0.0f, 0.0f, 0.0f); // Currently not calculated + result.data = cubicVertex.data; // Data is not encoded return result; } From d7d1d99ca9c7fe091685aab7031d8cb6c28e1539 Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 2 Jun 2014 08:45:25 +0200 Subject: [PATCH 62/72] Renamed members to differentiate between encoded and decoded values. --- examples/DecodeOnGPU/main.cpp | 4 ++-- .../PolyVoxCore/CubicSurfaceExtractor.h | 11 ++++------ .../PolyVoxCore/CubicSurfaceExtractor.inl | 2 +- .../MarchingCubesSurfaceExtractor.h | 20 +++++++++---------- .../MarchingCubesSurfaceExtractor.inl | 12 +++++------ 5 files changed, 23 insertions(+), 26 deletions(-) diff --git a/examples/DecodeOnGPU/main.cpp b/examples/DecodeOnGPU/main.cpp index f286efc2..54e83970 100644 --- a/examples/DecodeOnGPU/main.cpp +++ b/examples/DecodeOnGPU/main.cpp @@ -92,14 +92,14 @@ OpenGLMeshData buildOpenGLMeshData(const PolyVox::Mesh< PolyVox::MarchingCubesVe // Every surface extractor outputs valid positions for the vertices, so tell OpenGL how these are laid out glEnableVertexAttribArray(0); // Attrib '0' is the vertex positions - glVertexAttribIPointer(0, 3, GL_UNSIGNED_SHORT, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + glVertexAttribIPointer(0, 3, GL_UNSIGNED_SHORT, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, encodedPosition))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) // Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor // does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the // shader. This is mostly just to simplify this example code - in a real application you will know whether your // chosen surface extractor generates normals and can skip uploading them if not. glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals. - glVertexAttribIPointer(1, 1, GL_UNSIGNED_SHORT, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, normal))); + glVertexAttribIPointer(1, 1, GL_UNSIGNED_SHORT, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, encodedNormal))); // Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code // we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here. diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h index 6c3b7898..3d819a36 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h @@ -47,19 +47,16 @@ namespace PolyVox // Each component of the position is stored as a single unsigned byte. // The true position is found by offseting each component by 0.5f. - Vector3DUint8 position; - - // Currently unused and just serves as passing - uint8_t unused; + Vector3DUint8 encodedPosition; // User data DataType data; }; /// Decodes a position from a CubicVertex - inline Vector3DFloat decode(const Vector3DUint8& position) + inline Vector3DFloat decode(const Vector3DUint8& encodedPosition) { - Vector3DFloat result(position.getX(), position.getY(), position.getZ()); + Vector3DFloat result(encodedPosition.getX(), encodedPosition.getY(), encodedPosition.getZ()); result -= 0.5f; // Apply the required offset return result; } @@ -69,7 +66,7 @@ namespace PolyVox Vertex decode(const CubicVertex& cubicVertex) { Vertex result; - result.position = decode(cubicVertex.position); + result.position = decode(cubicVertex.encodedPosition); result.normal.setElements(0.0f, 0.0f, 0.0f); // Currently not calculated result.data = cubicVertex.data; // Data is not encoded return result; diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl index 7fe9286b..4c3e47cc 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl @@ -221,7 +221,7 @@ namespace PolyVox { //No vertices matched and we've now hit an empty space. Fill it by creating a vertex. The 0.5f offset is because vertices set between voxels in order to build cubes around them. CubicVertex cubicVertex; - cubicVertex.position.setElements(static_cast(uX), static_cast(uY), static_cast(uZ)); + cubicVertex.encodedPosition.setElements(static_cast(uX), static_cast(uY), static_cast(uZ)); cubicVertex.data = uMaterialIn; rEntry.iIndex = m_meshCurrent->addVertex(cubicVertex); rEntry.uMaterial = uMaterialIn; diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h index 6e115319..1740ea20 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h @@ -45,32 +45,32 @@ namespace PolyVox typedef _DataType DataType; // Each component of the position is stored using 8.8 fixed-point encoding. - Vector3DUint16 position; + Vector3DUint16 encodedPosition; // Each component of the normal is encoded using 5 bits of this variable. // The 16 bits are -xxxxxyyyyyzzzzz (note the left-most bit is currently // unused). Some extra shifting and scaling is required to make it signed. - uint16_t normal; + uint16_t encodedNormal; // User data DataType data; }; /// Decodes a position from a MarchingCubesVertex - inline Vector3DFloat decode(const Vector3DUint16& position) + inline Vector3DFloat decode(const Vector3DUint16& encodedPosition) { - Vector3DFloat result(position.getX(), position.getY(), position.getZ()); + Vector3DFloat result(encodedPosition.getX(), encodedPosition.getY(), encodedPosition.getZ()); result *= (1.0f / 256.0f); // Division is compile-time constant return result; } /// Decodes a normal from a MarchingCubesVertex - inline Vector3DFloat decode(const uint16_t normal) + inline Vector3DFloat decode(const uint16_t encodedNormal) { // Get normal components in the range 0 to 31 - uint16_t x = (normal >> 10) & 0x1F; - uint16_t y = (normal >> 5) & 0x1F; - uint16_t z = (normal) & 0x1F; + uint16_t x = (encodedNormal >> 10) & 0x1F; + uint16_t y = (encodedNormal >> 5) & 0x1F; + uint16_t z = (encodedNormal) & 0x1F; // Build the resulting vector Vector3DFloat result(x, y, z); @@ -89,8 +89,8 @@ namespace PolyVox Vertex decode(const MarchingCubesVertex& marchingCubesVertex) { Vertex result; - result.position = decode(marchingCubesVertex.position); - result.normal = decode(marchingCubesVertex.normal); + result.position = decode(marchingCubesVertex.encodedPosition); + result.normal = decode(marchingCubesVertex.encodedNormal); result.data = marchingCubesVertex.data; // Data is not encoded return result; } diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl index 9514e22e..0f506763 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl @@ -470,8 +470,8 @@ namespace PolyVox const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v100, fInterp); MarchingCubesVertex surfaceVertex; - surfaceVertex.position = v3dScaledPosition; - surfaceVertex.normal = encodedNormal; + surfaceVertex.encodedPosition = v3dScaledPosition; + surfaceVertex.encodedNormal = encodedNormal; surfaceVertex.data = uMaterial; const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); @@ -513,8 +513,8 @@ namespace PolyVox const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v010, fInterp); MarchingCubesVertex surfaceVertex; - surfaceVertex.position = v3dScaledPosition; - surfaceVertex.normal = encodedNormal; + surfaceVertex.encodedPosition = v3dScaledPosition; + surfaceVertex.encodedNormal = encodedNormal; surfaceVertex.data = uMaterial; uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); @@ -555,8 +555,8 @@ namespace PolyVox const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v001, fInterp); MarchingCubesVertex surfaceVertex; - surfaceVertex.position = v3dScaledPosition; - surfaceVertex.normal = encodedNormal; + surfaceVertex.encodedPosition = v3dScaledPosition; + surfaceVertex.encodedNormal = encodedNormal; surfaceVertex.data = uMaterial; const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); From 82f9d6ad6f1ef701f464be1362f4a140a7574a38 Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 2 Jun 2014 08:57:30 +0200 Subject: [PATCH 63/72] Renamed VertexTypes.h to Vertex.h. --- library/PolyVoxCore/CMakeLists.txt | 7 +- .../PolyVoxCore/CubicSurfaceExtractor.h | 2 +- .../MarchingCubesSurfaceExtractor.h | 2 +- .../PolyVoxCore/include/PolyVoxCore/Mesh.h | 2 +- .../PolyVoxCore/{VertexTypes.h => Vertex.h} | 102 +++++++++--------- library/PolyVoxCore/source/VertexTypes.cpp | 1 - 6 files changed, 57 insertions(+), 59 deletions(-) rename library/PolyVoxCore/include/PolyVoxCore/{VertexTypes.h => Vertex.h} (91%) delete mode 100644 library/PolyVoxCore/source/VertexTypes.cpp diff --git a/library/PolyVoxCore/CMakeLists.txt b/library/PolyVoxCore/CMakeLists.txt index 3fbb260b..db5caaa8 100644 --- a/library/PolyVoxCore/CMakeLists.txt +++ b/library/PolyVoxCore/CMakeLists.txt @@ -27,7 +27,6 @@ SET(CORE_SRC_FILES source/ArraySizes.cpp source/AStarPathfinder.cpp source/Region.cpp - source/VertexTypes.cpp ) #Projects headers files @@ -66,6 +65,8 @@ SET(CORE_INC_FILES include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl include/PolyVoxCore/Material.h include/PolyVoxCore/MaterialDensityPair.h + include/PolyVoxCore/Mesh.h + include/PolyVoxCore/Mesh.inl include/PolyVoxCore/MinizBlockCompressor.h include/PolyVoxCore/MinizBlockCompressor.inl include/PolyVoxCore/Pager.h @@ -84,13 +85,11 @@ SET(CORE_INC_FILES include/PolyVoxCore/SimpleVolume.inl include/PolyVoxCore/SimpleVolumeBlock.inl include/PolyVoxCore/SimpleVolumeSampler.inl - include/PolyVoxCore/Mesh.h - include/PolyVoxCore/Mesh.inl include/PolyVoxCore/UncompressedBlock.h include/PolyVoxCore/UncompressedBlock.inl include/PolyVoxCore/Vector.h include/PolyVoxCore/Vector.inl - include/PolyVoxCore/VertexTypes.h + include/PolyVoxCore/Vertex.h include/PolyVoxCore/VolumeResampler.h include/PolyVoxCore/VolumeResampler.inl include/PolyVoxCore/VoxelFilters.h diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h index 3d819a36..c2ba3481 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h @@ -32,7 +32,7 @@ freely, subject to the following restrictions: #include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these? #include "PolyVoxCore/DefaultIsQuadNeeded.h" #include "PolyVoxCore/Mesh.h" -#include "PolyVoxCore/VertexTypes.h" +#include "PolyVoxCore/Vertex.h" namespace PolyVox { diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h index 1740ea20..4b96b432 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h @@ -31,7 +31,7 @@ freely, subject to the following restrictions: #include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these? #include "PolyVoxCore/Mesh.h" #include "PolyVoxCore/DefaultMarchingCubesController.h" -#include "PolyVoxCore/VertexTypes.h" +#include "PolyVoxCore/Vertex.h" namespace PolyVox { diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h index f0ce39ea..0499b9f1 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h @@ -27,7 +27,7 @@ freely, subject to the following restrictions: #include "Impl/TypeDef.h" #include "PolyVoxCore/Region.h" -#include "PolyVoxCore/VertexTypes.h" //Should probably do away with this on in the future... +#include "PolyVoxCore/Vertex.h" //Should probably do away with this on in the future... #include #include diff --git a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h b/library/PolyVoxCore/include/PolyVoxCore/Vertex.h similarity index 91% rename from library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h rename to library/PolyVoxCore/include/PolyVoxCore/Vertex.h index 964ff88d..1eb6f429 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Vertex.h @@ -1,51 +1,51 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David Williams - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*******************************************************************************/ - -#ifndef __PolyVox_SurfaceVertex_H__ -#define __PolyVox_SurfaceVertex_H__ - -#include "Impl/TypeDef.h" - -#include "PolyVoxCore/Vector.h" - -#include -#include - -namespace PolyVox -{ - #ifdef SWIG - struct Vertex -#else - template - struct POLYVOX_API Vertex -#endif - { - typedef _DataType DataType; - - Vector3DFloat position; - Vector3DFloat normal; - DataType data; - }; -} - -#endif +/******************************************************************************* +Copyright (c) 2005-2009 David Williams + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*******************************************************************************/ + +#ifndef __PolyVox_Vertex_H__ +#define __PolyVox_Vertex_H__ + +#include "Impl/TypeDef.h" + +#include "PolyVoxCore/Vector.h" + +#include +#include + +namespace PolyVox +{ + #ifdef SWIG + struct Vertex +#else + template + struct POLYVOX_API Vertex +#endif + { + typedef _DataType DataType; + + Vector3DFloat position; + Vector3DFloat normal; + DataType data; + }; +} + +#endif // __PolyVox_Vertex_H__ diff --git a/library/PolyVoxCore/source/VertexTypes.cpp b/library/PolyVoxCore/source/VertexTypes.cpp deleted file mode 100644 index 8b137891..00000000 --- a/library/PolyVoxCore/source/VertexTypes.cpp +++ /dev/null @@ -1 +0,0 @@ - From 0bff22fbf599556786a021245b5d72c317c08fba Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 2 Jun 2014 09:08:07 +0200 Subject: [PATCH 64/72] Purged old/dead code from Mesh class. --- .../PolyVoxCore/include/PolyVoxCore/Mesh.h | 21 +- .../PolyVoxCore/include/PolyVoxCore/Mesh.inl | 262 +----------------- 2 files changed, 2 insertions(+), 281 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h index 0499b9f1..657d7e1a 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h @@ -69,37 +69,18 @@ namespace PolyVox void clear(void); bool isEmpty(void) const; - void scaleVertices(float amount); - void translateVertices(const Vector3DFloat& amount); - - //THESE FUNCTIONS TO BE REMOVED IN THE FUTURE. OR AT LEAST MOVED OUT OF THIS CLASS INTO FREE FUNCTIONS. - //THEY ARE CAUSING PROBLEMS WITH THE SWIG BINDINGS. THE FUNCTIONS REGARDING NORMALS MAKE NO SENSE WHEN - //A VERTEX MIGHT NOT HAVE NORMALS. THE EXTRACT SUBSET FUNCTION SHOULD MAYBE BE APPLICATION CODE, AT ANY - //RATE THE STD::SET CAUSES PROBLEMS WITH SWIG. IF YOU UNCOMMENT ANY OF THESE FUNCTIONS, PLEASE POST ON - //THE FORUM SO WE CAN KNOW THE FUNCTIONALITY IS STILL NEEDED IN SOME FORM. - //void sumNearbyNormals(bool bNormaliseResult = true); - //std::shared_ptr< Mesh > extractSubset(std::set setMaterials); - //void generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices = false); - int noOfDegenerateTris(void); void removeDegenerateTris(void); void removeUnusedVertices(void); Region m_Region; - - int32_t m_iTimeStamp; - - int32_t m_iNoOfLod0Tris; public: std::vector m_vecTriangleIndices; std::vector m_vecVertices; std::vector m_vecLodRecords; - }; - - template - std::shared_ptr< Mesh > extractSubset(Mesh& inputMesh, std::set setMaterials); + }; template Mesh< Vertex< typename MeshType::VertexType::DataType > > decode(const MeshType& mesh) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl index 44fc5320..a886defa 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl @@ -26,7 +26,6 @@ namespace PolyVox template Mesh::Mesh() { - m_iTimeStamp = -1; } template @@ -143,173 +142,7 @@ namespace PolyVox { return (getNoOfVertices() == 0) || (getNoOfIndices() == 0); } - - //////////////////////////////////////////////////////////////////////////////// - /// This function can help improve the visual appearance of a surface patch by - /// smoothing normals with other nearby normals. It iterates over each triangle - /// in the surface patch and determines the sum of its corners normals. For any - /// given vertex, these sums are in turn summed for any triangles which use the - /// vertex. Usually, the resulting normals should be renormalised afterwards. - /// Note: This function can cause lighting discontinuities accross region boundaries. - //////////////////////////////////////////////////////////////////////////////// - /*template - void Mesh::sumNearbyNormals(bool bNormaliseResult) - { - if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... - { - return; - } - - std::vector summedNormals(m_vecVertices.size()); - - //Initialise all normals to zero. Should be ok as the vector should store all elements contiguously. - memset(&summedNormals[0], 0, summedNormals.size() * sizeof(Vector3DFloat)); - - for(vector::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();) - { - PositionMaterialNormal& v0 = m_vecVertices[*iterIndex]; - Vector3DFloat& v0New = summedNormals[*iterIndex]; - iterIndex++; - PositionMaterialNormal& v1 = m_vecVertices[*iterIndex]; - Vector3DFloat& v1New = summedNormals[*iterIndex]; - iterIndex++; - PositionMaterialNormal& v2 = m_vecVertices[*iterIndex]; - Vector3DFloat& v2New = summedNormals[*iterIndex]; - iterIndex++; - - Vector3DFloat sumOfNormals = v0.getNormal() + v1.getNormal() + v2.getNormal(); - - v0New += sumOfNormals; - v1New += sumOfNormals; - v2New += sumOfNormals; - } - - for(uint32_t uIndex = 0; uIndex < summedNormals.size(); uIndex++) - { - if(bNormaliseResult) - { - summedNormals[uIndex].normalise(); - } - m_vecVertices[uIndex].setNormal(summedNormals[uIndex]); - } - }*/ - - /*template - void Mesh::generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices) - { - Vector3DFloat offset = static_cast(m_Region.getLowerCorner()); - - //Initially zero the normals - for(vector::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++) - { - if(m_Region.containsPoint(iterVertex->getPosition() + offset, 0.001)) - { - iterVertex->setNormal(Vector3DFloat(0.0f,0.0f,0.0f)); - } - } - - for(vector::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();) - { - PositionMaterialNormal& v0 = m_vecVertices[*iterIndex]; - iterIndex++; - PositionMaterialNormal& v1 = m_vecVertices[*iterIndex]; - iterIndex++; - PositionMaterialNormal& v2 = m_vecVertices[*iterIndex]; - iterIndex++; - - Vector3DFloat triangleNormal = (v1.getPosition()-v0.getPosition()).cross(v2.getPosition()-v0.getPosition()); - - if(m_Region.containsPoint(v0.getPosition() + offset, 0.001)) - { - v0.setNormal(v0.getNormal() + triangleNormal); - } - if(m_Region.containsPoint(v1.getPosition() + offset, 0.001)) - { - v1.setNormal(v1.getNormal() + triangleNormal); - } - if(m_Region.containsPoint(v2.getPosition() + offset, 0.001)) - { - v2.setNormal(v2.getNormal() + triangleNormal); - } - } - - if(bNormalise) - { - for(vector::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++) - { - Vector3DFloat normal = iterVertex->getNormal(); - normal.normalise(); - iterVertex->setNormal(normal); - } - } - }*/ - - /*template - std::shared_ptr< Mesh > Mesh::extractSubset(std::set setMaterials) - { - std::shared_ptr< Mesh > result(new Mesh); - - if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... - { - return result; - } - - assert(m_vecLodRecords.size() == 1); - if(m_vecLodRecords.size() != 1) - { - //If we have done progressive LOD then it's too late to split into subsets. - return result; - } - - std::vector indexMap(m_vecVertices.size()); - std::fill(indexMap.begin(), indexMap.end(), -1); - - for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size(); triCt += 3) - { - - PositionMaterialNormal& v0 = m_vecVertices[m_vecTriangleIndices[triCt]]; - PositionMaterialNormal& v1 = m_vecVertices[m_vecTriangleIndices[triCt + 1]]; - PositionMaterialNormal& v2 = m_vecVertices[m_vecTriangleIndices[triCt + 2]]; - - if( - (setMaterials.find(v0.getMaterial()) != setMaterials.end()) || - (setMaterials.find(v1.getMaterial()) != setMaterials.end()) || - (setMaterials.find(v2.getMaterial()) != setMaterials.end())) - { - uint32_t i0; - if(indexMap[m_vecTriangleIndices[triCt]] == -1) - { - indexMap[m_vecTriangleIndices[triCt]] = result->addVertex(v0); - } - i0 = indexMap[m_vecTriangleIndices[triCt]]; - - uint32_t i1; - if(indexMap[m_vecTriangleIndices[triCt+1]] == -1) - { - indexMap[m_vecTriangleIndices[triCt+1]] = result->addVertex(v1); - } - i1 = indexMap[m_vecTriangleIndices[triCt+1]]; - - uint32_t i2; - if(indexMap[m_vecTriangleIndices[triCt+2]] == -1) - { - indexMap[m_vecTriangleIndices[triCt+2]] = result->addVertex(v2); - } - i2 = indexMap[m_vecTriangleIndices[triCt+2]]; - - result->addTriangle(i0,i1,i2); - } - } - - result->m_vecLodRecords.clear(); - LodRecord lodRecord; - lodRecord.beginIndex = 0; - lodRecord.endIndex = result->getNoOfIndices(); - result->m_vecLodRecords.push_back(lodRecord); - - return result; - }*/ - + template int Mesh::noOfDegenerateTris(void) { @@ -392,97 +225,4 @@ namespace PolyVox m_vecTriangleIndices[triCt] = newPos[m_vecTriangleIndices[triCt]]; } } - - //Currently a free function - think where this needs to go. - template - std::shared_ptr< Mesh > extractSubset(Mesh& inputMesh, std::set setMaterials) - { - std::shared_ptr< Mesh > result(new Mesh); - - result->m_Region = inputMesh.m_Region; - - if(inputMesh.m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... - { - return result; - } - - POLYVOX_ASSERT(inputMesh.m_vecLodRecords.size() == 1, "Number of LOD records must equal one."); - if(inputMesh.m_vecLodRecords.size() != 1) - { - //If we have done progressive LOD then it's too late to split into subsets. - return result; - } - - std::vector indexMap(inputMesh.m_vecVertices.size()); - std::fill(indexMap.begin(), indexMap.end(), -1); - - for(uint32_t triCt = 0; triCt < inputMesh.m_vecTriangleIndices.size(); triCt += 3) - { - - VertexType& v0 = inputMesh.m_vecVertices[inputMesh.m_vecTriangleIndices[triCt]]; - VertexType& v1 = inputMesh.m_vecVertices[inputMesh.m_vecTriangleIndices[triCt + 1]]; - VertexType& v2 = inputMesh.m_vecVertices[inputMesh.m_vecTriangleIndices[triCt + 2]]; - - if( - (setMaterials.find(v0.getMaterial()) != setMaterials.end()) || - (setMaterials.find(v1.getMaterial()) != setMaterials.end()) || - (setMaterials.find(v2.getMaterial()) != setMaterials.end())) - { - uint32_t i0; - if(indexMap[inputMesh.m_vecTriangleIndices[triCt]] == -1) - { - indexMap[inputMesh.m_vecTriangleIndices[triCt]] = result->addVertex(v0); - } - i0 = indexMap[inputMesh.m_vecTriangleIndices[triCt]]; - - uint32_t i1; - if(indexMap[inputMesh.m_vecTriangleIndices[triCt+1]] == -1) - { - indexMap[inputMesh.m_vecTriangleIndices[triCt+1]] = result->addVertex(v1); - } - i1 = indexMap[inputMesh.m_vecTriangleIndices[triCt+1]]; - - uint32_t i2; - if(indexMap[inputMesh.m_vecTriangleIndices[triCt+2]] == -1) - { - indexMap[inputMesh.m_vecTriangleIndices[triCt+2]] = result->addVertex(v2); - } - i2 = indexMap[inputMesh.m_vecTriangleIndices[triCt+2]]; - - result->addTriangle(i0,i1,i2); - } - } - - result->m_vecLodRecords.clear(); - LodRecord lodRecord; - lodRecord.beginIndex = 0; - lodRecord.endIndex = result->getNoOfIndices(); - result->m_vecLodRecords.push_back(lodRecord); - - return result; - } - - template - void Mesh::scaleVertices(float amount) - { - for(uint32_t ct = 0; ct < m_vecVertices.size(); ct++) - { - //TODO: Should rethink accessors here to provide faster access - Vector3DFloat position = m_vecVertices[ct].getPosition(); - position *= amount; - m_vecVertices[ct].setPosition(position); - } - } - - template - void Mesh::translateVertices(const Vector3DFloat& amount) - { - for(uint32_t ct = 0; ct < m_vecVertices.size(); ct++) - { - //TODO: Should rethink accessors here to provide faster access - Vector3DFloat position = m_vecVertices[ct].getPosition(); - position += amount; - m_vecVertices[ct].setPosition(position); - } - } } From 9fd52e34946a360822f092b3ac05f80e528b280d Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 2 Jun 2014 09:40:28 +0200 Subject: [PATCH 65/72] Removing more old stuff from the Mesh class. --- .../PolyVoxCore/CubicSurfaceExtractor.inl | 4 +- .../PolyVoxCore/include/PolyVoxCore/Mesh.h | 31 ++---- .../PolyVoxCore/include/PolyVoxCore/Mesh.inl | 104 ------------------ 3 files changed, 14 insertions(+), 125 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl index 4c3e47cc..63d021e2 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl @@ -190,8 +190,8 @@ namespace PolyVox for(typename std::list::iterator quadIter = listQuads.begin(); quadIter != iterEnd; quadIter++) { Quad& quad = *quadIter; - m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[1],quad.vertices[2]); - m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[2],quad.vertices[3]); + m_meshCurrent->addTriangle(quad.vertices[0], quad.vertices[1],quad.vertices[2]); + m_meshCurrent->addTriangle(quad.vertices[0], quad.vertices[2],quad.vertices[3]); } } } diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h index 657d7e1a..408c1ddc 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h @@ -52,28 +52,21 @@ namespace PolyVox typedef _VertexType VertexType; - Mesh(); - ~Mesh(); + Mesh(); + ~Mesh(); - const std::vector& getIndices(void) const; - uint32_t getNoOfIndices(void) const; - uint32_t getNoOfNonUniformTrianges(void) const; - uint32_t getNoOfUniformTrianges(void) const; - uint32_t getNoOfVertices(void) const; - std::vector& getRawVertexData(void); //FIXME - this should be removed - const std::vector& getVertices(void) const; + const std::vector& getIndices(void) const; + uint32_t getNoOfIndices(void) const; + uint32_t getNoOfVertices(void) const; + const std::vector& getVertices(void) const; - void addTriangle(uint32_t index0, uint32_t index1, uint32_t index2); - void addTriangleCubic(uint32_t index0, uint32_t index1, uint32_t index2); - uint32_t addVertex(const VertexType& vertex); - void clear(void); - bool isEmpty(void) const; + void addTriangle(uint32_t index0, uint32_t index1, uint32_t index2); + uint32_t addVertex(const VertexType& vertex); + void clear(void); + bool isEmpty(void) const; + void removeUnusedVertices(void); - int noOfDegenerateTris(void); - void removeDegenerateTris(void); - void removeUnusedVertices(void); - - Region m_Region; + Region m_Region; public: std::vector m_vecTriangleIndices; diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl index a886defa..2f62c051 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl @@ -43,39 +43,6 @@ namespace PolyVox uint32_t Mesh::getNoOfIndices(void) const { return m_vecTriangleIndices.size(); - } - - template - uint32_t Mesh::getNoOfNonUniformTrianges(void) const - { - uint32_t result = 0; - for(uint32_t i = 0; i < m_vecTriangleIndices.size() - 2; i += 3) - { - if((m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+1]].getMaterial()) - && (m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+2]].getMaterial())) - { - } - else - { - result++; - } - } - return result; - } - - template - uint32_t Mesh::getNoOfUniformTrianges(void) const - { - uint32_t result = 0; - for(uint32_t i = 0; i < m_vecTriangleIndices.size() - 2; i += 3) - { - if((m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+1]].getMaterial()) - && (m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+2]].getMaterial())) - { - result++; - } - } - return result; } template @@ -84,12 +51,6 @@ namespace PolyVox return m_vecVertices.size(); } - template - std::vector& Mesh::getRawVertexData(void) - { - return m_vecVertices; - } - template const std::vector& Mesh::getVertices(void) const { @@ -109,19 +70,6 @@ namespace PolyVox m_vecTriangleIndices.push_back(index2); } - template - void Mesh::addTriangleCubic(uint32_t index0, uint32_t index1, uint32_t index2) - { - //Make sure the specified indices correspond to valid vertices. - POLYVOX_ASSERT(index0 < m_vecVertices.size(), "Index points at an invalid vertex."); - POLYVOX_ASSERT(index1 < m_vecVertices.size(), "Index points at an invalid vertex."); - POLYVOX_ASSERT(index2 < m_vecVertices.size(), "Index points at an invalid vertex."); - - m_vecTriangleIndices.push_back(index0); - m_vecTriangleIndices.push_back(index1); - m_vecTriangleIndices.push_back(index2); - } - template uint32_t Mesh::addVertex(const VertexType& vertex) { @@ -134,7 +82,6 @@ namespace PolyVox { m_vecVertices.clear(); m_vecTriangleIndices.clear(); - m_vecLodRecords.clear(); } template @@ -142,57 +89,6 @@ namespace PolyVox { return (getNoOfVertices() == 0) || (getNoOfIndices() == 0); } - - template - int Mesh::noOfDegenerateTris(void) - { - int count = 0; - for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size();) - { - int v0 = m_vecTriangleIndices[triCt]; - triCt++; - int v1 = m_vecTriangleIndices[triCt]; - triCt++; - int v2 = m_vecTriangleIndices[triCt]; - triCt++; - - if((v0 == v1) || (v1 == v2) || (v2 == v0)) - { - count++; - } - } - return count; - } - - template - void Mesh::removeDegenerateTris(void) - { - int noOfNonDegenerate = 0; - int targetCt = 0; - for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size();) - { - int v0 = m_vecTriangleIndices[triCt]; - triCt++; - int v1 = m_vecTriangleIndices[triCt]; - triCt++; - int v2 = m_vecTriangleIndices[triCt]; - triCt++; - - if((v0 != v1) && (v1 != v2) & (v2 != v0)) - { - m_vecTriangleIndices[targetCt] = v0; - targetCt++; - m_vecTriangleIndices[targetCt] = v1; - targetCt++; - m_vecTriangleIndices[targetCt] = v2; - targetCt++; - - noOfNonDegenerate++; - } - } - - m_vecTriangleIndices.resize(noOfNonDegenerate * 3); - } template void Mesh::removeUnusedVertices(void) From 31e5a6e34693b72342754ed364e0077761e12abe Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 2 Jun 2014 17:30:41 +0200 Subject: [PATCH 66/72] Replaced 'm_region' with 'm_offset' and demonstrated its use. --- examples/OpenGL/main.cpp | 5 +++-- .../include/PolyVoxCore/CubicSurfaceExtractor.inl | 2 +- .../PolyVoxCore/MarchingCubesSurfaceExtractor.inl | 2 +- library/PolyVoxCore/include/PolyVoxCore/Mesh.h | 7 +++++-- library/PolyVoxCore/include/PolyVoxCore/Mesh.inl | 14 +++++++++++++- 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index a95d66e5..12d1068f 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -130,8 +130,9 @@ int main(int argc, char *argv[]) // The returned mesh needs to be decoded to be appropriate for GPU rendering. auto decodedMesh = decode(mesh); - //Pass the surface to the OpenGL window - openGLWidget.addMesh(decodedMesh, Vector3DInt32(x, y, z)); + // Pass the surface to the OpenGL window. Note that we are also passing an offset in this multi-mesh example. This is because + // the surface extractors return a mesh with 'local space' positions to reduce storage requirements and precision problems. + openGLWidget.addMesh(decodedMesh, decodedMesh.getOffset()); meshCounter++; } diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl index 63d021e2..d05a7c57 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl @@ -196,7 +196,7 @@ namespace PolyVox } } - m_meshCurrent->m_Region = m_regSizeInVoxels; + m_meshCurrent->setOffset(m_regSizeInVoxels.getLowerCorner()); m_meshCurrent->removeUnusedVertices(); m_meshCurrent->m_vecLodRecords.clear(); diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl index 0f506763..382dc85a 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl @@ -122,7 +122,7 @@ namespace PolyVox m_regSliceCurrent.shift(Vector3DInt32(0,0,1)); } - m_meshCurrent->m_Region = m_regSizeInVoxels; + m_meshCurrent->setOffset(m_regSizeInVoxels.getLowerCorner()); m_meshCurrent->m_vecLodRecords.clear(); LodRecord lodRecord; diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h index 408c1ddc..18537e9e 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h @@ -59,6 +59,9 @@ namespace PolyVox uint32_t getNoOfIndices(void) const; uint32_t getNoOfVertices(void) const; const std::vector& getVertices(void) const; + const Vector3DInt32& getOffset(void) const; + + void setOffset(const Vector3DInt32& offset); void addTriangle(uint32_t index0, uint32_t index1, uint32_t index2); uint32_t addVertex(const VertexType& vertex); @@ -66,7 +69,7 @@ namespace PolyVox bool isEmpty(void) const; void removeUnusedVertices(void); - Region m_Region; + Vector3DInt32 m_offset; public: std::vector m_vecTriangleIndices; @@ -88,7 +91,7 @@ namespace PolyVox result.m_vecTriangleIndices = mesh.m_vecTriangleIndices; - result.m_Region = mesh.m_Region; + result.m_offset = mesh.m_offset; return result; } diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl index 2f62c051..d2363046 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl @@ -55,7 +55,19 @@ namespace PolyVox const std::vector& Mesh::getVertices(void) const { return m_vecVertices; - } + } + + template + const Vector3DInt32& Mesh::getOffset(void) const + { + return m_offset; + } + + template + void Mesh::setOffset(const Vector3DInt32& offset) + { + m_offset = offset; + } template void Mesh::addTriangle(uint32_t index0, uint32_t index1, uint32_t index2) From 9b19ea656bd22f00c5fc7af038ca3380dd795a28 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 3 Jun 2014 10:37:11 +0100 Subject: [PATCH 67/72] Fix commit on Linux --- examples/common/OpenGLWidget.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/common/OpenGLWidget.h b/examples/common/OpenGLWidget.h index a0150556..1bbbc1e4 100644 --- a/examples/common/OpenGLWidget.h +++ b/examples/common/OpenGLWidget.h @@ -71,7 +71,7 @@ public: // The GL_ARRAY_BUFFER will contain the list of vertex positions glGenBuffers(1, &(meshData.vertexBuffer)); glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(Vertex< DataType >), vecVertices.data(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PolyVox::Vertex< DataType >), vecVertices.data(), GL_STATIC_DRAW); // and GL_ELEMENT_ARRAY_BUFFER will contain the indices glGenBuffers(1, &(meshData.indexBuffer)); @@ -80,20 +80,20 @@ public: // Every surface extractor outputs valid positions for the vertices, so tell OpenGL how these are laid out glEnableVertexAttribArray(0); // Attrib '0' is the vertex positions - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex< DataType >), (GLvoid*)(offsetof(Vertex< DataType >, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(PolyVox::Vertex< DataType >), (GLvoid*)(offsetof(PolyVox::Vertex< DataType >, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) // Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor // does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the // shader. This is mostly just to simplify this example code - in a real application you will know whether your // chosen surface extractor generates normals and can skip uploading them if not. glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals. - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex< DataType >), (GLvoid*)(offsetof(Vertex< DataType >, normal))); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(PolyVox::Vertex< DataType >), (GLvoid*)(offsetof(PolyVox::Vertex< DataType >, normal))); // Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code // we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here. glEnableVertexAttribArray(2); //We're talking about shader attribute '2' GLint size = (std::min)(sizeof(DataType), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type) - glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(Vertex< DataType >), (GLvoid*)(offsetof(Vertex< DataType >, data))); + glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(PolyVox::Vertex< DataType >), (GLvoid*)(offsetof(PolyVox::Vertex< DataType >, data))); // We're done uploading and can now unbind. glBindVertexArray(0); From 78d750a0f27730fc1163f6dda1429e6f648b7a03 Mon Sep 17 00:00:00 2001 From: David Williams Date: Tue, 3 Jun 2014 15:50:30 +0200 Subject: [PATCH 68/72] Removed unused 'LodRecord'. --- .../include/PolyVoxCore/CubicSurfaceExtractor.inl | 6 ------ .../PolyVoxCore/MarchingCubesSurfaceExtractor.inl | 6 ------ library/PolyVoxCore/include/PolyVoxCore/Mesh.h | 9 --------- 3 files changed, 21 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl index d05a7c57..5e00a572 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl @@ -199,12 +199,6 @@ namespace PolyVox m_meshCurrent->setOffset(m_regSizeInVoxels.getLowerCorner()); m_meshCurrent->removeUnusedVertices(); - m_meshCurrent->m_vecLodRecords.clear(); - LodRecord lodRecord; - lodRecord.beginIndex = 0; - lodRecord.endIndex = m_meshCurrent->getNoOfIndices(); - m_meshCurrent->m_vecLodRecords.push_back(lodRecord); - POLYVOX_LOG_TRACE("Cubic surface extraction took " << timer.elapsedTimeInMilliSeconds() << "ms (Region size = " << m_regSizeInVoxels.getWidthInVoxels() << "x" << m_regSizeInVoxels.getHeightInVoxels() << "x" << m_regSizeInVoxels.getDepthInVoxels() << ")"); diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl index 382dc85a..19968cd6 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl @@ -124,12 +124,6 @@ namespace PolyVox m_meshCurrent->setOffset(m_regSizeInVoxels.getLowerCorner()); - m_meshCurrent->m_vecLodRecords.clear(); - LodRecord lodRecord; - lodRecord.beginIndex = 0; - lodRecord.endIndex = m_meshCurrent->getNoOfIndices(); - m_meshCurrent->m_vecLodRecords.push_back(lodRecord); - POLYVOX_LOG_TRACE("Marching cubes surface extraction took " << timer.elapsedTimeInMilliSeconds() << "ms (Region size = " << m_regSizeInVoxels.getWidthInVoxels() << "x" << m_regSizeInVoxels.getHeightInVoxels() << "x" << m_regSizeInVoxels.getDepthInVoxels() << ")"); diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h index 18537e9e..9403c5d8 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h @@ -38,13 +38,6 @@ freely, subject to the following restrictions: namespace PolyVox { - class LodRecord - { - public: - int beginIndex; - int endIndex; //Let's put it just past the end STL style - }; - template class Mesh { @@ -74,8 +67,6 @@ namespace PolyVox public: std::vector m_vecTriangleIndices; std::vector m_vecVertices; - - std::vector m_vecLodRecords; }; template From 5701e7a6ccf45da262ad11c6723a5b16008111a7 Mon Sep 17 00:00:00 2001 From: David Williams Date: Tue, 3 Jun 2014 15:51:42 +0200 Subject: [PATCH 69/72] It seems we don't need these leading underscores? Perhaps they were required in older versions of Visual Studio? Let's see what GCC/Clang says. --- library/PolyVoxCore/include/PolyVoxCore/Mesh.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h index 9403c5d8..6b122323 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h @@ -38,12 +38,12 @@ freely, subject to the following restrictions: namespace PolyVox { - template + template class Mesh { public: - typedef _VertexType VertexType; + typedef VertexType VertexType; Mesh(); ~Mesh(); From ffdf606ad6e7aa0f3f69235e44104acacb0703ad Mon Sep 17 00:00:00 2001 From: David Williams Date: Tue, 3 Jun 2014 15:58:07 +0200 Subject: [PATCH 70/72] Added IndexType template parameter to Mesh class. --- .../PolyVoxCore/include/PolyVoxCore/Mesh.h | 3 +- .../PolyVoxCore/include/PolyVoxCore/Mesh.inl | 52 +++++++++---------- .../PolyVoxCore/PolyVoxForwardDeclarations.h | 20 +++---- 3 files changed, 38 insertions(+), 37 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h index 6b122323..45f78930 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h @@ -38,12 +38,13 @@ freely, subject to the following restrictions: namespace PolyVox { - template + template class Mesh { public: typedef VertexType VertexType; + typedef IndexType IndexType; Mesh(); ~Mesh(); diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl index d2363046..7a57c748 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl @@ -23,54 +23,54 @@ freely, subject to the following restrictions: namespace PolyVox { - template - Mesh::Mesh() + template + Mesh::Mesh() { } - template - Mesh::~Mesh() + template + Mesh::~Mesh() { } - template - const std::vector& Mesh::getIndices(void) const + template + const std::vector& Mesh::getIndices(void) const { return m_vecTriangleIndices; } - template - uint32_t Mesh::getNoOfIndices(void) const + template + uint32_t Mesh::getNoOfIndices(void) const { return m_vecTriangleIndices.size(); } - template - uint32_t Mesh::getNoOfVertices(void) const + template + uint32_t Mesh::getNoOfVertices(void) const { return m_vecVertices.size(); } - template - const std::vector& Mesh::getVertices(void) const + template + const std::vector& Mesh::getVertices(void) const { return m_vecVertices; } - template - const Vector3DInt32& Mesh::getOffset(void) const + template + const Vector3DInt32& Mesh::getOffset(void) const { return m_offset; } - template - void Mesh::setOffset(const Vector3DInt32& offset) + template + void Mesh::setOffset(const Vector3DInt32& offset) { m_offset = offset; } - template - void Mesh::addTriangle(uint32_t index0, uint32_t index1, uint32_t index2) + template + void Mesh::addTriangle(uint32_t index0, uint32_t index1, uint32_t index2) { //Make sure the specified indices correspond to valid vertices. POLYVOX_ASSERT(index0 < m_vecVertices.size(), "Index points at an invalid vertex."); @@ -82,28 +82,28 @@ namespace PolyVox m_vecTriangleIndices.push_back(index2); } - template - uint32_t Mesh::addVertex(const VertexType& vertex) + template + uint32_t Mesh::addVertex(const VertexType& vertex) { m_vecVertices.push_back(vertex); return m_vecVertices.size() - 1; } - template - void Mesh::clear(void) + template + void Mesh::clear(void) { m_vecVertices.clear(); m_vecTriangleIndices.clear(); } - template - bool Mesh::isEmpty(void) const + template + bool Mesh::isEmpty(void) const { return (getNoOfVertices() == 0) || (getNoOfIndices() == 0); } - template - void Mesh::removeUnusedVertices(void) + template + void Mesh::removeUnusedVertices(void) { std::vector isVertexUsed(m_vecVertices.size()); std::fill(isVertexUsed.begin(), isVertexUsed.end(), false); diff --git a/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h b/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h index 49bd882c..e4555893 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h +++ b/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h @@ -108,6 +108,11 @@ namespace PolyVox //////////////////////////////////////////////////////////////////////////////// template class LargeVolume; + //////////////////////////////////////////////////////////////////////////////// + // MarchingCubesSurfaceExtractor + //////////////////////////////////////////////////////////////////////////////// + template class MarchingCubesSurfaceExtractor; + //////////////////////////////////////////////////////////////////////////////// // MarchingCubesVertex //////////////////////////////////////////////////////////////////////////////// @@ -134,6 +139,11 @@ namespace PolyVox typedef MaterialDensityPair MaterialDensityPair44; typedef MaterialDensityPair MaterialDensityPair88; + //////////////////////////////////////////////////////////////////////////////// + // Mesh + //////////////////////////////////////////////////////////////////////////////// + template class Mesh; + //////////////////////////////////////////////////////////////////////////////// // Pager //////////////////////////////////////////////////////////////////////////////// @@ -154,16 +164,6 @@ namespace PolyVox //////////////////////////////////////////////////////////////////////////////// template class SimpleVolume; - //////////////////////////////////////////////////////////////////////////////// - // MarchingCubesSurfaceExtractor - //////////////////////////////////////////////////////////////////////////////// - template class MarchingCubesSurfaceExtractor; - - //////////////////////////////////////////////////////////////////////////////// - // Mesh - //////////////////////////////////////////////////////////////////////////////// - template class Mesh; - //////////////////////////////////////////////////////////////////////////////// // Vector //////////////////////////////////////////////////////////////////////////////// From 06540d6c970680b327db73b8013fb897a4bd1b09 Mon Sep 17 00:00:00 2001 From: David Williams Date: Tue, 3 Jun 2014 16:52:09 +0200 Subject: [PATCH 71/72] More work to make Mesh be templatized on IndexType. This requires making the SurfaceExtractor classes be templatised on MeshType (at least for now - maybe there is a better approach when working with free functions). This has been partially done for CubicSurfaceExtractor. --- .../PolyVoxCore/CubicSurfaceExtractor.h | 13 +++++----- .../PolyVoxCore/CubicSurfaceExtractor.inl | 24 +++++++++---------- .../PolyVoxCore/include/PolyVoxCore/Mesh.h | 16 ++++++------- .../PolyVoxCore/include/PolyVoxCore/Mesh.inl | 10 ++++---- .../PolyVoxCore/PolyVoxForwardDeclarations.h | 2 +- 5 files changed, 33 insertions(+), 32 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h index c2ba3481..71571038 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h @@ -113,7 +113,7 @@ namespace PolyVox /// /// Another scenario which sometimes results in confusion is when you wish to extract a region which corresponds to the whole volume, partcularly when solid voxels extend right to the edge of the volume. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - template + template class CubicSurfaceExtractor { struct IndexAndMaterial @@ -150,9 +150,9 @@ namespace PolyVox // This is a bit ugly - it seems that the C++03 syntax is different from the C++11 syntax? See this thread: http://stackoverflow.com/questions/6076015/typename-outside-of-template // Long term we should probably come back to this and if the #ifdef is still needed then maybe it should check for C++11 mode instead of MSVC? #if defined(_MSC_VER) - CubicSurfaceExtractor(VolumeType* volData, Region region, Mesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); + CubicSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); #else - CubicSurfaceExtractor(VolumeType* volData, Region region, Mesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); + CubicSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); #endif @@ -172,7 +172,7 @@ namespace PolyVox Region m_regSizeInVoxels; //The surface patch we are currently filling. - Mesh >* m_meshCurrent; + MeshType* m_meshCurrent; //Used to avoid creating duplicate vertices. Array<3, IndexAndMaterial> m_previousSliceVertices; @@ -198,8 +198,9 @@ namespace PolyVox template Mesh > extractCubicMesh(VolumeType* volData, Region region, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded) { - Mesh > result; - CubicSurfaceExtractor extractor(volData, region, &result, eWrapMode, tBorderValue, bMergeQuads, isQuadNeeded); + typedef Mesh > MeshType; + MeshType result; + CubicSurfaceExtractor extractor(volData, region, &result, eWrapMode, tBorderValue, bMergeQuads, isQuadNeeded); extractor.execute(); return result; } diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl index 5e00a572..6ebec5ef 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl @@ -32,11 +32,11 @@ namespace PolyVox // happens when we have a 2x2x2 group of voxels, all with different materials and some/all partially transparent. // The vertex position at the center of this group is then going to be used by all eight voxels all with different // materials. - template - const uint32_t CubicSurfaceExtractor::MaxVerticesPerPosition = 8; + template + const uint32_t CubicSurfaceExtractor::MaxVerticesPerPosition = 8; - template - CubicSurfaceExtractor::CubicSurfaceExtractor(VolumeType* volData, Region region, Mesh >* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded) + template + CubicSurfaceExtractor::CubicSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded) :m_volData(volData) ,m_regSizeInVoxels(region) ,m_meshCurrent(result) @@ -53,8 +53,8 @@ namespace PolyVox POLYVOX_THROW_IF(region.getDepthInVoxels() > maxReionDimension, std::invalid_argument, "Requested extraction region exceeds maximum dimensions"); } - template - void CubicSurfaceExtractor::execute() + template + void CubicSurfaceExtractor::execute() { Timer timer; m_meshCurrent->clear(); @@ -204,8 +204,8 @@ namespace PolyVox << "x" << m_regSizeInVoxels.getDepthInVoxels() << ")"); } - template - int32_t CubicSurfaceExtractor::addVertex(uint32_t uX, uint32_t uY, uint32_t uZ, typename VolumeType::VoxelType uMaterialIn, Array<3, IndexAndMaterial>& existingVertices) + template + int32_t CubicSurfaceExtractor::addVertex(uint32_t uX, uint32_t uY, uint32_t uZ, typename VolumeType::VoxelType uMaterialIn, Array<3, IndexAndMaterial>& existingVertices) { for(uint32_t ct = 0; ct < MaxVerticesPerPosition; ct++) { @@ -236,8 +236,8 @@ namespace PolyVox return -1; //Should never happen. } - template - bool CubicSurfaceExtractor::performQuadMerging(std::list& quads) + template + bool CubicSurfaceExtractor::performQuadMerging(std::list& quads) { bool bDidMerge = false; for(typename std::list::iterator outerIter = quads.begin(); outerIter != quads.end(); outerIter++) @@ -266,8 +266,8 @@ namespace PolyVox return bDidMerge; } - template - bool CubicSurfaceExtractor::mergeQuads(Quad& q1, Quad& q2) + template + bool CubicSurfaceExtractor::mergeQuads(Quad& q1, Quad& q2) { //All four vertices of a given quad have the same data, //so just check that the first pair of vertices match. diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h index 45f78930..34dc50b4 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.h @@ -49,16 +49,16 @@ namespace PolyVox Mesh(); ~Mesh(); - const std::vector& getIndices(void) const; + const std::vector& getIndices(void) const; uint32_t getNoOfIndices(void) const; - uint32_t getNoOfVertices(void) const; + IndexType getNoOfVertices(void) const; const std::vector& getVertices(void) const; const Vector3DInt32& getOffset(void) const; void setOffset(const Vector3DInt32& offset); - void addTriangle(uint32_t index0, uint32_t index1, uint32_t index2); - uint32_t addVertex(const VertexType& vertex); + void addTriangle(IndexType index0, IndexType index1, IndexType index2); + IndexType addVertex(const VertexType& vertex); void clear(void); bool isEmpty(void) const; void removeUnusedVertices(void); @@ -66,17 +66,17 @@ namespace PolyVox Vector3DInt32 m_offset; public: - std::vector m_vecTriangleIndices; + std::vector m_vecTriangleIndices; std::vector m_vecVertices; }; template - Mesh< Vertex< typename MeshType::VertexType::DataType > > decode(const MeshType& mesh) + Mesh< Vertex< typename MeshType::VertexType::DataType >, typename MeshType::IndexType > decode(const MeshType& mesh) { - Mesh< Vertex< typename MeshType::VertexType::DataType > > result; + Mesh< Vertex< typename MeshType::VertexType::DataType >, typename MeshType::IndexType > result; result.m_vecVertices.resize(mesh.m_vecVertices.size()); - for(uint32_t ct = 0; ct < mesh.m_vecVertices.size(); ct++) + for(MeshType::IndexType ct = 0; ct < mesh.m_vecVertices.size(); ct++) { result.m_vecVertices[ct] = decode(mesh.m_vecVertices[ct]); } diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl index 7a57c748..cd93f878 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl @@ -34,7 +34,7 @@ namespace PolyVox } template - const std::vector& Mesh::getIndices(void) const + const std::vector& Mesh::getIndices(void) const { return m_vecTriangleIndices; } @@ -46,7 +46,7 @@ namespace PolyVox } template - uint32_t Mesh::getNoOfVertices(void) const + IndexType Mesh::getNoOfVertices(void) const { return m_vecVertices.size(); } @@ -70,7 +70,7 @@ namespace PolyVox } template - void Mesh::addTriangle(uint32_t index0, uint32_t index1, uint32_t index2) + void Mesh::addTriangle(IndexType index0, IndexType index1, IndexType index2) { //Make sure the specified indices correspond to valid vertices. POLYVOX_ASSERT(index0 < m_vecVertices.size(), "Index points at an invalid vertex."); @@ -83,7 +83,7 @@ namespace PolyVox } template - uint32_t Mesh::addVertex(const VertexType& vertex) + IndexType Mesh::addVertex(const VertexType& vertex) { m_vecVertices.push_back(vertex); return m_vecVertices.size() - 1; @@ -116,7 +116,7 @@ namespace PolyVox int noOfUsedVertices = 0; std::vector newPos(m_vecVertices.size()); - for(uint32_t vertCt = 0; vertCt < m_vecVertices.size(); vertCt++) + for(IndexType vertCt = 0; vertCt < m_vecVertices.size(); vertCt++) { if(isVertexUsed[vertCt]) { diff --git a/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h b/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h index e4555893..16151e4c 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h +++ b/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h @@ -76,7 +76,7 @@ namespace PolyVox // CubicSurfaceExtractor //////////////////////////////////////////////////////////////////////////////// template class DefaultIsQuadNeeded; - template > class CubicSurfaceExtractor; + template > class CubicSurfaceExtractor; //////////////////////////////////////////////////////////////////////////////// // CubicVertex From b7be2ff7ab25c5b3ef80ec7e738035b1b27d51c4 Mon Sep 17 00:00:00 2001 From: David Williams Date: Tue, 3 Jun 2014 16:59:09 +0200 Subject: [PATCH 72/72] Added some error handling. --- library/PolyVoxCore/include/PolyVoxCore/Mesh.inl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl index cd93f878..e34f51ff 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/Mesh.inl @@ -85,6 +85,9 @@ namespace PolyVox template IndexType Mesh::addVertex(const VertexType& vertex) { + // We should not add more vertices than our chosen index type will let us index. + POLYVOX_THROW_IF(m_vecVertices.size() >= std::numeric_limits::max(), std::out_of_range, "Mesh has more vertices that the chosen index type allows."); + m_vecVertices.push_back(vertex); return m_vecVertices.size() - 1; }