diff --git a/CMakeLists.txt b/CMakeLists.txt index cadcdb15..6691be4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ # 3. This notice may not be removed or altered from any source # distribution. -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.6) PROJECT(PolyVox) @@ -55,12 +55,6 @@ else() set_package_properties(Qt4 PROPERTIES TYPE OPTIONAL PURPOSE "Building the tests") endif() -if(MSVC AND (MSVC_VERSION LESS 1600)) - # Require boost for older (pre-vc2010) Visual Studio compilers - # See library/include/polyvoxcore/impl/TypeDef.h - find_package(Boost REQUIRED) - include_directories(${Boost_INCLUDE_DIRS}) -endif() IF(CMAKE_COMPILER_IS_GNUCXX) #Maybe "OR MINGW" ADD_DEFINITIONS(-std=c++0x) #Enable C++0x mode @@ -89,7 +83,6 @@ INCLUDE(Packaging.cmake) OPTION(ENABLE_TESTS "Should the tests be built" ON) IF(ENABLE_TESTS AND QT_QTTEST_FOUND) INCLUDE(CTest) - MARK_AS_ADVANCED(FORCE DART_TESTING_TIMEOUT) #This is only needed to hide the variable in the GUI (CMake bug) until 2.8.5 MARK_AS_ADVANCED(FORCE BUILD_TESTING) ADD_SUBDIRECTORY(tests) SET(BUILD_TESTS ON) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index f33a8c7c..9b662fb2 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -1,6 +1,8 @@ #include "OpenGLWidget.h" #include +#include +//#include using namespace PolyVox; using namespace std; @@ -12,43 +14,42 @@ OpenGLWidget::OpenGLWidget(QWidget *parent) { } -void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh& surfaceMesh) +void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh& 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 + const auto& vecIndices = surfaceMesh.getIndices(); + const auto& vecVertices = surfaceMesh.getVertices(); + + //Create the VAO for the mesh + glGenVertexArrays(1, &vertexArrayObject); + glBindVertexArray(vertexArrayObject); + + //The GL_ARRAY_BUFFER will contain the list of vertex positions glGenBuffers(1, &vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); - const GLvoid* pVertices = static_cast(&(vecVertices[0])); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PositionMaterialNormal), pVertices, GL_STATIC_DRAW); - - m_uBeginIndex = 0; - m_uEndIndex = vecIndices.size(); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PositionMaterial), vecVertices.data(), GL_STATIC_DRAW); + + //and GL_ELEMENT_ARRAY_BUFFER will contain the indices + glGenBuffers(1, &indexBuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 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(PositionMaterial), 0); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + + glBindVertexArray(0); + + noOfIndices = vecIndices.size(); //Save this for the call to glDrawElements later } 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 + GLenum err = glewInit(); + if (GLEW_OK != err) { /* 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); + std::cout << "GLEW Error: " << glewGetErrorString(err) << std::endl; } //Print out some information about the OpenGL implementation. @@ -61,74 +62,121 @@ void OpenGLWidget::initializeGL() 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); + 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); + glDepthRange(0.0, 1.0); + + 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, 0.5, color, 1.0); + } + )")) + { + std::cerr << shader.log().toStdString() << std::endl; + exit(EXIT_FAILURE); + } + + shader.bindAttributeLocation("position", 0); + + if(!shader.link()) + { + 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) { //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); + + auto aspectRatio = w / (float)h; + float zNear = 1.0; + float zFar = 1000.0; + + QMatrix4x4 cameraToClipMatrix{}; + cameraToClipMatrix.frustum(-aspectRatio, aspectRatio, -1, 1, zNear, zFar); + + shader.bind(); + shader.setUniformValue("cameraToClipMatrix", cameraToClipMatrix); + shader.release(); } 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(PositionMaterialNormal), 0); - glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (GLvoid*)12); - - glDrawRangeElements(GL_TRIANGLES, m_uBeginIndex, m_uEndIndex-1, m_uEndIndex - m_uBeginIndex, GL_UNSIGNED_INT, 0); + + 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 + + glBindVertexArray(vertexArrayObject); + + glDrawElements(GL_TRIANGLES, noOfIndices, GL_UNSIGNED_INT, 0); + + glBindVertexArray(0); + + shader.release(); GLenum errCode = glGetError(); if(errCode != GL_NO_ERROR) { - //What has replaced getErrorString() in the latest OpenGL? - std::cout << "OpenGL Error: " << errCode << std::endl; + std::cerr << "OpenGL Error: " << errCode << std::endl; } } diff --git a/examples/Basic/OpenGLWidget.h b/examples/Basic/OpenGLWidget.h index 011b9734..1126aba3 100644 --- a/examples/Basic/OpenGLWidget.h +++ b/examples/Basic/OpenGLWidget.h @@ -29,6 +29,7 @@ distribution. #include "glew/glew.h" #include +#include class OpenGLWidget : public QGLWidget { @@ -40,8 +41,8 @@ public: void mouseMoveEvent(QMouseEvent* event); void mousePressEvent(QMouseEvent* event); - //Convert a SrfaceMesh to OpenGL index/vertex buffers - void setSurfaceMeshToRender(const PolyVox::SurfaceMesh& surfaceMesh); + //Convert a SurfaceMesh to OpenGL index/vertex buffers + void setSurfaceMeshToRender(const PolyVox::SurfaceMesh& surfaceMesh); protected: //Qt OpenGL functions @@ -51,11 +52,12 @@ protected: private: //Index/vertex buffer data - GLuint m_uBeginIndex; - GLuint m_uEndIndex; GLuint noOfIndices; GLuint indexBuffer; GLuint vertexBuffer; + GLuint vertexArrayObject; + + QGLShaderProgram shader; //Mouse data QPoint m_LastFrameMousePos; diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index 4cd45bab..b51df61d 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -23,7 +23,7 @@ freely, subject to the following restrictions: #include "OpenGLWidget.h" -#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.h" +#include "PolyVoxCore/CubicSurfaceExtractor.h" #include "PolyVoxCore/MarchingCubesSurfaceExtractor.h" #include "PolyVoxCore/SurfaceMesh.h" #include "PolyVoxCore/SimpleVolume.h" @@ -76,10 +76,10 @@ int main(int argc, char *argv[]) //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 = extractCubicSurfaceWithNormals(&volData, volData.getEnclosingRegion()); - auto mesh = extractMarchingCubesSurface(&volData, volData.getEnclosingRegion()); + auto mesh = extractCubicSurface(&volData, volData.getEnclosingRegion()); + //auto mesh = extractMarchingCubesSurface(&volData, volData.getEnclosingRegion()); //Pass the surface to the OpenGL window openGLWidget.setSurfaceMeshToRender(mesh); diff --git a/examples/SmoothLOD/OpenGLWidget.cpp b/examples/SmoothLOD/OpenGLWidget.cpp index 7c706648..9b016303 100644 --- a/examples/SmoothLOD/OpenGLWidget.cpp +++ b/examples/SmoothLOD/OpenGLWidget.cpp @@ -7,6 +7,15 @@ 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) {