Merge branch 'feature/vertex-and-example-refactor' into develop
This commit is contained in:
commit
6bedd40694
@ -72,6 +72,7 @@ IF(ENABLE_EXAMPLES AND QT_QTOPENGL_FOUND)
|
|||||||
ADD_SUBDIRECTORY(examples/Paging)
|
ADD_SUBDIRECTORY(examples/Paging)
|
||||||
ADD_SUBDIRECTORY(examples/OpenGL)
|
ADD_SUBDIRECTORY(examples/OpenGL)
|
||||||
ADD_SUBDIRECTORY(examples/SmoothLOD)
|
ADD_SUBDIRECTORY(examples/SmoothLOD)
|
||||||
|
ADD_SUBDIRECTORY(examples/DecodeOnGPU)
|
||||||
ADD_SUBDIRECTORY(examples/Python)
|
ADD_SUBDIRECTORY(examples/Python)
|
||||||
SET(BUILD_EXAMPLES ON)
|
SET(BUILD_EXAMPLES ON)
|
||||||
ELSE()
|
ELSE()
|
||||||
|
@ -26,7 +26,7 @@ PROJECT(BasicExample)
|
|||||||
#Projects source files
|
#Projects source files
|
||||||
SET(SRC_FILES
|
SET(SRC_FILES
|
||||||
main.cpp
|
main.cpp
|
||||||
OpenGLWidget.cpp
|
../common/OpenGLWidget.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
#Projects headers files
|
#Projects headers files
|
||||||
@ -36,19 +36,20 @@ SET(INC_FILES
|
|||||||
|
|
||||||
add_definitions(-DGLEW_STATIC)
|
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)
|
FIND_PACKAGE(OpenGL REQUIRED)
|
||||||
|
|
||||||
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
#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})
|
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR})
|
||||||
LINK_DIRECTORIES(${PolyVoxCore_BINARY_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
|
#Build
|
||||||
ADD_EXECUTABLE(BasicExample ${SRC_FILES})
|
ADD_EXECUTABLE(BasicExample ${SRC_FILES} ${COMMON_RESOURCES_RCC})
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
SET_TARGET_PROPERTIES(BasicExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
|
SET_TARGET_PROPERTIES(BasicExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
|
||||||
ENDIF(MSVC)
|
ENDIF(MSVC)
|
||||||
|
@ -1,200 +0,0 @@
|
|||||||
#include "OpenGLWidget.h"
|
|
||||||
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <QMatrix4x4>
|
|
||||||
//#include <QtMath>
|
|
||||||
|
|
||||||
using namespace PolyVox;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
OpenGLWidget::OpenGLWidget(QWidget *parent)
|
|
||||||
:QGLWidget(parent)
|
|
||||||
,m_xRotation(0)
|
|
||||||
,m_yRotation(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh<CubicVertex<uint8_t> >& surfaceMesh)
|
|
||||||
{
|
|
||||||
//Convienient access to the vertices and indices
|
|
||||||
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);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(CubicVertex<uint8_t>), 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(CubicVertex<uint8_t>), 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()
|
|
||||||
{
|
|
||||||
GLenum err = glewInit();
|
|
||||||
if (GLEW_OK != err)
|
|
||||||
{
|
|
||||||
/* Problem: glewInit failed, something is seriously wrong. */
|
|
||||||
std::cout << "GLEW Error: " << glewGetErrorString(err) << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
//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;
|
|
||||||
|
|
||||||
//Set up the clear colour
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
std::cerr << "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();
|
|
||||||
}
|
|
@ -1,69 +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/SurfaceMesh.h"
|
|
||||||
|
|
||||||
#include "glew/glew.h"
|
|
||||||
|
|
||||||
#include <QGLWidget>
|
|
||||||
#include <QGLShaderProgram>
|
|
||||||
|
|
||||||
class OpenGLWidget : public QGLWidget
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//Constructor
|
|
||||||
OpenGLWidget(QWidget *parent);
|
|
||||||
|
|
||||||
//Mouse handling
|
|
||||||
void mouseMoveEvent(QMouseEvent* event);
|
|
||||||
void mousePressEvent(QMouseEvent* event);
|
|
||||||
|
|
||||||
//Convert a SurfaceMesh to OpenGL index/vertex buffers
|
|
||||||
void setSurfaceMeshToRender(const PolyVox::SurfaceMesh<PolyVox::CubicVertex<uint8_t> >& surfaceMesh);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//Qt OpenGL functions
|
|
||||||
void initializeGL();
|
|
||||||
void resizeGL(int w, int h);
|
|
||||||
void paintGL();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//Index/vertex buffer data
|
|
||||||
GLuint noOfIndices;
|
|
||||||
GLuint indexBuffer;
|
|
||||||
GLuint vertexBuffer;
|
|
||||||
GLuint vertexArrayObject;
|
|
||||||
|
|
||||||
QGLShaderProgram shader;
|
|
||||||
|
|
||||||
//Mouse data
|
|
||||||
QPoint m_LastFrameMousePos;
|
|
||||||
QPoint m_CurrentMousePos;
|
|
||||||
int m_xRotation;
|
|
||||||
int m_yRotation;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //__BasicExample_OpenGLWidget_H__
|
|
@ -25,7 +25,7 @@ freely, subject to the following restrictions:
|
|||||||
|
|
||||||
#include "PolyVoxCore/CubicSurfaceExtractor.h"
|
#include "PolyVoxCore/CubicSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/SurfaceMesh.h"
|
#include "PolyVoxCore/Mesh.h"
|
||||||
#include "PolyVoxCore/SimpleVolume.h"
|
#include "PolyVoxCore/SimpleVolume.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
@ -78,11 +78,17 @@ int main(int argc, char *argv[])
|
|||||||
createSphereInVolume(volData, 30);
|
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.
|
// 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 = extractCubicMesh(&volData, volData.getEnclosingRegion());
|
||||||
//auto mesh = extractMarchingCubesSurface(&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
|
//Pass the surface to the OpenGL window
|
||||||
openGLWidget.setSurfaceMeshToRender(mesh);
|
openGLWidget.addMesh(decodedMesh);
|
||||||
|
//openGLWidget.addMesh(mesh2);
|
||||||
|
openGLWidget.setViewableRegion(volData.getEnclosingRegion());
|
||||||
|
|
||||||
//Run the message pump.
|
//Run the message pump.
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
75
examples/DecodeOnGPU/CMakeLists.txt
Normal file
75
examples/DecodeOnGPU/CMakeLists.txt
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# 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)
|
||||||
|
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} decode.qrc ${DECODE_RESOURCES_RCC})
|
||||||
|
|
||||||
|
#Build
|
||||||
|
ADD_EXECUTABLE(DecodeOnGPUExample ${SRC_FILES} ${COMMON_RESOURCES_RCC} ${DECODE_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)
|
19
examples/DecodeOnGPU/decode.frag
Normal file
19
examples/DecodeOnGPU/decode.frag
Normal file
@ -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(worldNormal.xyz) * 0.5 + vec3(0.5, 0.5, 0.5), 1.0);
|
||||||
|
}
|
6
examples/DecodeOnGPU/decode.qrc
Normal file
6
examples/DecodeOnGPU/decode.qrc
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<!DOCTYPE RCC><RCC version="1.0">
|
||||||
|
<qresource>
|
||||||
|
<file>decode.vert</file>
|
||||||
|
<file>decode.frag</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
33
examples/DecodeOnGPU/decode.vert
Normal file
33
examples/DecodeOnGPU/decode.vert
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#version 140
|
||||||
|
|
||||||
|
in uvec4 position; // This will be the position of the vertex in model-space
|
||||||
|
in uint normal;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
out vec4 worldNormal;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 decodedPosition = position;
|
||||||
|
decodedPosition.xyz = decodedPosition.xyz * (1.0 / 256.0);
|
||||||
|
|
||||||
|
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;
|
||||||
|
vec4 cameraPosition = worldToCameraMatrix * worldPosition;
|
||||||
|
gl_Position = cameraToClipMatrix * cameraPosition;
|
||||||
|
}
|
164
examples/DecodeOnGPU/main.cpp
Normal file
164
examples/DecodeOnGPU/main.cpp
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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 <QApplication>
|
||||||
|
|
||||||
|
//Use the PolyVox namespace
|
||||||
|
using namespace PolyVox;
|
||||||
|
|
||||||
|
void createSphereInVolume(SimpleVolume<uint8_t>& 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
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(MarchingCubesVertex< 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
|
||||||
|
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 >, 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.
|
||||||
|
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(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< 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
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
OpenGLWidget openGLWidget(0);
|
||||||
|
openGLWidget.show();
|
||||||
|
|
||||||
|
QSharedPointer<QGLShaderProgram> 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<uint8_t> 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
|
||||||
|
OpenGLMeshData meshData = buildOpenGLMeshData(mesh);
|
||||||
|
openGLWidget.addMeshData(meshData);
|
||||||
|
|
||||||
|
openGLWidget.setViewableRegion(volData.getEnclosingRegion());
|
||||||
|
|
||||||
|
//Run the message pump.
|
||||||
|
return app.exec();
|
||||||
|
}
|
@ -26,37 +26,33 @@ PROJECT(OpenGLExample)
|
|||||||
#Projects source files
|
#Projects source files
|
||||||
SET(SRC_FILES
|
SET(SRC_FILES
|
||||||
main.cpp
|
main.cpp
|
||||||
OpenGLImmediateModeSupport.cpp
|
../common/OpenGLWidget.cpp
|
||||||
OpenGLSupport.cpp
|
|
||||||
OpenGLVertexBufferObjectSupport.cpp
|
|
||||||
OpenGLWidget.cpp
|
|
||||||
Shapes.cpp
|
Shapes.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
#Projects headers files
|
#Projects headers files
|
||||||
SET(INC_FILES
|
SET(INC_FILES
|
||||||
OpenGLImmediateModeSupport.h
|
|
||||||
OpenGLSupport.h
|
|
||||||
OpenGLVertexBufferObjectSupport.h
|
|
||||||
OpenGLWidget.h
|
OpenGLWidget.h
|
||||||
Shapes.h
|
Shapes.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(-DGLEW_STATIC)
|
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)
|
FIND_PACKAGE(OpenGL REQUIRED)
|
||||||
|
|
||||||
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
#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})
|
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR})
|
||||||
LINK_DIRECTORIES(${PolyVoxCore_BINARY_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)
|
||||||
|
|
||||||
|
# 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
|
#Build
|
||||||
ADD_EXECUTABLE(OpenGLExample ${SRC_FILES})
|
ADD_EXECUTABLE(OpenGLExample ${SRC_FILES} ${COMMON_RESOURCES_RCC} ${OPENGLEXAMPLE_RESOURCES_RCC})
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
SET_TARGET_PROPERTIES(OpenGLExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
|
SET_TARGET_PROPERTIES(OpenGLExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
|
||||||
ENDIF(MSVC)
|
ENDIF(MSVC)
|
||||||
|
@ -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/SurfaceMesh.h"
|
|
||||||
|
|
||||||
using namespace PolyVox;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
void renderRegionImmediateMode(PolyVox::SurfaceMesh<MarchingCubesVertex<MaterialDensityPair44> >& mesh, unsigned int uLodLevel)
|
|
||||||
{
|
|
||||||
const vector<MarchingCubesVertex<MaterialDensityPair44> >& vecVertices = mesh.getVertices();
|
|
||||||
const vector<uint32_t>& vecIndices = mesh.getIndices();
|
|
||||||
|
|
||||||
int beginIndex = mesh.m_vecLodRecords[uLodLevel].beginIndex;
|
|
||||||
int endIndex = mesh.m_vecLodRecords[uLodLevel].endIndex;
|
|
||||||
|
|
||||||
glBegin(GL_TRIANGLES);
|
|
||||||
//for(vector<PolyVox::uint32_t>::const_iterator iterIndex = vecIndices.begin(); iterIndex != vecIndices.end(); ++iterIndex)
|
|
||||||
for(int index = beginIndex; index < endIndex; ++index)
|
|
||||||
{
|
|
||||||
const MarchingCubesVertex<MaterialDensityPair44> & 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<Vector3DFloat>(mesh.m_Region.getLowerCorner());
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t material = static_cast<uint8_t>(static_cast<double>(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();
|
|
||||||
}
|
|
@ -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::SurfaceMesh<PolyVox::MarchingCubesVertex<PolyVox::MaterialDensityPair44> >& mesh, unsigned int uLodLevel);
|
|
||||||
|
|
||||||
#endif //__OpenGLExample_OpenGLImmediateModeSupport_H__
|
|
@ -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;
|
|
||||||
}
|
|
@ -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/SurfaceMesh.h"
|
|
||||||
|
|
||||||
using namespace PolyVox;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const SurfaceMesh<MarchingCubesVertex<MaterialDensityPair44> >& mesh)
|
|
||||||
{
|
|
||||||
//Represents our filled in OpenGL vertex and index buffer objects.
|
|
||||||
OpenGLSurfaceMesh result;
|
|
||||||
|
|
||||||
//The source
|
|
||||||
result.sourceMesh = &mesh;
|
|
||||||
|
|
||||||
//Convienient access to the vertices and indices
|
|
||||||
const vector<MarchingCubesVertex<MaterialDensityPair44> >& vecVertices = mesh.getVertices();
|
|
||||||
const vector<uint32_t>& 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<MarchingCubesVertex<MaterialDensityPair44> >::const_iterator iterVertex = vecVertices.begin(); iterVertex != vecVertices.end(); ++iterVertex)
|
|
||||||
{
|
|
||||||
const MarchingCubesVertex<MaterialDensityPair44> & 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<Vector3DFloat>(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<uint8_t>(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 OpenGLSurfaceMesh& openGLSurfaceMesh, unsigned int uLodLevel)
|
|
||||||
{
|
|
||||||
int beginIndex = openGLSurfaceMesh.sourceMesh->m_vecLodRecords[uLodLevel].beginIndex;
|
|
||||||
int endIndex = openGLSurfaceMesh.sourceMesh->m_vecLodRecords[uLodLevel].endIndex;
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, openGLSurfaceMesh.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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
glDisableClientState(GL_COLOR_ARRAY);
|
|
||||||
glDisableClientState(GL_NORMAL_ARRAY);
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
}
|
|
@ -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 OpenGLSurfaceMesh
|
|
||||||
{
|
|
||||||
GLulong noOfIndices;
|
|
||||||
GLuint indexBuffer;
|
|
||||||
GLuint vertexBuffer;
|
|
||||||
const PolyVox::SurfaceMesh<PolyVox::MarchingCubesVertex<PolyVox::MaterialDensityPair44> >* sourceMesh;
|
|
||||||
};
|
|
||||||
|
|
||||||
OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const PolyVox::SurfaceMesh<PolyVox::MarchingCubesVertex<PolyVox::MaterialDensityPair44> >& mesh);
|
|
||||||
void renderRegionVertexBufferObject(const OpenGLSurfaceMesh& openGLSurfaceMesh, unsigned int uLodLevel);
|
|
||||||
|
|
||||||
#endif //__OpenGLExample_OpenGLVertexBufferObjectSupport_H__
|
|
@ -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 <QMouseEvent>
|
|
||||||
|
|
||||||
#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<MaterialDensityPair44>* volData)
|
|
||||||
{
|
|
||||||
//First we free anything from the previous volume (if there was one).
|
|
||||||
m_mapOpenGLSurfaceMeshes.clear();
|
|
||||||
m_mapSurfaceMeshes.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< SurfaceMesh<MarchingCubesVertex<MaterialDensityPair44> > > mesh(new SurfaceMesh<MarchingCubesVertex<MaterialDensityPair44> >);
|
|
||||||
MarchingCubesSurfaceExtractor< LargeVolume<MaterialDensityPair44> > 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)
|
|
||||||
{
|
|
||||||
OpenGLSurfaceMesh openGLSurfaceMesh = BuildOpenGLSurfaceMesh(*(mesh.get()));
|
|
||||||
m_mapOpenGLSurfaceMeshes.insert(make_pair(v3dRegPos, openGLSurfaceMesh));
|
|
||||||
}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
m_mapSurfaceMeshes.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_mapSurfaceMeshes.find(v3dRegPos) != m_mapSurfaceMeshes.end())
|
|
||||||
{
|
|
||||||
std::shared_ptr< SurfaceMesh<MarchingCubesVertex<MaterialDensityPair44> > > meshCurrent = m_mapSurfaceMeshes[v3dRegPos];
|
|
||||||
unsigned int uLodLevel = 0; //meshCurrent->m_vecLodRecords.size() - 1;
|
|
||||||
if(m_bUseOpenGLVertexBufferObjects)
|
|
||||||
{
|
|
||||||
renderRegionVertexBufferObject(m_mapOpenGLSurfaceMeshes[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<float>(width()) / static_cast<float>(height());
|
|
||||||
|
|
||||||
glOrtho(frustumSize*aspect, -frustumSize*aspect, frustumSize, -frustumSize, 1.0, 5000);
|
|
||||||
}
|
|
@ -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 <QGLWidget>
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
#include "PolyVoxCore/LargeVolume.h"
|
|
||||||
#include "PolyVoxCore/SurfaceMesh.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<PolyVox::MaterialDensityPair44>* 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<PolyVox::MaterialDensityPair44>* m_volData;
|
|
||||||
|
|
||||||
//Rather than storing one big mesh, the volume is broken into regions and a mesh is stored for each region
|
|
||||||
std::map<PolyVox::Vector3DUint8, OpenGLSurfaceMesh, Vector3DUint8Compare> m_mapOpenGLSurfaceMeshes;
|
|
||||||
std::map<PolyVox::Vector3DUint8, std::shared_ptr<PolyVox::SurfaceMesh<PolyVox::MarchingCubesVertex<PolyVox::MaterialDensityPair44> > >, Vector3DUint8Compare> m_mapSurfaceMeshes;
|
|
||||||
|
|
||||||
unsigned int m_uRegionSideLength;
|
|
||||||
unsigned int m_uVolumeWidthInRegions;
|
|
||||||
unsigned int m_uVolumeHeightInRegions;
|
|
||||||
unsigned int m_uVolumeDepthInRegions;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //__PolyVox_OpenGLWidget_H__
|
|
@ -27,7 +27,7 @@ freely, subject to the following restrictions:
|
|||||||
|
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
|
|
||||||
void createSphereInVolume(LargeVolume<MaterialDensityPair44>& volData, float fRadius, uint8_t uValue)
|
void createSphereInVolume(LargeVolume<MaterialDensityPair88>& volData, float fRadius, uint8_t uValue)
|
||||||
{
|
{
|
||||||
//This vector hold the position of the center of the volume
|
//This vector hold the position of the center of the volume
|
||||||
Vector3DInt32 v3dVolCenter = (volData.getEnclosingRegion().getUpperCorner() - volData.getEnclosingRegion().getLowerCorner()) / static_cast<int32_t>(2);
|
Vector3DInt32 v3dVolCenter = (volData.getEnclosingRegion().getUpperCorner() - volData.getEnclosingRegion().getLowerCorner()) / static_cast<int32_t>(2);
|
||||||
@ -48,17 +48,17 @@ void createSphereInVolume(LargeVolume<MaterialDensityPair44>& volData, float fRa
|
|||||||
//then we make it solid, otherwise we make it empty space.
|
//then we make it solid, otherwise we make it empty space.
|
||||||
if(fDistToCenter <= fRadius)
|
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<MaterialDensityPair44>& volData, Vector3DInt32 lowerCorner, Vector3DInt32 upperCorner, uint8_t uValue)
|
void createCubeInVolume(LargeVolume<MaterialDensityPair88>& volData, Vector3DInt32 lowerCorner, Vector3DInt32 upperCorner, uint8_t uValue)
|
||||||
{
|
{
|
||||||
uint8_t maxDen = MaterialDensityPair44::getMaxDensity();
|
uint8_t maxDen = MaterialDensityPair88::getMaxDensity();
|
||||||
uint8_t minDen = MaterialDensityPair44::getMinDensity();
|
uint8_t minDen = MaterialDensityPair88::getMinDensity();
|
||||||
//This three-level for loop iterates over every voxel between the specified corners
|
//This three-level for loop iterates over every voxel between the specified corners
|
||||||
for (int z = lowerCorner.getZ(); z <= upperCorner.getZ(); z++)
|
for (int z = lowerCorner.getZ(); z <= upperCorner.getZ(); z++)
|
||||||
{
|
{
|
||||||
@ -66,7 +66,7 @@ void createCubeInVolume(LargeVolume<MaterialDensityPair44>& volData, Vector3DInt
|
|||||||
{
|
{
|
||||||
for (int x = lowerCorner.getX() ; x <= upperCorner.getX(); x++)
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ freely, subject to the following restrictions:
|
|||||||
#include "PolyVoxCore/LargeVolume.h"
|
#include "PolyVoxCore/LargeVolume.h"
|
||||||
#include "PolyVoxCore/MaterialDensityPair.h"
|
#include "PolyVoxCore/MaterialDensityPair.h"
|
||||||
|
|
||||||
void createSphereInVolume(PolyVox::LargeVolume<PolyVox::MaterialDensityPair44>& volData, float fRadius, uint8_t uValue);
|
void createSphereInVolume(PolyVox::LargeVolume<PolyVox::MaterialDensityPair88>& volData, float fRadius, uint8_t uValue);
|
||||||
void createCubeInVolume(PolyVox::LargeVolume<PolyVox::MaterialDensityPair44>& volData, PolyVox::Vector3DInt32 lowerCorner, PolyVox::Vector3DInt32 upperCorner, uint8_t uValue);
|
void createCubeInVolume(PolyVox::LargeVolume<PolyVox::MaterialDensityPair88>& volData, PolyVox::Vector3DInt32 lowerCorner, PolyVox::Vector3DInt32 upperCorner, uint8_t uValue);
|
||||||
|
|
||||||
#endif //__OpenGLExample_Shapes_H__
|
#endif //__OpenGLExample_Shapes_H__
|
@ -22,16 +22,15 @@ freely, subject to the following restrictions:
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVoxCore/FilePager.h"
|
#include "PolyVoxCore/FilePager.h"
|
||||||
|
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/MaterialDensityPair.h"
|
#include "PolyVoxCore/MaterialDensityPair.h"
|
||||||
#include "PolyVoxCore/LargeVolume.h"
|
#include "PolyVoxCore/LargeVolume.h"
|
||||||
#include "PolyVoxCore/LowPassFilter.h"
|
#include "PolyVoxCore/LowPassFilter.h"
|
||||||
#include "PolyVoxCore/RawVolume.h"
|
#include "PolyVoxCore/RawVolume.h"
|
||||||
#include "PolyVoxCore/RLEBlockCompressor.h"
|
#include "PolyVoxCore/RLEBlockCompressor.h"
|
||||||
#include "PolyVoxCore/SurfaceMesh.h"
|
#include "PolyVoxCore/Mesh.h"
|
||||||
#include "PolyVoxCore/Impl/Utility.h"
|
#include "PolyVoxCore/Impl/Utility.h"
|
||||||
|
|
||||||
#include "OpenGLImmediateModeSupport.h"
|
|
||||||
#include "OpenGLVertexBufferObjectSupport.h"
|
|
||||||
#include "Shapes.h"
|
#include "Shapes.h"
|
||||||
|
|
||||||
#include "OpenGLWidget.h"
|
#include "OpenGLWidget.h"
|
||||||
@ -48,11 +47,13 @@ using namespace std;
|
|||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
const int32_t g_uVolumeSideLength = 128;
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
RLEBlockCompressor<MaterialDensityPair44>* compressor = new RLEBlockCompressor<MaterialDensityPair44>();
|
RLEBlockCompressor<MaterialDensityPair88>* compressor = new RLEBlockCompressor<MaterialDensityPair88>();
|
||||||
FilePager<MaterialDensityPair44>* pager = new FilePager<MaterialDensityPair44>("./");
|
FilePager<MaterialDensityPair88>* pager = new FilePager<MaterialDensityPair88>("./");
|
||||||
LargeVolume<MaterialDensityPair44> volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(g_uVolumeSideLength-1, g_uVolumeSideLength-1, g_uVolumeSideLength-1)), compressor, pager);
|
LargeVolume<MaterialDensityPair88> 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.
|
//Make our volume contain a sphere in the center.
|
||||||
int32_t minPos = 0;
|
int32_t minPos = 0;
|
||||||
@ -80,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, 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());
|
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<MaterialDensityPair44> tempVolume(PolyVox::Region(0,0,0,128, 128, 128));
|
|
||||||
//LowPassFilter< LargeVolume<MaterialDensityPair44>, RawVolume<MaterialDensityPair44> > 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<MaterialDensityPair44>, LargeVolume<MaterialDensityPair44> > 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);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
OpenGLWidget openGLWidget(0);
|
OpenGLWidget openGLWidget(0);
|
||||||
@ -96,12 +88,62 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
openGLWidget.show();
|
openGLWidget.show();
|
||||||
|
|
||||||
|
QSharedPointer<QGLShaderProgram> shader(new QGLShaderProgram);
|
||||||
|
|
||||||
|
if (!shader->addShaderFromSourceFile(QGLShader::Vertex, ":/openglexample.vert"))
|
||||||
|
{
|
||||||
|
std::cerr << shader->log().toStdString() << std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shader->addShaderFromSourceFile(QGLShader::Fragment, ":/openglexample.frag"))
|
||||||
|
{
|
||||||
|
std::cerr << shader->log().toStdString() << std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
openGLWidget.setShader(shader);
|
||||||
|
|
||||||
QTime time;
|
QTime time;
|
||||||
time.start();
|
time.start();
|
||||||
openGLWidget.setVolume(&volData);
|
//openGLWidget.setVolume(&volData);
|
||||||
cout << endl << "Time taken = " << time.elapsed() / 1000.0f << "s" << endl << endl;
|
cout << endl << "Time taken = " << time.elapsed() / 1000.0f << "s" << endl << endl;
|
||||||
|
|
||||||
//return 0;
|
const int32_t extractedRegionSize = 32;
|
||||||
|
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.
|
||||||
|
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);
|
||||||
|
|
||||||
|
// 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. 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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << "Rendering volume as " << meshCounter << " seperate meshes" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
openGLWidget.setViewableRegion(volData.getEnclosingRegion());
|
||||||
|
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
45
examples/OpenGL/openglexample.frag
Normal file
45
examples/OpenGL/openglexample.frag
Normal file
@ -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
|
||||||
|
}
|
6
examples/OpenGL/openglexample.qrc
Normal file
6
examples/OpenGL/openglexample.qrc
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<!DOCTYPE RCC><RCC version="1.0">
|
||||||
|
<qresource>
|
||||||
|
<file>openglexample.vert</file>
|
||||||
|
<file>openglexample.frag</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
26
examples/OpenGL/openglexample.vert
Normal file
26
examples/OpenGL/openglexample.vert
Normal file
@ -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;
|
||||||
|
}
|
@ -26,7 +26,7 @@ PROJECT(PagingExample)
|
|||||||
#Projects source files
|
#Projects source files
|
||||||
SET(SRC_FILES
|
SET(SRC_FILES
|
||||||
main.cpp
|
main.cpp
|
||||||
OpenGLWidget.cpp
|
../common/OpenGLWidget.cpp
|
||||||
Perlin.cpp
|
Perlin.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -38,25 +38,29 @@ SET(INC_FILES
|
|||||||
|
|
||||||
add_definitions(-DGLEW_STATIC)
|
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)
|
FIND_PACKAGE(OpenGL REQUIRED)
|
||||||
|
|
||||||
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
#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})
|
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR})
|
||||||
LINK_DIRECTORIES(${PolyVoxCore_BINARY_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
|
#Build
|
||||||
ADD_EXECUTABLE(PagingExample ${SRC_FILES})
|
ADD_EXECUTABLE(PagingExample ${SRC_FILES} ${COMMON_RESOURCES_RCC})
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
SET_TARGET_PROPERTIES(PagingExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
|
SET_TARGET_PROPERTIES(PagingExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
|
||||||
ENDIF(MSVC)
|
ENDIF(MSVC)
|
||||||
TARGET_LINK_LIBRARIES(PagingExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
TARGET_LINK_LIBRARIES(PagingExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
||||||
SET_PROPERTY(TARGET PagingExample PROPERTY FOLDER "Examples")
|
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
|
#Install - Only install the example in Windows
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
INSTALL(TARGETS PagingExample
|
INSTALL(TARGETS PagingExample
|
||||||
|
@ -1,135 +0,0 @@
|
|||||||
#include "OpenGLWidget.h"
|
|
||||||
|
|
||||||
#include <QMouseEvent>
|
|
||||||
|
|
||||||
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::setSurfaceMeshToRender(const PolyVox::SurfaceMesh<CubicVertex<MaterialDensityPair44> >& 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<uint32_t>& vecIndices = surfaceMesh.getIndices();
|
|
||||||
const vector<CubicVertex<MaterialDensityPair44> >& vecVertices = surfaceMesh.getVertices();
|
|
||||||
|
|
||||||
//Build an OpenGL index buffer
|
|
||||||
glGenBuffers(1, &indexBuffer);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
|
|
||||||
const GLvoid* pIndices = static_cast<const GLvoid*>(&(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<const GLvoid*>(&(vecVertices[0]));
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(CubicVertex<MaterialDensityPair44>), 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<float>(width()) / static_cast<float>(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<MaterialDensityPair44>), 0);
|
|
||||||
//glNormalPointer(GL_FLOAT, sizeof(CubicVertex<MaterialDensityPair44>), (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();
|
|
||||||
}
|
|
@ -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/SurfaceMesh.h"
|
|
||||||
|
|
||||||
#include "glew/glew.h"
|
|
||||||
|
|
||||||
#include <QGLWidget>
|
|
||||||
|
|
||||||
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 setSurfaceMeshToRender(const PolyVox::SurfaceMesh<PolyVox::CubicVertex<PolyVox::MaterialDensityPair44> >& 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__
|
|
@ -29,7 +29,7 @@ freely, subject to the following restrictions:
|
|||||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/Pager.h"
|
#include "PolyVoxCore/Pager.h"
|
||||||
#include "PolyVoxCore/RLEBlockCompressor.h"
|
#include "PolyVoxCore/RLEBlockCompressor.h"
|
||||||
#include "PolyVoxCore/SurfaceMesh.h"
|
#include "PolyVoxCore/Mesh.h"
|
||||||
#include "PolyVoxCore/LargeVolume.h"
|
#include "PolyVoxCore/LargeVolume.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
@ -186,11 +186,15 @@ int main(int argc, char *argv[])
|
|||||||
std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
||||||
|
|
||||||
//Extract the surface
|
//Extract the surface
|
||||||
auto mesh = extractCubicSurface(&volData, reg);
|
auto mesh = extractCubicMesh(&volData, reg2);
|
||||||
std::cout << "#vertices: " << mesh.getNoOfVertices() << std::endl;
|
std::cout << "#vertices: " << mesh.getNoOfVertices() << std::endl;
|
||||||
|
|
||||||
|
auto decodedMesh = decode(mesh);
|
||||||
|
|
||||||
//Pass the surface to the OpenGL window
|
//Pass the surface to the OpenGL window
|
||||||
openGLWidget.setSurfaceMeshToRender(mesh);
|
openGLWidget.addMesh(decodedMesh);
|
||||||
|
|
||||||
|
openGLWidget.setViewableRegion(reg2);
|
||||||
|
|
||||||
//Run the message pump.
|
//Run the message pump.
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
@ -21,6 +21,4 @@
|
|||||||
|
|
||||||
PROJECT(PythonExample)
|
PROJECT(PythonExample)
|
||||||
|
|
||||||
SOURCE_GROUP("Sources" FILES PythonExample.py)
|
|
||||||
|
|
||||||
configure_file(PythonExample.py PythonExample.py COPYONLY)
|
configure_file(PythonExample.py PythonExample.py COPYONLY)
|
||||||
|
@ -26,7 +26,7 @@ PROJECT(SmoothLODExample)
|
|||||||
#Projects source files
|
#Projects source files
|
||||||
SET(SRC_FILES
|
SET(SRC_FILES
|
||||||
main.cpp
|
main.cpp
|
||||||
OpenGLWidget.cpp
|
../common/OpenGLWidget.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
#Projects headers files
|
#Projects headers files
|
||||||
@ -36,25 +36,29 @@ SET(INC_FILES
|
|||||||
|
|
||||||
add_definitions(-DGLEW_STATIC)
|
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)
|
FIND_PACKAGE(OpenGL REQUIRED)
|
||||||
|
|
||||||
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
#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})
|
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR})
|
||||||
LINK_DIRECTORIES(${PolyVoxCore_BINARY_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
|
#Build
|
||||||
ADD_EXECUTABLE(SmoothLODExample ${SRC_FILES})
|
ADD_EXECUTABLE(SmoothLODExample ${SRC_FILES} ${COMMON_RESOURCES_RCC})
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
SET_TARGET_PROPERTIES(SmoothLODExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127") #All warnings
|
SET_TARGET_PROPERTIES(SmoothLODExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127") #All warnings
|
||||||
ENDIF(MSVC)
|
ENDIF(MSVC)
|
||||||
TARGET_LINK_LIBRARIES(SmoothLODExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
TARGET_LINK_LIBRARIES(SmoothLODExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
||||||
SET_PROPERTY(TARGET SmoothLODExample PROPERTY FOLDER "Examples")
|
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
|
#Install - Only install the example in Windows
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
INSTALL(TARGETS SmoothLODExample
|
INSTALL(TARGETS SmoothLODExample
|
||||||
|
@ -1,195 +0,0 @@
|
|||||||
#include "OpenGLWidget.h"
|
|
||||||
|
|
||||||
#include <QMouseEvent>
|
|
||||||
|
|
||||||
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::setSurfaceMeshToRender(const PolyVox::SurfaceMesh<MarchingCubesVertex<uint8_t> >& surfaceMesh)
|
|
||||||
{
|
|
||||||
//Convienient access to the vertices and indices
|
|
||||||
const vector<uint32_t>& vecIndices = surfaceMesh.getIndices();
|
|
||||||
const vector<MarchingCubesVertex<uint8_t> >& vecVertices = surfaceMesh.getVertices();
|
|
||||||
|
|
||||||
//Build an OpenGL index buffer
|
|
||||||
glGenBuffers(1, &indexBuffer);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
|
|
||||||
const GLvoid* pIndices = static_cast<const GLvoid*>(&(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<const GLvoid*>(&(vecVertices[0]));
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(MarchingCubesVertex<uint8_t>), pVertices, GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
m_uBeginIndex = 0;
|
|
||||||
m_uEndIndex = vecIndices.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLWidget::setSurfaceMeshToRenderLowLOD(const PolyVox::SurfaceMesh<MarchingCubesVertex<uint8_t> >& surfaceMesh)
|
|
||||||
{
|
|
||||||
//Convienient access to the vertices and indices
|
|
||||||
const vector<uint32_t>& vecIndices = surfaceMesh.getIndices();
|
|
||||||
const vector<MarchingCubesVertex<uint8_t> >& vecVertices = surfaceMesh.getVertices();
|
|
||||||
|
|
||||||
//Build an OpenGL index buffer
|
|
||||||
glGenBuffers(1, &indexBufferLow);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferLow);
|
|
||||||
const GLvoid* pIndices = static_cast<const GLvoid*>(&(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<const GLvoid*>(&(vecVertices[0]));
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(MarchingCubesVertex<uint8_t>), 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<float>(width()) / static_cast<float>(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<uint8_t>), 0);
|
|
||||||
glNormalPointer(GL_FLOAT, sizeof(MarchingCubesVertex<uint8_t>), (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<uint8_t>), 0);
|
|
||||||
glNormalPointer(GL_FLOAT, sizeof(MarchingCubesVertex<uint8_t>), (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();
|
|
||||||
}
|
|
@ -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/SurfaceMesh.h"
|
|
||||||
|
|
||||||
#include "glew/glew.h"
|
|
||||||
|
|
||||||
#include <QGLWidget>
|
|
||||||
|
|
||||||
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 setSurfaceMeshToRender(const PolyVox::SurfaceMesh<PolyVox::MarchingCubesVertex <uint8_t> >& surfaceMesh);
|
|
||||||
void setSurfaceMeshToRenderLowLOD(const PolyVox::SurfaceMesh<PolyVox::MarchingCubesVertex<uint8_t> >& 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__
|
|
@ -25,7 +25,7 @@ freely, subject to the following restrictions:
|
|||||||
|
|
||||||
#include "PolyVoxCore/Density.h"
|
#include "PolyVoxCore/Density.h"
|
||||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/SurfaceMesh.h"
|
#include "PolyVoxCore/Mesh.h"
|
||||||
#include "PolyVoxCore/RawVolume.h"
|
#include "PolyVoxCore/RawVolume.h"
|
||||||
#include "PolyVoxCore/SimpleVolume.h"
|
#include "PolyVoxCore/SimpleVolume.h"
|
||||||
#include "PolyVoxCore/VolumeResampler.h"
|
#include "PolyVoxCore/VolumeResampler.h"
|
||||||
@ -90,16 +90,20 @@ int main(int argc, char *argv[])
|
|||||||
volumeResampler.execute();
|
volumeResampler.execute();
|
||||||
|
|
||||||
//Extract the surface
|
//Extract the surface
|
||||||
auto meshLowLOD = extractMarchingCubesSurface(&volDataLowLOD, volDataLowLOD.getEnclosingRegion());
|
auto meshLowLOD = extractMarchingCubesMesh(&volDataLowLOD, volDataLowLOD.getEnclosingRegion());
|
||||||
meshLowLOD.scaleVertices(/*2.0f*/63.0f / 31.0f);
|
// The returned mesh needs to be decoded to be appropriate for GPU rendering.
|
||||||
|
auto decodedMeshLowLOD = decode(meshLowLOD);
|
||||||
|
|
||||||
//Extract the surface
|
//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));
|
// The returned mesh needs to be decoded to be appropriate for GPU rendering.
|
||||||
|
auto decodedMeshHighLOD = decode(meshHighLOD);
|
||||||
|
|
||||||
//Pass the surface to the OpenGL window
|
//Pass the surface to the OpenGL window
|
||||||
openGLWidget.setSurfaceMeshToRender(meshHighLOD);
|
openGLWidget.addMesh(decodedMeshHighLOD, Vector3DInt32(30, 0, 0));
|
||||||
openGLWidget.setSurfaceMeshToRenderLowLOD(meshLowLOD);
|
openGLWidget.addMesh(decodedMeshLowLOD, Vector3DInt32(0, 0, 0), 63.0f / 31.0f);
|
||||||
|
|
||||||
|
openGLWidget.setViewableRegion(volData.getEnclosingRegion());
|
||||||
|
|
||||||
//Run the message pump.
|
//Run the message pump.
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
196
examples/common/OpenGLWidget.cpp
Normal file
196
examples/common/OpenGLWidget.cpp
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
#include "OpenGLWidget.h"
|
||||||
|
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QMatrix4x4>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
//#include <QtMath>
|
||||||
|
|
||||||
|
using namespace PolyVox;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Public functions
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
OpenGLWidget::OpenGLWidget(QWidget *parent)
|
||||||
|
:QGLWidget(parent)
|
||||||
|
,m_viewableRegion(PolyVox::Region(0, 0, 0, 255, 255, 255))
|
||||||
|
,m_xRotation(0)
|
||||||
|
,m_yRotation(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLWidget::setShader(QSharedPointer<QGLShaderProgram> shader)
|
||||||
|
{
|
||||||
|
mShader = shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLWidget::setViewableRegion(PolyVox::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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Protected functions
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void OpenGLWidget::initializeGL()
|
||||||
|
{
|
||||||
|
GLenum err = glewInit();
|
||||||
|
if (GLEW_OK != err)
|
||||||
|
{
|
||||||
|
/* Problem: glewInit failed, something is seriously wrong. */
|
||||||
|
std::cout << "GLEW Error: " << glewGetErrorString(err) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//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;
|
||||||
|
|
||||||
|
//Set up the clear colour
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
glClearDepth(1.0f);
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
glDepthRange(0.0, 1.0);
|
||||||
|
|
||||||
|
mShader = QSharedPointer<QGLShaderProgram>(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->addShaderFromSourceFile(QGLShader::Vertex, ":/example.vert"))
|
||||||
|
{
|
||||||
|
std::cerr << mShader->log().toStdString() << std::endl;
|
||||||
|
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->addShaderFromSourceFile(QGLShader::Fragment, ":/example.frag"))
|
||||||
|
{
|
||||||
|
std::cerr << mShader->log().toStdString() << std::endl;
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!mShader->link())
|
||||||
|
{
|
||||||
|
std::cerr << mShader->log().toStdString() << std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial setup of camera.
|
||||||
|
setupWorldToCameraMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLWidget::resizeGL(int w, int h)
|
||||||
|
{
|
||||||
|
//Setup the viewport
|
||||||
|
glViewport(0, 0, w, h);
|
||||||
|
|
||||||
|
auto aspectRatio = w / (float)h;
|
||||||
|
float zNear = 1.0;
|
||||||
|
float zFar = 1000.0;
|
||||||
|
|
||||||
|
cameraToClipMatrix.setToIdentity();
|
||||||
|
cameraToClipMatrix.frustum(-aspectRatio, aspectRatio, -1, 1, zNear, zFar);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
std::cerr << "OpenGL Error: " << errCode << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private functions
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void OpenGLWidget::setupWorldToCameraMatrix()
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
156
examples/common/OpenGLWidget.h
Normal file
156
examples/common/OpenGLWidget.h
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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 <QGLWidget>
|
||||||
|
#include <QGLShaderProgram>
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
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:
|
||||||
|
// Constructor
|
||||||
|
OpenGLWidget(QWidget *parent);
|
||||||
|
|
||||||
|
// Convert a PolyVox mesh to OpenGL index/vertex buffers. Inlined because it's templatised.
|
||||||
|
template <typename DataType>
|
||||||
|
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();
|
||||||
|
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(PolyVox::Vertex< DataType >), 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(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(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(PolyVox::Vertex< DataType >), (GLvoid*)(offsetof(PolyVox::Vertex< DataType >, 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;
|
||||||
|
|
||||||
|
// Now add the mesh to the list of meshes to render.
|
||||||
|
addMeshData(meshData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addMeshData(OpenGLMeshData meshData)
|
||||||
|
{
|
||||||
|
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<QGLShaderProgram> 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
|
||||||
|
void initializeGL();
|
||||||
|
void resizeGL(int w, int h);
|
||||||
|
void paintGL();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void setupWorldToCameraMatrix();
|
||||||
|
|
||||||
|
// Index/vertex buffer data
|
||||||
|
std::vector<OpenGLMeshData> mMeshData;
|
||||||
|
|
||||||
|
QSharedPointer<QGLShaderProgram> mShader;
|
||||||
|
|
||||||
|
// Matrices
|
||||||
|
QMatrix4x4 worldToCameraMatrix;
|
||||||
|
QMatrix4x4 cameraToClipMatrix;
|
||||||
|
|
||||||
|
// Mouse data
|
||||||
|
QPoint m_LastFrameMousePos;
|
||||||
|
QPoint m_CurrentMousePos;
|
||||||
|
|
||||||
|
// Camera setup
|
||||||
|
PolyVox::Region m_viewableRegion;
|
||||||
|
int m_xRotation;
|
||||||
|
int m_yRotation;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__BasicExample_OpenGLWidget_H__
|
19
examples/common/example.frag
Normal file
19
examples/common/example.frag
Normal file
@ -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);
|
||||||
|
}
|
6
examples/common/example.qrc
Normal file
6
examples/common/example.qrc
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<!DOCTYPE RCC><RCC version="1.0">
|
||||||
|
<qresource>
|
||||||
|
<file>example.vert</file>
|
||||||
|
<file>example.frag</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
20
examples/common/example.vert
Normal file
20
examples/common/example.vert
Normal file
@ -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;
|
||||||
|
}
|
@ -27,7 +27,6 @@ SET(CORE_SRC_FILES
|
|||||||
source/ArraySizes.cpp
|
source/ArraySizes.cpp
|
||||||
source/AStarPathfinder.cpp
|
source/AStarPathfinder.cpp
|
||||||
source/Region.cpp
|
source/Region.cpp
|
||||||
source/VertexTypes.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
#Projects headers files
|
#Projects headers files
|
||||||
@ -66,6 +65,8 @@ SET(CORE_INC_FILES
|
|||||||
include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl
|
include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl
|
||||||
include/PolyVoxCore/Material.h
|
include/PolyVoxCore/Material.h
|
||||||
include/PolyVoxCore/MaterialDensityPair.h
|
include/PolyVoxCore/MaterialDensityPair.h
|
||||||
|
include/PolyVoxCore/Mesh.h
|
||||||
|
include/PolyVoxCore/Mesh.inl
|
||||||
include/PolyVoxCore/MinizBlockCompressor.h
|
include/PolyVoxCore/MinizBlockCompressor.h
|
||||||
include/PolyVoxCore/MinizBlockCompressor.inl
|
include/PolyVoxCore/MinizBlockCompressor.inl
|
||||||
include/PolyVoxCore/Pager.h
|
include/PolyVoxCore/Pager.h
|
||||||
@ -84,13 +85,11 @@ SET(CORE_INC_FILES
|
|||||||
include/PolyVoxCore/SimpleVolume.inl
|
include/PolyVoxCore/SimpleVolume.inl
|
||||||
include/PolyVoxCore/SimpleVolumeBlock.inl
|
include/PolyVoxCore/SimpleVolumeBlock.inl
|
||||||
include/PolyVoxCore/SimpleVolumeSampler.inl
|
include/PolyVoxCore/SimpleVolumeSampler.inl
|
||||||
include/PolyVoxCore/SurfaceMesh.h
|
|
||||||
include/PolyVoxCore/SurfaceMesh.inl
|
|
||||||
include/PolyVoxCore/UncompressedBlock.h
|
include/PolyVoxCore/UncompressedBlock.h
|
||||||
include/PolyVoxCore/UncompressedBlock.inl
|
include/PolyVoxCore/UncompressedBlock.inl
|
||||||
include/PolyVoxCore/Vector.h
|
include/PolyVoxCore/Vector.h
|
||||||
include/PolyVoxCore/Vector.inl
|
include/PolyVoxCore/Vector.inl
|
||||||
include/PolyVoxCore/VertexTypes.h
|
include/PolyVoxCore/Vertex.h
|
||||||
include/PolyVoxCore/VolumeResampler.h
|
include/PolyVoxCore/VolumeResampler.h
|
||||||
include/PolyVoxCore/VolumeResampler.inl
|
include/PolyVoxCore/VolumeResampler.inl
|
||||||
include/PolyVoxCore/VoxelFilters.h
|
include/PolyVoxCore/VoxelFilters.h
|
||||||
@ -130,11 +129,11 @@ SET(IMPL_INC_FILES
|
|||||||
|
|
||||||
#"Sources" and "Headers" are the group names in Visual Studio.
|
#"Sources" and "Headers" are the group names in Visual Studio.
|
||||||
#They may have other uses too...
|
#They may have other uses too...
|
||||||
SOURCE_GROUP("Sources" FILES ${CORE_SRC_FILES})
|
SOURCE_GROUP("Source Files" FILES ${CORE_SRC_FILES})
|
||||||
SOURCE_GROUP("Headers" FILES ${CORE_INC_FILES})
|
SOURCE_GROUP("Header Files" FILES ${CORE_INC_FILES})
|
||||||
|
|
||||||
SOURCE_GROUP("Sources\\Impl" FILES ${IMPL_SRC_FILES})
|
SOURCE_GROUP("Source Files\\Impl" FILES ${IMPL_SRC_FILES})
|
||||||
SOURCE_GROUP("Headers\\Impl" FILES ${IMPL_INC_FILES})
|
SOURCE_GROUP("Header Files\\Impl" FILES ${IMPL_INC_FILES})
|
||||||
|
|
||||||
#Tell CMake the paths
|
#Tell CMake the paths
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
@ -31,10 +31,47 @@ freely, subject to the following restrictions:
|
|||||||
#include "PolyVoxCore/Array.h"
|
#include "PolyVoxCore/Array.h"
|
||||||
#include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these?
|
#include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these?
|
||||||
#include "PolyVoxCore/DefaultIsQuadNeeded.h"
|
#include "PolyVoxCore/DefaultIsQuadNeeded.h"
|
||||||
#include "PolyVoxCore/SurfaceMesh.h"
|
#include "PolyVoxCore/Mesh.h"
|
||||||
|
#include "PolyVoxCore/Vertex.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
|
#ifdef SWIG
|
||||||
|
struct CubicVertex
|
||||||
|
#else
|
||||||
|
template<typename _DataType>
|
||||||
|
struct POLYVOX_API CubicVertex
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
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 encodedPosition;
|
||||||
|
|
||||||
|
// User data
|
||||||
|
DataType data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Decodes a position from a CubicVertex
|
||||||
|
inline Vector3DFloat decode(const Vector3DUint8& encodedPosition)
|
||||||
|
{
|
||||||
|
Vector3DFloat result(encodedPosition.getX(), encodedPosition.getY(), encodedPosition.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<typename DataType>
|
||||||
|
Vertex<DataType> decode(const CubicVertex<DataType>& cubicVertex)
|
||||||
|
{
|
||||||
|
Vertex<DataType> result;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/// The CubicSurfaceExtractor creates a mesh in which each voxel appears to be rendered as a cube
|
/// The CubicSurfaceExtractor creates a mesh in which each voxel appears to be rendered as a cube
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Introduction
|
/// Introduction
|
||||||
@ -76,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.
|
/// 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<typename VolumeType, typename IsQuadNeeded>
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
||||||
class CubicSurfaceExtractor
|
class CubicSurfaceExtractor
|
||||||
{
|
{
|
||||||
struct IndexAndMaterial
|
struct IndexAndMaterial
|
||||||
@ -113,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
|
// 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?
|
// 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)
|
#if defined(_MSC_VER)
|
||||||
CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<CubicVertex<typename VolumeType::VoxelType> >* 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
|
#else
|
||||||
CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<CubicVertex<typename VolumeType::VoxelType> >* 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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -135,7 +172,7 @@ namespace PolyVox
|
|||||||
Region m_regSizeInVoxels;
|
Region m_regSizeInVoxels;
|
||||||
|
|
||||||
//The surface patch we are currently filling.
|
//The surface patch we are currently filling.
|
||||||
SurfaceMesh<CubicVertex<typename VolumeType::VoxelType> >* m_meshCurrent;
|
MeshType* m_meshCurrent;
|
||||||
|
|
||||||
//Used to avoid creating duplicate vertices.
|
//Used to avoid creating duplicate vertices.
|
||||||
Array<3, IndexAndMaterial> m_previousSliceVertices;
|
Array<3, IndexAndMaterial> m_previousSliceVertices;
|
||||||
@ -159,10 +196,11 @@ namespace PolyVox
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename VolumeType, typename IsQuadNeeded>
|
template<typename VolumeType, typename IsQuadNeeded>
|
||||||
SurfaceMesh<CubicVertex<typename VolumeType::VoxelType> > extractCubicSurface(VolumeType* volData, Region region, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded)
|
Mesh<CubicVertex<typename VolumeType::VoxelType> > extractCubicMesh(VolumeType* volData, Region region, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded)
|
||||||
{
|
{
|
||||||
SurfaceMesh<CubicVertex<typename VolumeType::VoxelType> > result;
|
typedef Mesh<CubicVertex<typename VolumeType::VoxelType> > MeshType;
|
||||||
CubicSurfaceExtractor<VolumeType, IsQuadNeeded> extractor(volData, region, &result, eWrapMode, tBorderValue, bMergeQuads, isQuadNeeded);
|
MeshType result;
|
||||||
|
CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded> extractor(volData, region, &result, eWrapMode, tBorderValue, bMergeQuads, isQuadNeeded);
|
||||||
extractor.execute();
|
extractor.execute();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -171,13 +209,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
|
// 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?
|
// 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)
|
#if defined(_MSC_VER)
|
||||||
SurfaceMesh<CubicVertex<typename VolumeType::VoxelType> > extractCubicSurface(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true)
|
Mesh<CubicVertex<typename VolumeType::VoxelType> > extractCubicMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true)
|
||||||
#else
|
#else
|
||||||
SurfaceMesh<CubicVertex<typename VolumeType::VoxelType> > extractCubicSurface(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true)
|
Mesh<CubicVertex<typename VolumeType::VoxelType> > extractCubicMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
DefaultIsQuadNeeded<typename VolumeType::VoxelType> isQuadNeeded;
|
DefaultIsQuadNeeded<typename VolumeType::VoxelType> isQuadNeeded;
|
||||||
return extractCubicSurface<VolumeType, DefaultIsQuadNeeded<typename VolumeType::VoxelType> >(volData, region, eWrapMode, tBorderValue, bMergeQuads, isQuadNeeded);
|
return extractCubicMesh<VolumeType, DefaultIsQuadNeeded<typename VolumeType::VoxelType> >(volData, region, eWrapMode, tBorderValue, bMergeQuads, isQuadNeeded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,11 +32,11 @@ namespace PolyVox
|
|||||||
// happens when we have a 2x2x2 group of voxels, all with different materials and some/all partially transparent.
|
// 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
|
// The vertex position at the center of this group is then going to be used by all eight voxels all with different
|
||||||
// materials.
|
// materials.
|
||||||
template<typename VolumeType, typename IsQuadNeeded>
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
||||||
const uint32_t CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::MaxVerticesPerPosition = 8;
|
const uint32_t CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::MaxVerticesPerPosition = 8;
|
||||||
|
|
||||||
template<typename VolumeType, typename IsQuadNeeded>
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
||||||
CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<CubicVertex<typename VolumeType::VoxelType> >* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded)
|
CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::CubicSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded)
|
||||||
:m_volData(volData)
|
:m_volData(volData)
|
||||||
,m_regSizeInVoxels(region)
|
,m_regSizeInVoxels(region)
|
||||||
,m_meshCurrent(result)
|
,m_meshCurrent(result)
|
||||||
@ -45,10 +45,16 @@ namespace PolyVox
|
|||||||
,m_tBorderValue(tBorderValue)
|
,m_tBorderValue(tBorderValue)
|
||||||
{
|
{
|
||||||
m_funcIsQuadNeededCallback = isQuadNeeded;
|
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<typename VolumeType, typename IsQuadNeeded>
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
||||||
void CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::execute()
|
void CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::execute()
|
||||||
{
|
{
|
||||||
Timer timer;
|
Timer timer;
|
||||||
m_meshCurrent->clear();
|
m_meshCurrent->clear();
|
||||||
@ -184,28 +190,22 @@ namespace PolyVox
|
|||||||
for(typename std::list<Quad>::iterator quadIter = listQuads.begin(); quadIter != iterEnd; quadIter++)
|
for(typename std::list<Quad>::iterator quadIter = listQuads.begin(); quadIter != iterEnd; quadIter++)
|
||||||
{
|
{
|
||||||
Quad& quad = *quadIter;
|
Quad& quad = *quadIter;
|
||||||
m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[1],quad.vertices[2]);
|
m_meshCurrent->addTriangle(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[2],quad.vertices[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_meshCurrent->m_Region = m_regSizeInVoxels;
|
m_meshCurrent->setOffset(m_regSizeInVoxels.getLowerCorner());
|
||||||
m_meshCurrent->removeUnusedVertices();
|
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()
|
POLYVOX_LOG_TRACE("Cubic surface extraction took " << timer.elapsedTimeInMilliSeconds()
|
||||||
<< "ms (Region size = " << m_regSizeInVoxels.getWidthInVoxels() << "x" << m_regSizeInVoxels.getHeightInVoxels()
|
<< "ms (Region size = " << m_regSizeInVoxels.getWidthInVoxels() << "x" << m_regSizeInVoxels.getHeightInVoxels()
|
||||||
<< "x" << m_regSizeInVoxels.getDepthInVoxels() << ")");
|
<< "x" << m_regSizeInVoxels.getDepthInVoxels() << ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType, typename IsQuadNeeded>
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
||||||
int32_t CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::addVertex(uint32_t uX, uint32_t uY, uint32_t uZ, typename VolumeType::VoxelType uMaterialIn, Array<3, IndexAndMaterial>& existingVertices)
|
int32_t CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::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++)
|
for(uint32_t ct = 0; ct < MaxVerticesPerPosition; ct++)
|
||||||
{
|
{
|
||||||
@ -214,7 +214,10 @@ namespace PolyVox
|
|||||||
if(rEntry.iIndex == -1)
|
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.
|
//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<typename VolumeType::VoxelType>(Vector3DFloat(static_cast<float>(uX)-0.5f, static_cast<float>(uY)-0.5f, static_cast<float>(uZ)-0.5f), uMaterialIn));
|
CubicVertex<typename VolumeType::VoxelType> cubicVertex;
|
||||||
|
cubicVertex.encodedPosition.setElements(static_cast<uint8_t>(uX), static_cast<uint8_t>(uY), static_cast<uint8_t>(uZ));
|
||||||
|
cubicVertex.data = uMaterialIn;
|
||||||
|
rEntry.iIndex = m_meshCurrent->addVertex(cubicVertex);
|
||||||
rEntry.uMaterial = uMaterialIn;
|
rEntry.uMaterial = uMaterialIn;
|
||||||
|
|
||||||
return rEntry.iIndex;
|
return rEntry.iIndex;
|
||||||
@ -233,8 +236,8 @@ namespace PolyVox
|
|||||||
return -1; //Should never happen.
|
return -1; //Should never happen.
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType, typename IsQuadNeeded>
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
||||||
bool CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::performQuadMerging(std::list<Quad>& quads)
|
bool CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::performQuadMerging(std::list<Quad>& quads)
|
||||||
{
|
{
|
||||||
bool bDidMerge = false;
|
bool bDidMerge = false;
|
||||||
for(typename std::list<Quad>::iterator outerIter = quads.begin(); outerIter != quads.end(); outerIter++)
|
for(typename std::list<Quad>::iterator outerIter = quads.begin(); outerIter != quads.end(); outerIter++)
|
||||||
@ -263,12 +266,12 @@ namespace PolyVox
|
|||||||
return bDidMerge;
|
return bDidMerge;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType, typename IsQuadNeeded>
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
||||||
bool CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::mergeQuads(Quad& q1, Quad& q2)
|
bool CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::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.
|
//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]].data == m_meshCurrent->getVertices()[q2.vertices[0]].data)
|
||||||
{
|
{
|
||||||
//Now check whether quad 2 is adjacent to quad one by comparing vertices.
|
//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
|
//Adjacent quads must share two vertices, and the second quad could be to the
|
||||||
|
@ -55,7 +55,7 @@ namespace PolyVox
|
|||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
Vector3DFloat computeSmoothSobelGradient(typename VolumeType::Sampler& volIter);
|
Vector3DFloat computeSmoothSobelGradient(typename VolumeType::Sampler& volIter);
|
||||||
|
|
||||||
//POLYVOX_API void computeNormalsForVertices(VolumeType<uint8_t>* volumeData, SurfaceMesh<PositionMaterialNormal>& mesh, NormalGenerationMethod normalGenerationMethod);
|
//POLYVOX_API void computeNormalsForVertices(VolumeType<uint8_t>* volumeData, Mesh<PositionMaterialNormal>& mesh, NormalGenerationMethod normalGenerationMethod);
|
||||||
//POLYVOX_API Vector3DFloat computeNormal(VolumeType<uint8_t>* volumeData, const Vector3DFloat& v3dPos, NormalGenerationMethod normalGenerationMethod);
|
//POLYVOX_API Vector3DFloat computeNormal(VolumeType<uint8_t>* volumeData, const Vector3DFloat& v3dPos, NormalGenerationMethod normalGenerationMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,11 +29,72 @@ freely, subject to the following restrictions:
|
|||||||
|
|
||||||
#include "PolyVoxCore/Array.h"
|
#include "PolyVoxCore/Array.h"
|
||||||
#include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these?
|
#include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these?
|
||||||
#include "PolyVoxCore/SurfaceMesh.h"
|
#include "PolyVoxCore/Mesh.h"
|
||||||
#include "PolyVoxCore/DefaultMarchingCubesController.h"
|
#include "PolyVoxCore/DefaultMarchingCubesController.h"
|
||||||
|
#include "PolyVoxCore/Vertex.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
|
#ifdef SWIG
|
||||||
|
struct MarchingCubesVertex
|
||||||
|
#else
|
||||||
|
template<typename _DataType>
|
||||||
|
struct POLYVOX_API MarchingCubesVertex
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
typedef _DataType DataType;
|
||||||
|
|
||||||
|
// Each component of the position is stored using 8.8 fixed-point encoding.
|
||||||
|
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 encodedNormal;
|
||||||
|
|
||||||
|
// User data
|
||||||
|
DataType data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Decodes a position from a MarchingCubesVertex
|
||||||
|
inline Vector3DFloat decode(const Vector3DUint16& encodedPosition)
|
||||||
|
{
|
||||||
|
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 encodedNormal)
|
||||||
|
{
|
||||||
|
// Get normal components in the range 0 to 31
|
||||||
|
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);
|
||||||
|
|
||||||
|
// 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<typename DataType>
|
||||||
|
Vertex<DataType> decode(const MarchingCubesVertex<DataType>& marchingCubesVertex)
|
||||||
|
{
|
||||||
|
Vertex<DataType> result;
|
||||||
|
result.position = decode(marchingCubesVertex.encodedPosition);
|
||||||
|
result.normal = decode(marchingCubesVertex.encodedNormal);
|
||||||
|
result.data = marchingCubesVertex.data; // Data is not encoded
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
template< typename VolumeType, typename Controller = DefaultMarchingCubesController<typename VolumeType::VoxelType> >
|
template< typename VolumeType, typename Controller = DefaultMarchingCubesController<typename VolumeType::VoxelType> >
|
||||||
class MarchingCubesSurfaceExtractor
|
class MarchingCubesSurfaceExtractor
|
||||||
{
|
{
|
||||||
@ -41,9 +102,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
|
// 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?
|
// 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)
|
#if defined(_MSC_VER)
|
||||||
MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<MarchingCubesVertex<typename VolumeType::VoxelType> >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), Controller controller = Controller());
|
MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, Mesh<MarchingCubesVertex<typename VolumeType::VoxelType> >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), Controller controller = Controller());
|
||||||
#else
|
#else
|
||||||
MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<MarchingCubesVertex<typename VolumeType::VoxelType> >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), Controller controller = Controller());
|
MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, Mesh<MarchingCubesVertex<typename VolumeType::VoxelType> >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), Controller controller = Controller());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void execute();
|
void execute();
|
||||||
@ -193,7 +254,7 @@ namespace PolyVox
|
|||||||
uint32_t m_uNoOfOccupiedCells;
|
uint32_t m_uNoOfOccupiedCells;
|
||||||
|
|
||||||
//The surface patch we are currently filling.
|
//The surface patch we are currently filling.
|
||||||
SurfaceMesh<MarchingCubesVertex<typename VolumeType::VoxelType> >* m_meshCurrent;
|
Mesh<MarchingCubesVertex<typename VolumeType::VoxelType> >* m_meshCurrent;
|
||||||
|
|
||||||
//Information about the region we are currently processing
|
//Information about the region we are currently processing
|
||||||
Region m_regSizeInVoxels;
|
Region m_regSizeInVoxels;
|
||||||
@ -212,9 +273,9 @@ namespace PolyVox
|
|||||||
};
|
};
|
||||||
|
|
||||||
template< typename VolumeType, typename Controller>
|
template< typename VolumeType, typename Controller>
|
||||||
SurfaceMesh<MarchingCubesVertex<typename VolumeType::VoxelType> > extractMarchingCubesSurface(VolumeType* volData, Region region, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, Controller controller)
|
Mesh<MarchingCubesVertex<typename VolumeType::VoxelType> > extractMarchingCubesMesh(VolumeType* volData, Region region, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, Controller controller)
|
||||||
{
|
{
|
||||||
SurfaceMesh<MarchingCubesVertex<typename VolumeType::VoxelType> > result;
|
Mesh<MarchingCubesVertex<typename VolumeType::VoxelType> > result;
|
||||||
MarchingCubesSurfaceExtractor<VolumeType, Controller> extractor(volData, region, &result, eWrapMode, tBorderValue, controller);
|
MarchingCubesSurfaceExtractor<VolumeType, Controller> extractor(volData, region, &result, eWrapMode, tBorderValue, controller);
|
||||||
extractor.execute();
|
extractor.execute();
|
||||||
return result;
|
return result;
|
||||||
@ -224,13 +285,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
|
// 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?
|
// 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)
|
#if defined(_MSC_VER)
|
||||||
SurfaceMesh<MarchingCubesVertex<typename VolumeType::VoxelType> > extractMarchingCubesSurface(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType())
|
Mesh<MarchingCubesVertex<typename VolumeType::VoxelType> > extractMarchingCubesMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType())
|
||||||
#else
|
#else
|
||||||
SurfaceMesh<MarchingCubesVertex<typename VolumeType::VoxelType> > extractMarchingCubesSurface(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType())
|
Mesh<MarchingCubesVertex<typename VolumeType::VoxelType> > extractMarchingCubesMesh(VolumeType* volData, Region region, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType())
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
DefaultMarchingCubesController<typename VolumeType::VoxelType> controller;
|
DefaultMarchingCubesController<typename VolumeType::VoxelType> controller;
|
||||||
return extractMarchingCubesSurface(volData, region, eWrapMode, tBorderValue, controller);
|
return extractMarchingCubesMesh(volData, region, eWrapMode, tBorderValue, controller);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ freely, subject to the following restrictions:
|
|||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
template<typename VolumeType, typename Controller>
|
template<typename VolumeType, typename Controller>
|
||||||
MarchingCubesSurfaceExtractor<VolumeType, Controller>::MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<MarchingCubesVertex<typename VolumeType::VoxelType> >* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, Controller controller)
|
MarchingCubesSurfaceExtractor<VolumeType, Controller>::MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, Mesh<MarchingCubesVertex<typename VolumeType::VoxelType> >* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, Controller controller)
|
||||||
:m_volData(volData)
|
:m_volData(volData)
|
||||||
,m_sampVolume(volData)
|
,m_sampVolume(volData)
|
||||||
,m_meshCurrent(result)
|
,m_meshCurrent(result)
|
||||||
@ -122,13 +122,7 @@ namespace PolyVox
|
|||||||
m_regSliceCurrent.shift(Vector3DInt32(0,0,1));
|
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;
|
|
||||||
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()
|
POLYVOX_LOG_TRACE("Marching cubes surface extraction took " << timer.elapsedTimeInMilliSeconds()
|
||||||
<< "ms (Region size = " << m_regSizeInVoxels.getWidthInVoxels() << "x" << m_regSizeInVoxels.getHeightInVoxels()
|
<< "ms (Region size = " << m_regSizeInVoxels.getWidthInVoxels() << "x" << m_regSizeInVoxels.getHeightInVoxels()
|
||||||
@ -446,6 +440,7 @@ namespace PolyVox
|
|||||||
const float fInterp = static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v100) - m_controller.convertToDensity(v000));
|
const float fInterp = static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v100) - m_controller.convertToDensity(v000));
|
||||||
|
|
||||||
const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerX()) + fInterp, static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerY()), static_cast<float>(iZVolSpace - m_regSizeInCells.getLowerZ()));
|
const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerX()) + fInterp, static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerY()), static_cast<float>(iZVolSpace - m_regSizeInCells.getLowerZ()));
|
||||||
|
const Vector3DUint16 v3dScaledPosition(static_cast<uint16_t>(v3dPosition.getX() * 256.0f), static_cast<uint16_t>(v3dPosition.getY() * 256.0f), static_cast<uint16_t>(v3dPosition.getZ() * 256.0f));
|
||||||
|
|
||||||
Vector3DFloat v3dNormal = (n100*fInterp) + (n000*(1-fInterp));
|
Vector3DFloat v3dNormal = (n100*fInterp) + (n000*(1-fInterp));
|
||||||
|
|
||||||
@ -456,10 +451,23 @@ namespace PolyVox
|
|||||||
v3dNormal.normalise();
|
v3dNormal.normalise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v3dNormal += Vector3DFloat(1.0f, 1.0f, 1.0f);
|
||||||
|
uint16_t encodedX = static_cast<uint16_t>(roundToNearestInteger(v3dNormal.getX() * 15.5f));
|
||||||
|
uint16_t encodedY = static_cast<uint16_t>(roundToNearestInteger(v3dNormal.getY() * 15.5f));
|
||||||
|
uint16_t encodedZ = static_cast<uint16_t>(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.
|
// 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 typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v100, fInterp);
|
||||||
|
|
||||||
const MarchingCubesVertex<typename VolumeType::VoxelType> surfaceVertex(v3dPosition, v3dNormal, uMaterial);
|
MarchingCubesVertex<typename VolumeType::VoxelType> surfaceVertex;
|
||||||
|
surfaceVertex.encodedPosition = v3dScaledPosition;
|
||||||
|
surfaceVertex.encodedNormal = encodedNormal;
|
||||||
|
surfaceVertex.data = uMaterial;
|
||||||
|
|
||||||
const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
|
const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
|
||||||
m_pCurrentVertexIndicesX[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex;
|
m_pCurrentVertexIndicesX[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex;
|
||||||
|
|
||||||
@ -475,6 +483,7 @@ namespace PolyVox
|
|||||||
const float fInterp = static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v010) - m_controller.convertToDensity(v000));
|
const float fInterp = static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v010) - m_controller.convertToDensity(v000));
|
||||||
|
|
||||||
const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerX()), static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerY()) + fInterp, static_cast<float>(iZVolSpace - m_regSizeInVoxels.getLowerZ()));
|
const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerX()), static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerY()) + fInterp, static_cast<float>(iZVolSpace - m_regSizeInVoxels.getLowerZ()));
|
||||||
|
const Vector3DUint16 v3dScaledPosition(static_cast<uint16_t>(v3dPosition.getX() * 256.0f), static_cast<uint16_t>(v3dPosition.getY() * 256.0f), static_cast<uint16_t>(v3dPosition.getZ() * 256.0f));
|
||||||
|
|
||||||
Vector3DFloat v3dNormal = (n010*fInterp) + (n000*(1-fInterp));
|
Vector3DFloat v3dNormal = (n010*fInterp) + (n000*(1-fInterp));
|
||||||
|
|
||||||
@ -485,10 +494,23 @@ namespace PolyVox
|
|||||||
v3dNormal.normalise();
|
v3dNormal.normalise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v3dNormal += Vector3DFloat(1.0f, 1.0f, 1.0f);
|
||||||
|
uint16_t encodedX = static_cast<uint16_t>(roundToNearestInteger(v3dNormal.getX() * 15.5f));
|
||||||
|
uint16_t encodedY = static_cast<uint16_t>(roundToNearestInteger(v3dNormal.getY() * 15.5f));
|
||||||
|
uint16_t encodedZ = static_cast<uint16_t>(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.
|
// 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);
|
const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v010, fInterp);
|
||||||
|
|
||||||
MarchingCubesVertex<typename VolumeType::VoxelType> surfaceVertex(v3dPosition, v3dNormal, uMaterial);
|
MarchingCubesVertex<typename VolumeType::VoxelType> surfaceVertex;
|
||||||
|
surfaceVertex.encodedPosition = v3dScaledPosition;
|
||||||
|
surfaceVertex.encodedNormal = encodedNormal;
|
||||||
|
surfaceVertex.data = 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_pCurrentVertexIndicesY[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex;
|
||||||
|
|
||||||
@ -504,6 +526,7 @@ namespace PolyVox
|
|||||||
const float fInterp = static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v001) - m_controller.convertToDensity(v000));
|
const float fInterp = static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v001) - m_controller.convertToDensity(v000));
|
||||||
|
|
||||||
const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerX()), static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerY()), static_cast<float>(iZVolSpace - m_regSizeInVoxels.getLowerZ()) + fInterp);
|
const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerX()), static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerY()), static_cast<float>(iZVolSpace - m_regSizeInVoxels.getLowerZ()) + fInterp);
|
||||||
|
const Vector3DUint16 v3dScaledPosition(static_cast<uint16_t>(v3dPosition.getX() * 256.0f), static_cast<uint16_t>(v3dPosition.getY() * 256.0f), static_cast<uint16_t>(v3dPosition.getZ() * 256.0f));
|
||||||
|
|
||||||
Vector3DFloat v3dNormal = (n001*fInterp) + (n000*(1-fInterp));
|
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
|
// The gradient for a voxel can be zero (e.g. solid voxel surrounded by empty ones) and so
|
||||||
@ -513,10 +536,23 @@ namespace PolyVox
|
|||||||
v3dNormal.normalise();
|
v3dNormal.normalise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v3dNormal += Vector3DFloat(1.0f, 1.0f, 1.0f);
|
||||||
|
uint16_t encodedX = static_cast<uint16_t>(roundToNearestInteger(v3dNormal.getX() * 15.5f));
|
||||||
|
uint16_t encodedY = static_cast<uint16_t>(roundToNearestInteger(v3dNormal.getY() * 15.5f));
|
||||||
|
uint16_t encodedZ = static_cast<uint16_t>(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.
|
// 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 typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v001, fInterp);
|
||||||
|
|
||||||
const MarchingCubesVertex<typename VolumeType::VoxelType> surfaceVertex(v3dPosition, v3dNormal, uMaterial);
|
MarchingCubesVertex<typename VolumeType::VoxelType> surfaceVertex;
|
||||||
|
surfaceVertex.encodedPosition = v3dScaledPosition;
|
||||||
|
surfaceVertex.encodedNormal = encodedNormal;
|
||||||
|
surfaceVertex.data = uMaterial;
|
||||||
|
|
||||||
const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
|
const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
|
||||||
m_pCurrentVertexIndicesZ[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex;
|
m_pCurrentVertexIndicesZ[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex;
|
||||||
|
|
||||||
|
94
library/PolyVoxCore/include/PolyVoxCore/Mesh.h
Normal file
94
library/PolyVoxCore/include/PolyVoxCore/Mesh.h
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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/Vertex.h" //Should probably do away with this on in the future...
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace PolyVox
|
||||||
|
{
|
||||||
|
template <typename VertexType, typename IndexType = uint32_t>
|
||||||
|
class Mesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef VertexType VertexType;
|
||||||
|
typedef IndexType IndexType;
|
||||||
|
|
||||||
|
Mesh();
|
||||||
|
~Mesh();
|
||||||
|
|
||||||
|
const std::vector<IndexType>& getIndices(void) const;
|
||||||
|
uint32_t getNoOfIndices(void) const;
|
||||||
|
IndexType getNoOfVertices(void) const;
|
||||||
|
const std::vector<VertexType>& getVertices(void) const;
|
||||||
|
const Vector3DInt32& getOffset(void) const;
|
||||||
|
|
||||||
|
void setOffset(const Vector3DInt32& offset);
|
||||||
|
|
||||||
|
void addTriangle(IndexType index0, IndexType index1, IndexType index2);
|
||||||
|
IndexType addVertex(const VertexType& vertex);
|
||||||
|
void clear(void);
|
||||||
|
bool isEmpty(void) const;
|
||||||
|
void removeUnusedVertices(void);
|
||||||
|
|
||||||
|
Vector3DInt32 m_offset;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::vector<IndexType> m_vecTriangleIndices;
|
||||||
|
std::vector<VertexType> m_vecVertices;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename MeshType>
|
||||||
|
Mesh< Vertex< typename MeshType::VertexType::DataType >, typename MeshType::IndexType > decode(const MeshType& mesh)
|
||||||
|
{
|
||||||
|
Mesh< Vertex< typename MeshType::VertexType::DataType >, typename MeshType::IndexType > result;
|
||||||
|
result.m_vecVertices.resize(mesh.m_vecVertices.size());
|
||||||
|
|
||||||
|
for(MeshType::IndexType 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_offset = mesh.m_offset;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "PolyVoxCore/Mesh.inl"
|
||||||
|
|
||||||
|
#endif /* __Mesh_H__ */
|
139
library/PolyVoxCore/include/PolyVoxCore/Mesh.inl
Normal file
139
library/PolyVoxCore/include/PolyVoxCore/Mesh.inl
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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 <typename VertexType, typename IndexType>
|
||||||
|
Mesh<VertexType, IndexType>::Mesh()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexType, typename IndexType>
|
||||||
|
Mesh<VertexType, IndexType>::~Mesh()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexType, typename IndexType>
|
||||||
|
const std::vector<IndexType>& Mesh<VertexType, IndexType>::getIndices(void) const
|
||||||
|
{
|
||||||
|
return m_vecTriangleIndices;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexType, typename IndexType>
|
||||||
|
uint32_t Mesh<VertexType, IndexType>::getNoOfIndices(void) const
|
||||||
|
{
|
||||||
|
return m_vecTriangleIndices.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexType, typename IndexType>
|
||||||
|
IndexType Mesh<VertexType, IndexType>::getNoOfVertices(void) const
|
||||||
|
{
|
||||||
|
return m_vecVertices.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexType, typename IndexType>
|
||||||
|
const std::vector<VertexType>& Mesh<VertexType, IndexType>::getVertices(void) const
|
||||||
|
{
|
||||||
|
return m_vecVertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexType, typename IndexType>
|
||||||
|
const Vector3DInt32& Mesh<VertexType, IndexType>::getOffset(void) const
|
||||||
|
{
|
||||||
|
return m_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexType, typename IndexType>
|
||||||
|
void Mesh<VertexType, IndexType>::setOffset(const Vector3DInt32& offset)
|
||||||
|
{
|
||||||
|
m_offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexType, typename IndexType>
|
||||||
|
void Mesh<VertexType, IndexType>::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.");
|
||||||
|
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 <typename VertexType, typename IndexType>
|
||||||
|
IndexType Mesh<VertexType, IndexType>::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<IndexType>::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;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexType, typename IndexType>
|
||||||
|
void Mesh<VertexType, IndexType>::clear(void)
|
||||||
|
{
|
||||||
|
m_vecVertices.clear();
|
||||||
|
m_vecTriangleIndices.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexType, typename IndexType>
|
||||||
|
bool Mesh<VertexType, IndexType>::isEmpty(void) const
|
||||||
|
{
|
||||||
|
return (getNoOfVertices() == 0) || (getNoOfIndices() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexType, typename IndexType>
|
||||||
|
void Mesh<VertexType, IndexType>::removeUnusedVertices(void)
|
||||||
|
{
|
||||||
|
std::vector<bool> 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<uint32_t> newPos(m_vecVertices.size());
|
||||||
|
for(IndexType 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]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -76,12 +76,12 @@ namespace PolyVox
|
|||||||
// CubicSurfaceExtractor
|
// CubicSurfaceExtractor
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template<typename VoxelType> class DefaultIsQuadNeeded;
|
template<typename VoxelType> class DefaultIsQuadNeeded;
|
||||||
template<typename VolumeType, typename IsQuadNeeded = DefaultIsQuadNeeded<typename VolumeType::VoxelType> > class CubicSurfaceExtractor;
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded = DefaultIsQuadNeeded<typename VolumeType::VoxelType> > class CubicSurfaceExtractor;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// CubicVertex
|
// CubicVertex
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template<typename VoxelType> class CubicVertex;
|
template<typename VoxelType> struct CubicVertex;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Density
|
// Density
|
||||||
@ -108,10 +108,15 @@ namespace PolyVox
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType> class LargeVolume;
|
template <typename VoxelType> class LargeVolume;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// MarchingCubesSurfaceExtractor
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
template<typename VolumeType, typename Controller> class MarchingCubesSurfaceExtractor;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// MarchingCubesVertex
|
// MarchingCubesVertex
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template<typename VoxelType> class MarchingCubesVertex;
|
template<typename VoxelType> struct MarchingCubesVertex;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Material
|
// Material
|
||||||
@ -134,6 +139,11 @@ namespace PolyVox
|
|||||||
typedef MaterialDensityPair<uint8_t, 4, 4> MaterialDensityPair44;
|
typedef MaterialDensityPair<uint8_t, 4, 4> MaterialDensityPair44;
|
||||||
typedef MaterialDensityPair<uint16_t, 8, 8> MaterialDensityPair88;
|
typedef MaterialDensityPair<uint16_t, 8, 8> MaterialDensityPair88;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Mesh
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
template <typename VertexType, typename IndexType> class Mesh;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Pager
|
// Pager
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -154,16 +164,6 @@ namespace PolyVox
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType> class SimpleVolume;
|
template <typename VoxelType> class SimpleVolume;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// MarchingCubesSurfaceExtractor
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
template<typename VolumeType, typename Controller> class MarchingCubesSurfaceExtractor;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SurfaceMesh
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename VertexType> class SurfaceMesh;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Vector
|
// Vector
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1,104 +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_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 <algorithm>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <list>
|
|
||||||
#include <memory>
|
|
||||||
#include <set>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace PolyVox
|
|
||||||
{
|
|
||||||
class LodRecord
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int beginIndex;
|
|
||||||
int endIndex; //Let's put it just past the end STL style
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename VertexType>
|
|
||||||
class SurfaceMesh
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SurfaceMesh();
|
|
||||||
~SurfaceMesh();
|
|
||||||
|
|
||||||
const std::vector<uint32_t>& 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<VertexType>& getRawVertexData(void); //FIXME - this should be removed
|
|
||||||
const std::vector<VertexType>& 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<VertexType> > extractSubset(std::set<uint8_t> 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<uint32_t> m_vecTriangleIndices;
|
|
||||||
std::vector<VertexType> m_vecVertices;
|
|
||||||
|
|
||||||
std::vector<LodRecord> m_vecLodRecords;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename VertexType>
|
|
||||||
std::shared_ptr< SurfaceMesh<VertexType> > extractSubset(SurfaceMesh<VertexType>& inputMesh, std::set<uint8_t> setMaterials);
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "PolyVoxCore/SurfaceMesh.inl"
|
|
||||||
|
|
||||||
#endif /* __SurfaceMesh_H__ */
|
|
@ -1,488 +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.
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
namespace PolyVox
|
|
||||||
{
|
|
||||||
template <typename VertexType>
|
|
||||||
SurfaceMesh<VertexType>::SurfaceMesh()
|
|
||||||
{
|
|
||||||
m_iTimeStamp = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename VertexType>
|
|
||||||
SurfaceMesh<VertexType>::~SurfaceMesh()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename VertexType>
|
|
||||||
const std::vector<uint32_t>& SurfaceMesh<VertexType>::getIndices(void) const
|
|
||||||
{
|
|
||||||
return m_vecTriangleIndices;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename VertexType>
|
|
||||||
uint32_t SurfaceMesh<VertexType>::getNoOfIndices(void) const
|
|
||||||
{
|
|
||||||
return m_vecTriangleIndices.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename VertexType>
|
|
||||||
uint32_t SurfaceMesh<VertexType>::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 <typename VertexType>
|
|
||||||
uint32_t SurfaceMesh<VertexType>::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 <typename VertexType>
|
|
||||||
uint32_t SurfaceMesh<VertexType>::getNoOfVertices(void) const
|
|
||||||
{
|
|
||||||
return m_vecVertices.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename VertexType>
|
|
||||||
std::vector<VertexType>& SurfaceMesh<VertexType>::getRawVertexData(void)
|
|
||||||
{
|
|
||||||
return m_vecVertices;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename VertexType>
|
|
||||||
const std::vector<VertexType>& SurfaceMesh<VertexType>::getVertices(void) const
|
|
||||||
{
|
|
||||||
return m_vecVertices;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename VertexType>
|
|
||||||
void SurfaceMesh<VertexType>::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 <typename VertexType>
|
|
||||||
void SurfaceMesh<VertexType>::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 <typename VertexType>
|
|
||||||
uint32_t SurfaceMesh<VertexType>::addVertex(const VertexType& vertex)
|
|
||||||
{
|
|
||||||
m_vecVertices.push_back(vertex);
|
|
||||||
return m_vecVertices.size() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename VertexType>
|
|
||||||
void SurfaceMesh<VertexType>::clear(void)
|
|
||||||
{
|
|
||||||
m_vecVertices.clear();
|
|
||||||
m_vecTriangleIndices.clear();
|
|
||||||
m_vecLodRecords.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename VertexType>
|
|
||||||
bool SurfaceMesh<VertexType>::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 <typename VertexType>
|
|
||||||
void SurfaceMesh<VertexType>::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<Vector3DFloat> 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<uint32_t>::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 <typename VertexType>
|
|
||||||
void SurfaceMesh<VertexType>::generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices)
|
|
||||||
{
|
|
||||||
Vector3DFloat offset = static_cast<Vector3DFloat>(m_Region.getLowerCorner());
|
|
||||||
|
|
||||||
//Initially zero the normals
|
|
||||||
for(vector<PositionMaterialNormal>::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<uint32_t>::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<PositionMaterialNormal>::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++)
|
|
||||||
{
|
|
||||||
Vector3DFloat normal = iterVertex->getNormal();
|
|
||||||
normal.normalise();
|
|
||||||
iterVertex->setNormal(normal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*template <typename VertexType>
|
|
||||||
std::shared_ptr< SurfaceMesh<VertexType> > SurfaceMesh<VertexType>::extractSubset(std::set<uint8_t> setMaterials)
|
|
||||||
{
|
|
||||||
std::shared_ptr< SurfaceMesh<VertexType> > result(new SurfaceMesh<VertexType>);
|
|
||||||
|
|
||||||
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<int32_t> 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 <typename VertexType>
|
|
||||||
int SurfaceMesh<VertexType>::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 <typename VertexType>
|
|
||||||
void SurfaceMesh<VertexType>::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 <typename VertexType>
|
|
||||||
void SurfaceMesh<VertexType>::removeUnusedVertices(void)
|
|
||||||
{
|
|
||||||
std::vector<bool> 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<uint32_t> 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 <typename VertexType>
|
|
||||||
std::shared_ptr< SurfaceMesh<VertexType> > extractSubset(SurfaceMesh<VertexType>& inputMesh, std::set<uint8_t> setMaterials)
|
|
||||||
{
|
|
||||||
std::shared_ptr< SurfaceMesh<VertexType> > result(new SurfaceMesh<VertexType>);
|
|
||||||
|
|
||||||
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<int32_t> 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 <typename VertexType>
|
|
||||||
void SurfaceMesh<VertexType>::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 <typename VertexType>
|
|
||||||
void SurfaceMesh<VertexType>::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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -21,20 +21,31 @@ freely, subject to the following restrictions:
|
|||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __OpenGLExample_OpenGLSupport_H__
|
#ifndef __PolyVox_Vertex_H__
|
||||||
#define __OpenGLExample_OpenGLSupport_H__
|
#define __PolyVox_Vertex_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/PolyVoxForwardDeclarations.h"
|
#include "Impl/TypeDef.h"
|
||||||
|
|
||||||
#include "glew/glew.h"
|
#include "PolyVoxCore/Vector.h"
|
||||||
|
|
||||||
struct OpenGLColour
|
#include <bitset>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
GLfloat red;
|
#ifdef SWIG
|
||||||
GLfloat green;
|
struct Vertex
|
||||||
GLfloat blue;
|
#else
|
||||||
|
template<typename _DataType>
|
||||||
|
struct POLYVOX_API Vertex
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
typedef _DataType DataType;
|
||||||
|
|
||||||
|
Vector3DFloat position;
|
||||||
|
Vector3DFloat normal;
|
||||||
|
DataType data;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
OpenGLColour convertMaterialIDToColour(uint8_t materialID);
|
#endif // __PolyVox_Vertex_H__
|
||||||
|
|
||||||
#endif //__OpenGLExample_OpenGLSupport_H__
|
|
@ -1,159 +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_SurfaceVertex_H__
|
|
||||||
#define __PolyVox_SurfaceVertex_H__
|
|
||||||
|
|
||||||
#include "Impl/TypeDef.h"
|
|
||||||
|
|
||||||
#include "PolyVoxCore/Vector.h"
|
|
||||||
|
|
||||||
#include <bitset>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace PolyVox
|
|
||||||
{
|
|
||||||
#ifdef SWIG
|
|
||||||
class CubicVertex
|
|
||||||
#else
|
|
||||||
template<typename VoxelType>
|
|
||||||
class POLYVOX_API CubicVertex
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
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
|
|
||||||
#else
|
|
||||||
template<typename VoxelType>
|
|
||||||
class POLYVOX_API MarchingCubesVertex
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -36,8 +36,8 @@ ADD_DEFINITIONS(-DPOLYVOX_SHARED_EXPORTS) #Export symbols in the .dll
|
|||||||
|
|
||||||
#"Sources" and "Headers" are the group names in Visual Studio.
|
#"Sources" and "Headers" are the group names in Visual Studio.
|
||||||
#They may have other uses too...
|
#They may have other uses too...
|
||||||
SOURCE_GROUP("Sources" FILES ${UTIL_SRC_FILES})
|
SOURCE_GROUP("Source Files" FILES ${UTIL_SRC_FILES})
|
||||||
SOURCE_GROUP("Headers" FILES ${UTIL_INC_FILES})
|
SOURCE_GROUP("Header Files" FILES ${UTIL_INC_FILES})
|
||||||
|
|
||||||
#Tell CMake the paths
|
#Tell CMake the paths
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include)
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include)
|
||||||
|
@ -108,7 +108,7 @@ uint32_t testForType(void)
|
|||||||
{
|
{
|
||||||
Region regionToExtract(x, y, z, x + uRegionSideLength - 1, y + uRegionSideLength - 1, z + uRegionSideLength - 1);
|
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();
|
uTotalVertices += result.getNoOfVertices();
|
||||||
uTotalIndices += result.getNoOfIndices();
|
uTotalIndices += result.getNoOfIndices();
|
||||||
@ -130,7 +130,7 @@ void TestCubicSurfaceExtractor::testExecute()
|
|||||||
const static uint32_t uIndexToCheck = 2000;
|
const static uint32_t uIndexToCheck = 2000;
|
||||||
const static uint32_t uExpectedIndex = 1334;
|
const static uint32_t uExpectedIndex = 1334;
|
||||||
|
|
||||||
SurfaceMesh<CubicVertex> mesh;*/
|
Mesh<CubicVertex> mesh;*/
|
||||||
|
|
||||||
/*testForType<int8_t>(mesh);
|
/*testForType<int8_t>(mesh);
|
||||||
QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices);
|
QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices);
|
||||||
|
@ -102,7 +102,7 @@ void writeMaterialValueToVoxel(int valueToWrite, MaterialDensityPair88& voxel)
|
|||||||
|
|
||||||
// Runs the surface extractor for a given type.
|
// Runs the surface extractor for a given type.
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
SurfaceMesh<MarchingCubesVertex<VoxelType> > testForType(void) //I think we could avoid specifying this return type by using auto/decltype?
|
Mesh<MarchingCubesVertex<VoxelType> > testForType(void) //I think we could avoid specifying this return type by using auto/decltype?
|
||||||
{
|
{
|
||||||
const int32_t uVolumeSideLength = 32;
|
const int32_t uVolumeSideLength = 32;
|
||||||
|
|
||||||
@ -128,12 +128,12 @@ SurfaceMesh<MarchingCubesVertex<VoxelType> > testForType(void) //I think we coul
|
|||||||
DefaultMarchingCubesController<VoxelType> controller;
|
DefaultMarchingCubesController<VoxelType> controller;
|
||||||
controller.setThreshold(50);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void testCustomController(SurfaceMesh<MarchingCubesVertex<float> >& result)
|
void testCustomController(Mesh<MarchingCubesVertex<float> >& result)
|
||||||
{
|
{
|
||||||
const int32_t uVolumeSideLength = 32;
|
const int32_t uVolumeSideLength = 32;
|
||||||
|
|
||||||
@ -162,68 +162,68 @@ void TestSurfaceExtractor::testExecute()
|
|||||||
const static uint32_t uExpectedVertices = 4731;
|
const static uint32_t uExpectedVertices = 4731;
|
||||||
const static uint32_t uExpectedIndices = 12810;
|
const static uint32_t uExpectedIndices = 12810;
|
||||||
const static uint32_t uMaterialToCheck = 3000;
|
const static uint32_t uMaterialToCheck = 3000;
|
||||||
const static float fExpectedMaterial = 42.0f;
|
const static float fExpectedData = 42.0f;
|
||||||
const static float fNoMaterial = 1.0f;
|
const static float fNoMaterial = 1.0f;
|
||||||
|
|
||||||
SurfaceMesh<MarchingCubesVertex<int8_t> > mesh;
|
Mesh<MarchingCubesVertex<int8_t> > mesh;
|
||||||
//Run the test for various voxel types.
|
//Run the test for various voxel types.
|
||||||
QBENCHMARK {
|
QBENCHMARK {
|
||||||
mesh = testForType<int8_t>();
|
mesh = testForType<int8_t>();
|
||||||
}
|
}
|
||||||
QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices);
|
QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices);
|
||||||
QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices);
|
QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices);
|
||||||
QCOMPARE(mesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast<int8_t>(fNoMaterial));
|
QCOMPARE(mesh.getVertices()[uMaterialToCheck].data, static_cast<int8_t>(fExpectedData));
|
||||||
|
|
||||||
auto mesh1 = testForType<uint8_t>();
|
auto mesh1 = testForType<uint8_t>();
|
||||||
QCOMPARE(mesh1.getNoOfVertices(), uExpectedVertices);
|
QCOMPARE(mesh1.getNoOfVertices(), uExpectedVertices);
|
||||||
QCOMPARE(mesh1.getNoOfIndices(), uExpectedIndices);
|
QCOMPARE(mesh1.getNoOfIndices(), uExpectedIndices);
|
||||||
QCOMPARE(mesh1.getVertices()[uMaterialToCheck].getMaterial(), static_cast<uint8_t>(fNoMaterial));
|
QCOMPARE(mesh1.getVertices()[uMaterialToCheck].data, static_cast<uint8_t>(fExpectedData));
|
||||||
|
|
||||||
auto mesh2 = testForType<int16_t>();
|
auto mesh2 = testForType<int16_t>();
|
||||||
QCOMPARE(mesh2.getNoOfVertices(), uExpectedVertices);
|
QCOMPARE(mesh2.getNoOfVertices(), uExpectedVertices);
|
||||||
QCOMPARE(mesh2.getNoOfIndices(), uExpectedIndices);
|
QCOMPARE(mesh2.getNoOfIndices(), uExpectedIndices);
|
||||||
QCOMPARE(mesh2.getVertices()[uMaterialToCheck].getMaterial(), static_cast<int16_t>(fNoMaterial));
|
QCOMPARE(mesh2.getVertices()[uMaterialToCheck].data, static_cast<int16_t>(fExpectedData));
|
||||||
|
|
||||||
auto mesh3 = testForType<uint16_t>();
|
auto mesh3 = testForType<uint16_t>();
|
||||||
QCOMPARE(mesh3.getNoOfVertices(), uExpectedVertices);
|
QCOMPARE(mesh3.getNoOfVertices(), uExpectedVertices);
|
||||||
QCOMPARE(mesh3.getNoOfIndices(), uExpectedIndices);
|
QCOMPARE(mesh3.getNoOfIndices(), uExpectedIndices);
|
||||||
QCOMPARE(mesh3.getVertices()[uMaterialToCheck].getMaterial(), static_cast<uint16_t>(fNoMaterial));
|
QCOMPARE(mesh3.getVertices()[uMaterialToCheck].data, static_cast<uint16_t>(fExpectedData));
|
||||||
|
|
||||||
auto mesh4 = testForType<int32_t>();
|
auto mesh4 = testForType<int32_t>();
|
||||||
QCOMPARE(mesh4.getNoOfVertices(), uExpectedVertices);
|
QCOMPARE(mesh4.getNoOfVertices(), uExpectedVertices);
|
||||||
QCOMPARE(mesh4.getNoOfIndices(), uExpectedIndices);
|
QCOMPARE(mesh4.getNoOfIndices(), uExpectedIndices);
|
||||||
QCOMPARE(mesh4.getVertices()[uMaterialToCheck].getMaterial(), static_cast<int32_t>(fNoMaterial));
|
QCOMPARE(mesh4.getVertices()[uMaterialToCheck].data, static_cast<int32_t>(fExpectedData));
|
||||||
|
|
||||||
auto mesh5 = testForType<uint32_t>();
|
auto mesh5 = testForType<uint32_t>();
|
||||||
QCOMPARE(mesh5.getNoOfVertices(), uExpectedVertices);
|
QCOMPARE(mesh5.getNoOfVertices(), uExpectedVertices);
|
||||||
QCOMPARE(mesh5.getNoOfIndices(), uExpectedIndices);
|
QCOMPARE(mesh5.getNoOfIndices(), uExpectedIndices);
|
||||||
QCOMPARE(mesh5.getVertices()[uMaterialToCheck].getMaterial(), static_cast<uint32_t>(fNoMaterial));
|
QCOMPARE(mesh5.getVertices()[uMaterialToCheck].data, static_cast<uint32_t>(fExpectedData));
|
||||||
|
|
||||||
auto mesh6 = testForType<float>();
|
auto mesh6 = testForType<float>();
|
||||||
QCOMPARE(mesh6.getNoOfVertices(), uExpectedVertices);
|
QCOMPARE(mesh6.getNoOfVertices(), uExpectedVertices);
|
||||||
QCOMPARE(mesh6.getNoOfIndices(), uExpectedIndices);
|
QCOMPARE(mesh6.getNoOfIndices(), uExpectedIndices);
|
||||||
QCOMPARE(mesh6.getVertices()[uMaterialToCheck].getMaterial(), static_cast<float>(fNoMaterial));
|
QCOMPARE(mesh6.getVertices()[uMaterialToCheck].data, static_cast<float>(fExpectedData));
|
||||||
|
|
||||||
auto mesh7 = testForType<double>();
|
auto mesh7 = testForType<double>();
|
||||||
QCOMPARE(mesh7.getNoOfVertices(), uExpectedVertices);
|
QCOMPARE(mesh7.getNoOfVertices(), uExpectedVertices);
|
||||||
QCOMPARE(mesh7.getNoOfIndices(), uExpectedIndices);
|
QCOMPARE(mesh7.getNoOfIndices(), uExpectedIndices);
|
||||||
QCOMPARE(mesh7.getVertices()[uMaterialToCheck].getMaterial(), static_cast<double>(fNoMaterial));
|
QCOMPARE(mesh7.getVertices()[uMaterialToCheck].data, static_cast<double>(fExpectedData));
|
||||||
|
|
||||||
auto mesh8 = testForType<Density8>();
|
auto mesh8 = testForType<Density8>();
|
||||||
QCOMPARE(mesh8.getNoOfVertices(), uExpectedVertices);
|
QCOMPARE(mesh8.getNoOfVertices(), uExpectedVertices);
|
||||||
QCOMPARE(mesh8.getNoOfIndices(), uExpectedIndices);
|
QCOMPARE(mesh8.getNoOfIndices(), uExpectedIndices);
|
||||||
QCOMPARE(mesh8.getVertices()[uMaterialToCheck].getMaterial(), static_cast<Density8>(fNoMaterial));
|
QCOMPARE(mesh8.getVertices()[uMaterialToCheck].data, static_cast<Density8>(fExpectedData));
|
||||||
|
|
||||||
auto mesh9 = testForType<MaterialDensityPair88>();
|
auto mesh9 = testForType<MaterialDensityPair88>();
|
||||||
QCOMPARE(mesh9.getNoOfVertices(), uExpectedVertices);
|
QCOMPARE(mesh9.getNoOfVertices(), uExpectedVertices);
|
||||||
QCOMPARE(mesh9.getNoOfIndices(), uExpectedIndices);
|
QCOMPARE(mesh9.getNoOfIndices(), uExpectedIndices);
|
||||||
//QCOMPARE(mesh9.getVertices()[uMaterialToCheck].getMaterial(), fExpectedMaterial);
|
//QCOMPARE(mesh9.getVertices()[uMaterialToCheck].data, fExpectedMaterial);
|
||||||
|
|
||||||
//Test whether the CustomSurfaceExtractor works.
|
//Test whether the CustomSurfaceExtractor works.
|
||||||
/*testCustomController(floatMesh);
|
/*testCustomController(floatMesh);
|
||||||
QCOMPARE(floatMesh.getNoOfVertices(), uExpectedVertices);
|
QCOMPARE(floatMesh.getNoOfVertices(), uExpectedVertices);
|
||||||
QCOMPARE(floatMesh.getNoOfIndices(), uExpectedIndices);
|
QCOMPARE(floatMesh.getNoOfIndices(), uExpectedIndices);
|
||||||
QCOMPARE(floatMesh.getVertices()[uMaterialToCheck].getMaterial(), fNoMaterial);*/
|
QCOMPARE(floatMesh.getVertices()[uMaterialToCheck].data, fExpectedData);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(TestSurfaceExtractor)
|
QTEST_MAIN(TestSurfaceExtractor)
|
||||||
|
@ -184,7 +184,7 @@ void TestVolumeSubclass::testExtractSurface()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = extractCubicSurface(&volumeSubclass, volumeSubclass.getEnclosingRegion());
|
auto result = extractCubicMesh(&volumeSubclass, volumeSubclass.getEnclosingRegion());
|
||||||
|
|
||||||
QCOMPARE(result.getNoOfVertices(), static_cast<uint32_t>(8));
|
QCOMPARE(result.getNoOfVertices(), static_cast<uint32_t>(8));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user