Merge branch 'develop' into feature/opengl
Conflicts: examples/Basic/CMakeLists.txt examples/Basic/OpenGLWidget.cpp examples/Basic/OpenGLWidget.h include/PolyVox/Impl/Timer.h
This commit is contained in:
commit
d9da93b6c0
20
.gitattributes
vendored
Normal file
20
.gitattributes
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Based on GitHub sample: https://help.github.com/articles/dealing-with-line-endings
|
||||||
|
|
||||||
|
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
# Explicitly declare text files you want to always be normalized and converted
|
||||||
|
# to native line endings on checkout.
|
||||||
|
*.c text
|
||||||
|
*.cpp text
|
||||||
|
*.h text
|
||||||
|
*.inl text
|
||||||
|
*.txt text
|
||||||
|
*.i text
|
||||||
|
|
||||||
|
# Declare files that will always have CRLF line endings on checkout.
|
||||||
|
#*.sln text eol=crlf
|
||||||
|
|
||||||
|
# Denote all files that are truly binary and should not be modified.
|
||||||
|
#*.png binary
|
||||||
|
#*.jpg binary
|
@ -2,6 +2,21 @@ Changes for PolyVox version 0.3
|
|||||||
===============================
|
===============================
|
||||||
This release has focused on... (some introduction here).
|
This release has focused on... (some introduction here).
|
||||||
|
|
||||||
|
*** Quick braindump of some changes ***
|
||||||
|
|
||||||
|
* SimpleVolume is now PagedVolume (slightly slower but can go larger).
|
||||||
|
* MarchingCubesSurfaceExtractor class is now a free function extractMarchingCubesSurface()
|
||||||
|
* Meshes are more templatized (e.g. on IndexType) and extracted meshes are encoded to save space. A 'decode' function is provided for these (or you can do it on the GPU).
|
||||||
|
* Generally more templatization - you will want to use a lot of the 'auto' keyword to stay sane.
|
||||||
|
* MarchingCubesController class gives more control over extraction process, but defaults should be fine for primative voxel types.
|
||||||
|
* Requires VS2013 on Windows (GCC 4.7/Clang should be ok).
|
||||||
|
* Support for 'WrapModes' when accessing outside volumes but I think these have bought a performance impact.
|
||||||
|
* Documentation is as poor (or wrong) as ever but all tests and examples work.
|
||||||
|
* New Array class is much faster
|
||||||
|
|
||||||
|
*** End of braindump ***
|
||||||
|
|
||||||
|
|
||||||
This line was added just for testing.
|
This line was added just for testing.
|
||||||
|
|
||||||
Voxel access
|
Voxel access
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Copyright (c) 2007-2012 Matt Williams
|
# Copyright (c) 2007-2014 Matt Williams
|
||||||
# Copyright (c) 2007-2012 David Williams
|
# Copyright (c) 2007-2014 David Williams
|
||||||
#
|
#
|
||||||
# This software is provided 'as-is', without any express or implied
|
# This software is provided 'as-is', without any express or implied
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
# warranty. In no event will the authors be held liable for any damages
|
||||||
@ -24,68 +24,63 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.6)
|
|||||||
|
|
||||||
PROJECT(PolyVox)
|
PROJECT(PolyVox)
|
||||||
|
|
||||||
|
include(FeatureSummary)
|
||||||
|
|
||||||
|
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
|
||||||
|
#Set up for building the library itself
|
||||||
|
|
||||||
SET(POLYVOX_VERSION_MAJOR "0")
|
SET(POLYVOX_VERSION_MAJOR "0")
|
||||||
SET(POLYVOX_VERSION_MINOR "2")
|
SET(POLYVOX_VERSION_MINOR "2")
|
||||||
SET(POLYVOX_VERSION_PATCH "1")
|
SET(POLYVOX_VERSION_PATCH "1")
|
||||||
SET(POLYVOX_VERSION "${POLYVOX_VERSION_MAJOR}.${POLYVOX_VERSION_MINOR}.${POLYVOX_VERSION_PATCH}" CACHE STRING "PolyVox version")
|
SET(POLYVOX_VERSION "${POLYVOX_VERSION_MAJOR}.${POLYVOX_VERSION_MINOR}.${POLYVOX_VERSION_PATCH}" CACHE STRING "PolyVox version")
|
||||||
MARK_AS_ADVANCED(FORCE POLYVOX_VERSION)
|
MARK_AS_ADVANCED(FORCE POLYVOX_VERSION)
|
||||||
|
|
||||||
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
|
|
||||||
include(FeatureSummary)
|
|
||||||
|
|
||||||
FIND_PACKAGE(Doxygen)
|
|
||||||
OPTION(ENABLE_EXAMPLES "Should the examples be built" ON)
|
|
||||||
|
|
||||||
SET(LIBRARY_TYPE "DYNAMIC" CACHE STRING "Should the library be STATIC or DYNAMIC")
|
SET(LIBRARY_TYPE "DYNAMIC" CACHE STRING "Should the library be STATIC or DYNAMIC")
|
||||||
SET_PROPERTY(CACHE LIBRARY_TYPE PROPERTY STRINGS DYNAMIC STATIC)
|
SET_PROPERTY(CACHE LIBRARY_TYPE PROPERTY STRINGS DYNAMIC STATIC)
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
SET(LIBRARY_TYPE "STATIC")
|
SET(LIBRARY_TYPE "STATIC")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
# Qt is required for building the tests, the example and optionally for bundling the documentation
|
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||||
find_package(Qt5Test 5.2 REQUIRED)
|
|
||||||
find_package(Qt5OpenGL 5.2 REQUIRED)
|
|
||||||
|
|
||||||
set_package_properties(Doxygen PROPERTIES URL http://www.doxygen.org DESCRIPTION "API documentation generator" TYPE OPTIONAL PURPOSE "Building the API documentation")
|
|
||||||
set_package_properties(Qt5Test PROPERTIES DESCRIPTION "C++ framework" URL http://qt-project.org)
|
|
||||||
set_package_properties(Qt5Test PROPERTIES TYPE OPTIONAL PURPOSE "Building the tests")
|
|
||||||
set_package_properties(Qt5OpenGL PROPERTIES DESCRIPTION "C++ framework" URL http://qt-project.org)
|
|
||||||
set_package_properties(Qt5OpenGL PROPERTIES TYPE RECOMMENDED PURPOSE "Building the examples")
|
|
||||||
|
|
||||||
IF(CMAKE_COMPILER_IS_GNUCXX) #Maybe "OR MINGW"
|
|
||||||
ADD_DEFINITIONS(-std=c++0x) #Enable C++0x mode
|
|
||||||
ENDIF()
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
|
||||||
ADD_DEFINITIONS(-std=c++0x) #Enable C++0x mode
|
ADD_DEFINITIONS(-std=c++0x) #Enable C++0x mode
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
ADD_SUBDIRECTORY(library)
|
#We need to find doxygen before building the library
|
||||||
|
FIND_PACKAGE(Doxygen)
|
||||||
|
|
||||||
|
|
||||||
|
ADD_SUBDIRECTORY(include)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Qt is required for building the tests, the example and optionally for bundling the documentation
|
||||||
|
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui QtOpenGL QtTest)
|
||||||
|
INCLUDE(${QT_USE_FILE})
|
||||||
|
|
||||||
|
#Examples
|
||||||
OPTION(ENABLE_EXAMPLES "Should the examples be built" ON)
|
OPTION(ENABLE_EXAMPLES "Should the examples be built" ON)
|
||||||
IF(ENABLE_EXAMPLES AND Qt5OpenGL_FOUND)
|
IF(ENABLE_EXAMPLES AND QT_QTOPENGL_FOUND)
|
||||||
ADD_SUBDIRECTORY(examples/common)
|
|
||||||
ADD_SUBDIRECTORY(examples/Basic)
|
|
||||||
ADD_SUBDIRECTORY(examples/Paging)
|
|
||||||
ADD_SUBDIRECTORY(examples/OpenGL)
|
|
||||||
ADD_SUBDIRECTORY(examples/SmoothLOD)
|
|
||||||
ADD_SUBDIRECTORY(examples/Python)
|
|
||||||
SET(BUILD_EXAMPLES ON)
|
SET(BUILD_EXAMPLES ON)
|
||||||
|
add_subdirectory(examples)
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(BUILD_EXAMPLES OFF)
|
SET(BUILD_EXAMPLES OFF)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
INCLUDE(Packaging.cmake)
|
INCLUDE(Packaging.cmake)
|
||||||
|
|
||||||
|
#Tests
|
||||||
OPTION(ENABLE_TESTS "Should the tests be built" ON)
|
OPTION(ENABLE_TESTS "Should the tests be built" ON)
|
||||||
IF(ENABLE_TESTS AND Qt5Test_FOUND)
|
IF(ENABLE_TESTS AND QT_QTTEST_FOUND)
|
||||||
|
SET(BUILD_TESTS ON)
|
||||||
INCLUDE(CTest)
|
INCLUDE(CTest)
|
||||||
MARK_AS_ADVANCED(FORCE BUILD_TESTING)
|
MARK_AS_ADVANCED(FORCE BUILD_TESTING)
|
||||||
ADD_SUBDIRECTORY(tests)
|
ADD_SUBDIRECTORY(tests)
|
||||||
SET(BUILD_TESTS ON)
|
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(BUILD_TESTS OFF)
|
SET(BUILD_TESTS OFF)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
#Manual
|
||||||
#Check if we will building _and_ bundling the docs
|
#Check if we will building _and_ bundling the docs
|
||||||
IF(DOXYGEN_FOUND AND QT_QCOLLECTIONGENERATOR_EXECUTABLE)
|
IF(DOXYGEN_FOUND AND QT_QCOLLECTIONGENERATOR_EXECUTABLE)
|
||||||
SET(BUILD_AND_BUNDLE_DOCS ON)
|
SET(BUILD_AND_BUNDLE_DOCS ON)
|
||||||
@ -95,6 +90,13 @@ ENDIF()
|
|||||||
|
|
||||||
ADD_SUBDIRECTORY(documentation)
|
ADD_SUBDIRECTORY(documentation)
|
||||||
|
|
||||||
|
ADD_SUBDIRECTORY(bindings)
|
||||||
|
|
||||||
|
set_package_properties(Doxygen PROPERTIES URL http://www.doxygen.org DESCRIPTION "API documentation generator" TYPE OPTIONAL PURPOSE "Building the API documentation")
|
||||||
|
set_package_properties(Qt4 PROPERTIES DESCRIPTION "C++ framework" URL http://qt-project.org)
|
||||||
|
set_package_properties(Qt4 PROPERTIES TYPE RECOMMENDED PURPOSE "Building the examples")
|
||||||
|
set_package_properties(Qt4 PROPERTIES TYPE OPTIONAL PURPOSE "Building the tests")
|
||||||
|
|
||||||
add_feature_info("Examples" BUILD_EXAMPLES "Examples of PolyVox usage")
|
add_feature_info("Examples" BUILD_EXAMPLES "Examples of PolyVox usage")
|
||||||
add_feature_info("Tests" BUILD_TESTS "Unit tests")
|
add_feature_info("Tests" BUILD_TESTS "Unit tests")
|
||||||
add_feature_info("Bindings" BUILD_BINDINGS "SWIG bindings")
|
add_feature_info("Bindings" BUILD_BINDINGS "SWIG bindings")
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
option(ENABLE_BINDINGS "Build bindings" ON)
|
option(ENABLE_BINDINGS "Build bindings" OFF) #Off by default
|
||||||
if(ENABLE_BINDINGS)
|
if(ENABLE_BINDINGS)
|
||||||
find_package(SWIG)
|
find_package(SWIG)
|
||||||
mark_as_advanced(SWIG_DIR SWIG_VERSION)
|
mark_as_advanced(SWIG_DIR SWIG_VERSION)
|
||||||
@ -38,9 +38,9 @@ if(ENABLE_BINDINGS)
|
|||||||
set(CMAKE_SWIG_FLAGS "")
|
set(CMAKE_SWIG_FLAGS "")
|
||||||
set_source_files_properties(PolyVoxCore.i PROPERTIES CPLUSPLUS ON)
|
set_source_files_properties(PolyVoxCore.i PROPERTIES CPLUSPLUS ON)
|
||||||
|
|
||||||
|
include_directories(${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include/PolyVoxCore)
|
||||||
if(PYTHONLIBS_FOUND)
|
if(PYTHONLIBS_FOUND)
|
||||||
include_directories(${PYTHON_INCLUDE_PATH})
|
include_directories(${PYTHON_INCLUDE_PATH})
|
||||||
include_directories(${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include/PolyVoxCore)
|
|
||||||
link_directories(${PolyVoxCore_BINARY_DIR})
|
link_directories(${PolyVoxCore_BINARY_DIR})
|
||||||
|
|
||||||
#set_source_files_properties(PolyVoxCore.i PROPERTIES SWIG_FLAGS "-builtin")
|
#set_source_files_properties(PolyVoxCore.i PROPERTIES SWIG_FLAGS "-builtin")
|
9
bindings/Chunk.i
Normal file
9
bindings/Chunk.i
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
%module Chunk
|
||||||
|
%{
|
||||||
|
#include "Chunk.h"
|
||||||
|
%}
|
||||||
|
|
||||||
|
%include "Chunk.h"
|
||||||
|
|
||||||
|
VOLUMETYPES(Chunk)
|
||||||
|
|
9
bindings/CubicSurfaceExtractor.i
Normal file
9
bindings/CubicSurfaceExtractor.i
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
%module CubicSurfaceExtractor
|
||||||
|
%{
|
||||||
|
#include "CubicSurfaceExtractor.h"
|
||||||
|
%}
|
||||||
|
|
||||||
|
%include "CubicSurfaceExtractor.h"
|
||||||
|
|
||||||
|
%template(extractCubicMeshSimpleVolumeuint8) extractCubicMesh<PolyVox::PagedVolume<uint8_t> >;
|
||||||
|
//EXTRACTORS(CubicSurfaceExtractor)
|
50
bindings/PagedVolume.i
Normal file
50
bindings/PagedVolume.i
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
%module PagedVolume
|
||||||
|
|
||||||
|
#pragma SWIG nowarn=SWIGWARN_PARSE_NESTED_CLASS
|
||||||
|
|
||||||
|
namespace PolyVox
|
||||||
|
{
|
||||||
|
class PolyVox::PagedVolume_Chunk {
|
||||||
|
public:
|
||||||
|
PagedVolume_Chunk(Vector3DInt32 v3dPosition, uint16_t uSideLength, PolyVox::PagedVolume_Pager* pPager = nullptr);
|
||||||
|
~PagedVolume_Chunk();
|
||||||
|
|
||||||
|
VoxelType* getData(void) const;
|
||||||
|
uint32_t getDataSizeInBytes(void) const;
|
||||||
|
|
||||||
|
VoxelType getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const;
|
||||||
|
VoxelType getVoxel(const Vector3DUint16& v3dPos) const;
|
||||||
|
|
||||||
|
void setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue);
|
||||||
|
void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
class PolyVox::PagedVolume_Pager {
|
||||||
|
public:
|
||||||
|
/// Constructor
|
||||||
|
PagedVolume_Pager() {};
|
||||||
|
/// Destructor
|
||||||
|
virtual ~PagedVolume_Pager() {};
|
||||||
|
|
||||||
|
virtual void pageIn(const Region& region, PagedVolume_Chunk* pChunk) = 0;
|
||||||
|
virtual void pageOut(const Region& region, PagedVolume_Chunk* pChunk) = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
%{
|
||||||
|
#include "PagedVolume.h"
|
||||||
|
%}
|
||||||
|
|
||||||
|
%include "PagedVolume.h"
|
||||||
|
|
||||||
|
%{
|
||||||
|
namespace PolyVox
|
||||||
|
{
|
||||||
|
// SWIG thinks that Inner is a global class, so we need to trick the C++
|
||||||
|
// compiler into understanding this so called global type.
|
||||||
|
typedef PagedVolume<int8_t>::Pager PagedVolume_Pager;
|
||||||
|
typedef PagedVolume<int8_t>::Chunk PagedVolume_Chunk;
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
VOLUMETYPES(PagedVolume)
|
@ -28,30 +28,29 @@ const char* __str__() {
|
|||||||
//This macro will be called in the volume interface files to define the various volume types.
|
//This macro will be called in the volume interface files to define the various volume types.
|
||||||
%define VOLUMETYPES(class)
|
%define VOLUMETYPES(class)
|
||||||
%template(class ## int8) PolyVox::class<int8_t>;
|
%template(class ## int8) PolyVox::class<int8_t>;
|
||||||
%template(class ## int16) PolyVox::class<int16_t>;
|
//%template(class ## int16) PolyVox::class<int16_t>;
|
||||||
%template(class ## int32) PolyVox::class<int32_t>;
|
//%template(class ## int32) PolyVox::class<int32_t>;
|
||||||
%template(class ## uint8) PolyVox::class<uint8_t>;
|
//%template(class ## uint8) PolyVox::class<uint8_t>;
|
||||||
%template(class ## uint16) PolyVox::class<uint16_t>;
|
//%template(class ## uint16) PolyVox::class<uint16_t>;
|
||||||
%template(class ## uint32) PolyVox::class<uint32_t>;
|
//%template(class ## uint32) PolyVox::class<uint32_t>;
|
||||||
%template(class ## float) PolyVox::class<float>;
|
//%template(class ## float) PolyVox::class<float>;
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
//Template based on voxel type
|
//Template based on voxel type
|
||||||
%define EXTRACTOR(class, volumetype)
|
%define EXTRACTOR(class, volumetype)
|
||||||
%template(class ## volumetype ## int8) PolyVox::class<PolyVox::volumetype<int8_t> >;
|
%template(class ## volumetype ## int8) PolyVox::class<PolyVox::volumetype<int8_t> >;
|
||||||
%template(class ## volumetype ## int16) PolyVox::class<PolyVox::volumetype<int16_t> >;
|
//%template(class ## volumetype ## int16) PolyVox::class<PolyVox::volumetype<int16_t> >;
|
||||||
%template(class ## volumetype ## int32) PolyVox::class<PolyVox::volumetype<int32_t> >;
|
//%template(class ## volumetype ## int32) PolyVox::class<PolyVox::volumetype<int32_t> >;
|
||||||
%template(class ## volumetype ## uint8) PolyVox::class<PolyVox::volumetype<uint8_t> >;
|
//%template(class ## volumetype ## uint8) PolyVox::class<PolyVox::volumetype<uint8_t> >;
|
||||||
%template(class ## volumetype ## uint16) PolyVox::class<PolyVox::volumetype<uint16_t> >;
|
//%template(class ## volumetype ## uint16) PolyVox::class<PolyVox::volumetype<uint16_t> >;
|
||||||
%template(class ## volumetype ## uint32) PolyVox::class<PolyVox::volumetype<uint32_t> >;
|
//%template(class ## volumetype ## uint32) PolyVox::class<PolyVox::volumetype<uint32_t> >;
|
||||||
%template(class ## volumetype ## float) PolyVox::class<PolyVox::volumetype<float> >;
|
//%template(class ## volumetype ## float) PolyVox::class<PolyVox::volumetype<float> >;
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
//Template based on volume type
|
//Template based on volume type
|
||||||
%define EXTRACTORS(shortname)
|
%define EXTRACTORS(shortname)
|
||||||
EXTRACTOR(shortname, SimpleVolume)
|
EXTRACTOR(shortname, PagedVolume)
|
||||||
EXTRACTOR(shortname, RawVolume)
|
EXTRACTOR(shortname, RawVolume)
|
||||||
EXTRACTOR(shortname, LargeVolume)
|
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
%feature("autodoc", "1");
|
%feature("autodoc", "1");
|
||||||
@ -75,24 +74,20 @@ EXTRACTOR(shortname, LargeVolume)
|
|||||||
%include "Vector.i"
|
%include "Vector.i"
|
||||||
%include "DefaultMarchingCubesController.i"
|
%include "DefaultMarchingCubesController.i"
|
||||||
%include "Region.i"
|
%include "Region.i"
|
||||||
%include "Block.i"
|
//%include "Chunk.i"
|
||||||
%include "CompressedBlock.i"
|
//%include "CompressedBlock.i"
|
||||||
%include "UncompressedBlock.i"
|
//%include "UncompressedBlock.i"
|
||||||
%include "BlockCompressor.i"
|
//%include "BlockCompressor.i"
|
||||||
%include "Pager.i"
|
//%include "Pager.i"
|
||||||
%include "FilePager.i"
|
//%include "FilePager.i"
|
||||||
%include "MinizBlockCompressor.i"
|
//%include "MinizBlockCompressor.i"
|
||||||
%include "RLEBlockCompressor.i"
|
//%include "RLEBlockCompressor.i"
|
||||||
%include "BaseVolume.i"
|
%include "BaseVolume.i"
|
||||||
%include "SimpleVolume.i"
|
//%include "RawVolume.i"
|
||||||
%include "RawVolume.i"
|
%include "PagedVolume.i"
|
||||||
%include "LargeVolume.i"
|
//%include "VertexTypes.i"
|
||||||
//%include "SubArray.i"
|
//%include "SurfaceMesh.i"
|
||||||
//%include "Array.i"
|
////%include "MarchingCubesSurfaceExtractor.i"
|
||||||
%include "VertexTypes.i"
|
////%include "CubicSurfaceExtractor.i"
|
||||||
%include "SurfaceMesh.i"
|
//%include "Raycast.i"
|
||||||
%include "MarchingCubesSurfaceExtractor.i"
|
//%include "Picking.i"
|
||||||
%include "CubicSurfaceExtractor.i"
|
|
||||||
%include "CubicSurfaceExtractorWithNormals.i"
|
|
||||||
%include "Raycast.i"
|
|
||||||
%include "Picking.i"
|
|
20
bindings/SurfaceMesh.i
Normal file
20
bindings/SurfaceMesh.i
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
%module SurfaceMesh
|
||||||
|
%{
|
||||||
|
#include "Region.h"
|
||||||
|
#include "Vertex.h"
|
||||||
|
#include "Mesh.h"
|
||||||
|
%}
|
||||||
|
|
||||||
|
%include "Region.h"
|
||||||
|
%include "Vertex.h"
|
||||||
|
%include "Mesh.h"
|
||||||
|
|
||||||
|
//%template(VertexTypeVector) std::vector<PolyVox::VertexType>;
|
||||||
|
//%template(PositionMaterialVector) std::vector<PolyVox::PositionMaterial>;
|
||||||
|
//%template(PositionMaterialNormalVector) std::vector<PolyVox::PositionMaterialNormal>;
|
||||||
|
//%template(LodRecordVector) std::vector<PolyVox::LodRecord>;
|
||||||
|
//%template(uint8Vector) std::vector<uint8_t>;
|
||||||
|
//%template(uint32Vector) std::vector<uint32_t>;
|
||||||
|
|
||||||
|
%template(MeshPositionMaterial) PolyVox::Mesh<PolyVox::CubicVertex<uint8_t>, uint16_t >;
|
||||||
|
%template(MeshPositionMaterialNormal) PolyVox::Mesh<PolyVox::MarchingCubesVertex<uint8_t>, uint16_t >;
|
@ -2,12 +2,12 @@
|
|||||||
%{
|
%{
|
||||||
#include "Impl/TypeDef.h"
|
#include "Impl/TypeDef.h"
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
#include "VertexTypes.h"
|
#include "Vertex.h"
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%include "Impl/TypeDef.h"
|
%include "Impl/TypeDef.h"
|
||||||
%include "Vector.h"
|
%include "Vector.h"
|
||||||
%include "VertexTypes.h"
|
%include "Vertex.h"
|
||||||
|
|
||||||
//%template (PositionMaterial) PolyVox::PositionMaterial;
|
//%template (PositionMaterial) PolyVox::PositionMaterial;
|
||||||
//%template (PositionMaterialNormal) PolyVox::PositionMaterialNormal;
|
//%template (PositionMaterialNormal) PolyVox::PositionMaterialNormal;
|
@ -27,8 +27,10 @@ C++ does provide the 'volatile' keyword which can be used to ensure a variable i
|
|||||||
|
|
||||||
Lastly, note that PolyVox volumes are templatised which means the voxel type might be something other than a simple int. However we don't think this actually makes a difference given that so few guarantees are made anyway, and it should still be safe to perform multiple concurrent reads for more complex types.
|
Lastly, note that PolyVox volumes are templatised which means the voxel type might be something other than a simple int. However we don't think this actually makes a difference given that so few guarantees are made anyway, and it should still be safe to perform multiple concurrent reads for more complex types.
|
||||||
|
|
||||||
LargeVolume
|
PagedVolume
|
||||||
-----------
|
-----------
|
||||||
|
NOTE: The info below is based on LargeVolume, which PagedVolume has replaced. It is likely that the same limitations apply but this has not been well tested. We do intend to improve the thread safty of PagedVolume in the future.
|
||||||
|
|
||||||
The LargeVolume provides even less thread safety than the RawVolume, in that even concurrent read operations can cause problems. The reason for this is the more complex memory management which is performed behind the scenes, and which allows pieces of volume data to be moved around and deleted. For example, a read of a single voxel may mean that the block of data associated with that voxel has to be paged in to memory, which in turn may mean that another block of data has to be paged out of memory. If second thread was halfway through reading a voxel in this second block of data then a problem will occur.
|
The LargeVolume provides even less thread safety than the RawVolume, in that even concurrent read operations can cause problems. The reason for this is the more complex memory management which is performed behind the scenes, and which allows pieces of volume data to be moved around and deleted. For example, a read of a single voxel may mean that the block of data associated with that voxel has to be paged in to memory, which in turn may mean that another block of data has to be paged out of memory. If second thread was halfway through reading a voxel in this second block of data then a problem will occur.
|
||||||
|
|
||||||
In the future we may do a more comprehensive analysis of thread safety in the LargeVolume, but for now you should assume that any multithreaded access can cause problems.
|
In the future we may do a more comprehensive analysis of thread safety in the LargeVolume, but for now you should assume that any multithreaded access can cause problems.
|
||||||
|
@ -38,7 +38,7 @@ SOURCE_GROUP("Sources" FILES ${SRC_FILES})
|
|||||||
SOURCE_GROUP("Headers" FILES ${INC_FILES})
|
SOURCE_GROUP("Headers" FILES ${INC_FILES})
|
||||||
|
|
||||||
#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(${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include)
|
INCLUDE_DIRECTORIES(${PolyVoxHeaders_SOURCE_DIR})
|
||||||
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
||||||
|
|
||||||
#Build
|
#Build
|
||||||
|
@ -23,17 +23,17 @@ freely, subject to the following restrictions:
|
|||||||
|
|
||||||
#include "OpenGLWidget.h"
|
#include "OpenGLWidget.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/CubicSurfaceExtractor.h"
|
#include "PolyVox/CubicSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVox/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/SurfaceMesh.h"
|
#include "PolyVox/Mesh.h"
|
||||||
#include "PolyVoxCore/SimpleVolume.h"
|
#include "PolyVox/PagedVolume.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
//Use the PolyVox namespace
|
//Use the PolyVox namespace
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
|
|
||||||
void createSphereInVolume(SimpleVolume<uint8_t>& volData, float fRadius)
|
void createSphereInVolume(PagedVolume<uint8_t>& volData, float fRadius)
|
||||||
{
|
{
|
||||||
//This vector hold the position of the center of the volume
|
//This vector hold the position of the center of the volume
|
||||||
Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
||||||
@ -74,21 +74,21 @@ int main(int argc, char *argv[])
|
|||||||
openGLWidget.show();
|
openGLWidget.show();
|
||||||
|
|
||||||
//Create an empty volume and then place a sphere in it
|
//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)));
|
PagedVolume<uint8_t> volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(63, 63, 63)));
|
||||||
createSphereInVolume(volData, 30);
|
createSphereInVolume(volData, 30);
|
||||||
|
|
||||||
//A mesh object to hold the result of surface extraction
|
// Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see.
|
||||||
SurfaceMesh<PositionMaterial> mesh;
|
auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion());
|
||||||
|
//auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion());
|
||||||
|
|
||||||
//Create a surface extractor. Comment out one of the following two lines to decide which type gets created.
|
// The surface extractor outputs the mesh in an efficient compressed format which is not directly suitable for rendering. The easiest approach is to
|
||||||
CubicSurfaceExtractor< SimpleVolume<uint8_t> > surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
|
// 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.
|
||||||
//MarchingCubesSurfaceExtractor< SimpleVolume<uint8_t> > surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
|
auto decodedMesh = decodeMesh(mesh);
|
||||||
|
|
||||||
//Execute the surface extractor.
|
|
||||||
surfaceExtractor.execute();
|
|
||||||
|
|
||||||
//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();
|
||||||
|
7
examples/CMakeLists.txt
Normal file
7
examples/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
ADD_SUBDIRECTORY(common)
|
||||||
|
ADD_SUBDIRECTORY(Basic)
|
||||||
|
ADD_SUBDIRECTORY(Paging)
|
||||||
|
ADD_SUBDIRECTORY(OpenGL)
|
||||||
|
ADD_SUBDIRECTORY(SmoothLOD)
|
||||||
|
ADD_SUBDIRECTORY(DecodeOnGPU)
|
||||||
|
ADD_SUBDIRECTORY(Python)
|
67
examples/DecodeOnGPU/CMakeLists.txt
Normal file
67
examples/DecodeOnGPU/CMakeLists.txt
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# 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} ${PolyVoxHeaders_SOURCE_DIR} ${GLEW_SOURCE_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})
|
||||||
|
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
|
||||||
|
)
|
||||||
|
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>
|
46
examples/DecodeOnGPU/decode.vert
Normal file
46
examples/DecodeOnGPU/decode.vert
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#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;
|
||||||
|
|
||||||
|
// Returns +/- 1
|
||||||
|
vec2 signNotZero(vec2 v)
|
||||||
|
{
|
||||||
|
return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 decodedPosition = position;
|
||||||
|
decodedPosition.xyz = decodedPosition.xyz * (1.0 / 256.0);
|
||||||
|
|
||||||
|
//Get the encoded bytes of the normal
|
||||||
|
uint encodedX = (normal >> 8u) & 0xFFu;
|
||||||
|
uint encodedY = (normal) & 0xFFu;
|
||||||
|
|
||||||
|
// Map to range [-1.0, +1.0]
|
||||||
|
vec2 e = vec2(encodedX, encodedY);
|
||||||
|
e = e * vec2(1.0 / 127.5, 1.0 / 127.5);
|
||||||
|
e = e - vec2(1.0, 1.0);
|
||||||
|
|
||||||
|
// Now decode normal using listing 2 of http://jcgt.org/published/0003/02/01/
|
||||||
|
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
|
||||||
|
if (v.z < 0) v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);
|
||||||
|
worldNormal.xyz = normalize(v);
|
||||||
|
worldNormal.w = 1.0;
|
||||||
|
|
||||||
|
// Standard sequence of OpenGL transformations.
|
||||||
|
worldPosition = modelToWorldMatrix * decodedPosition;
|
||||||
|
vec4 cameraPosition = worldToCameraMatrix * worldPosition;
|
||||||
|
gl_Position = cameraToClipMatrix * cameraPosition;
|
||||||
|
}
|
167
examples/DecodeOnGPU/main.cpp
Normal file
167
examples/DecodeOnGPU/main.cpp
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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 "PolyVox/CubicSurfaceExtractor.h"
|
||||||
|
#include "PolyVox/MarchingCubesSurfaceExtractor.h"
|
||||||
|
#include "PolyVox/Mesh.h"
|
||||||
|
#include "PolyVox/PagedVolume.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
//Use the PolyVox namespace
|
||||||
|
using namespace PolyVox;
|
||||||
|
|
||||||
|
void createSphereInVolume(PagedVolume<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;
|
||||||
|
|
||||||
|
// Set 16 or 32-bit index buffer size.
|
||||||
|
meshData.indexType = sizeof(PolyVox::Mesh< PolyVox::MarchingCubesVertex< uint8_t > >::IndexType) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
|
||||||
|
|
||||||
|
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
|
||||||
|
PagedVolume<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 = decodeMesh(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,41 +26,36 @@ 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} ${PolyVoxHeaders_SOURCE_DIR} ${GLEW_SOURCE_DIR})
|
||||||
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
|
||||||
|
#This will include the shader files inside the compiled binary
|
||||||
|
QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
||||||
|
QT4_ADD_RESOURCES(OPENGLEXAMPLE_RESOURCES_RCC openglexample.qrc)
|
||||||
|
|
||||||
|
# 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)
|
||||||
TARGET_LINK_LIBRARIES(OpenGLExample glew Qt5::OpenGL ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
TARGET_LINK_LIBRARIES(OpenGLExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY})
|
||||||
SET_PROPERTY(TARGET OpenGLExample PROPERTY FOLDER "Examples")
|
SET_PROPERTY(TARGET OpenGLExample PROPERTY FOLDER "Examples")
|
||||||
|
|
||||||
#Install - Only install the example in Windows
|
#Install - Only install the example in Windows
|
||||||
@ -71,11 +66,4 @@ IF(WIN32)
|
|||||||
ARCHIVE DESTINATION Examples/OpenGL/lib
|
ARCHIVE DESTINATION Examples/OpenGL/lib
|
||||||
COMPONENT example
|
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)
|
ENDIF(WIN32)
|
||||||
|
@ -1,63 +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<PositionMaterialNormal>& mesh, unsigned int uLodLevel)
|
|
||||||
{
|
|
||||||
const vector<PositionMaterialNormal>& 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 PositionMaterialNormal& 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>(vertex.getMaterial() + 0.5);
|
|
||||||
|
|
||||||
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,33 +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/PolyVoxForwardDeclarations.h"
|
|
||||||
|
|
||||||
#include "glew/glew.h"
|
|
||||||
|
|
||||||
void renderRegionImmediateMode(PolyVox::SurfaceMesh<PolyVox::PositionMaterialNormal>& 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,40 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
Copyright (c) 2005-2009 David Williams
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any damages
|
|
||||||
arising from the use of this software.
|
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
|
||||||
including commercial applications, and to alter it and redistribute it
|
|
||||||
freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
|
||||||
claim that you wrote the original software. If you use this software
|
|
||||||
in a product, an acknowledgment in the product documentation would be
|
|
||||||
appreciated but is not required.
|
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
misrepresented as being the original software.
|
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
|
||||||
distribution.
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
#ifndef __OpenGLExample_OpenGLSupport_H__
|
|
||||||
#define __OpenGLExample_OpenGLSupport_H__
|
|
||||||
|
|
||||||
#include "PolyVoxCore/PolyVoxForwardDeclarations.h"
|
|
||||||
|
|
||||||
#include "glew/glew.h"
|
|
||||||
|
|
||||||
struct OpenGLColour
|
|
||||||
{
|
|
||||||
GLfloat red;
|
|
||||||
GLfloat green;
|
|
||||||
GLfloat blue;
|
|
||||||
};
|
|
||||||
|
|
||||||
OpenGLColour convertMaterialIDToColour(uint8_t materialID);
|
|
||||||
|
|
||||||
#endif //__OpenGLExample_OpenGLSupport_H__
|
|
@ -1,124 +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/SurfaceMesh.h"
|
|
||||||
|
|
||||||
using namespace PolyVox;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const SurfaceMesh<PositionMaterialNormal>& 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<PositionMaterialNormal>& 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<PositionMaterialNormal>::const_iterator iterVertex = vecVertices.begin(); iterVertex != vecVertices.end(); ++iterVertex)
|
|
||||||
{
|
|
||||||
const PositionMaterialNormal& 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() + 0.5);
|
|
||||||
|
|
||||||
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::PositionMaterialNormal>* sourceMesh;
|
|
||||||
};
|
|
||||||
|
|
||||||
OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const PolyVox::SurfaceMesh<PolyVox::PositionMaterialNormal>& 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<PositionMaterialNormal> > mesh(new SurfaceMesh<PositionMaterialNormal>);
|
|
||||||
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<PositionMaterialNormal> > 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::PositionMaterialNormal> >, Vector3DUint8Compare> m_mapSurfaceMeshes;
|
|
||||||
|
|
||||||
unsigned int m_uRegionSideLength;
|
|
||||||
unsigned int m_uVolumeWidthInRegions;
|
|
||||||
unsigned int m_uVolumeHeightInRegions;
|
|
||||||
unsigned int m_uVolumeDepthInRegions;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //__PolyVox_OpenGLWidget_H__
|
|
@ -23,11 +23,11 @@ freely, subject to the following restrictions:
|
|||||||
|
|
||||||
#include "Shapes.h"
|
#include "Shapes.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/MaterialDensityPair.h"
|
#include "PolyVox/MaterialDensityPair.h"
|
||||||
|
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
|
|
||||||
void createSphereInVolume(LargeVolume<MaterialDensityPair44>& volData, float fRadius, uint8_t uValue)
|
void createSphereInVolume(PagedVolume<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(PagedVolume<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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,10 @@ freely, subject to the following restrictions:
|
|||||||
#ifndef __OpenGLExample_Shapes_H__
|
#ifndef __OpenGLExample_Shapes_H__
|
||||||
#define __OpenGLExample_Shapes_H__
|
#define __OpenGLExample_Shapes_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/LargeVolume.h"
|
#include "PolyVox/PagedVolume.h"
|
||||||
#include "PolyVoxCore/MaterialDensityPair.h"
|
#include "PolyVox/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__
|
@ -21,17 +21,14 @@ freely, subject to the following restrictions:
|
|||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVoxCore/FilePager.h"
|
#include "PolyVox/FilePager.h"
|
||||||
#include "PolyVoxCore/MaterialDensityPair.h"
|
#include "PolyVox/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/LargeVolume.h"
|
#include "PolyVox/MaterialDensityPair.h"
|
||||||
#include "PolyVoxCore/LowPassFilter.h"
|
#include "PolyVox/LowPassFilter.h"
|
||||||
#include "PolyVoxCore/RawVolume.h"
|
#include "PolyVox/RawVolume.h"
|
||||||
#include "PolyVoxCore/RLEBlockCompressor.h"
|
#include "PolyVox/Mesh.h"
|
||||||
#include "PolyVoxCore/SurfaceMesh.h"
|
#include "PolyVox/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 +45,12 @@ 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>();
|
FilePager<MaterialDensityPair88>* pager = new FilePager<MaterialDensityPair88>(".");
|
||||||
FilePager<MaterialDensityPair44>* pager = new FilePager<MaterialDensityPair44>("./");
|
PagedVolume<MaterialDensityPair88> volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(g_uVolumeSideLength - 1, g_uVolumeSideLength - 1, g_uVolumeSideLength - 1)), pager);
|
||||||
LargeVolume<MaterialDensityPair44> 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 +78,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 +85,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 = decodeMesh(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;
|
||||||
|
}
|
@ -19,12 +19,14 @@
|
|||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||||
|
|
||||||
PROJECT(PagingExample)
|
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
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -36,25 +38,28 @@ 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} ${PolyVoxHeaders_SOURCE_DIR} ${GLEW_SOURCE_DIR})
|
||||||
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
|
||||||
|
#This will include the shader files inside the compiled binary
|
||||||
|
QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
||||||
|
|
||||||
|
# Put the resources in a seperate folder in Visual Studio
|
||||||
|
SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC})
|
||||||
|
|
||||||
#Build
|
#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 Qt5::OpenGL ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
TARGET_LINK_LIBRARIES(PagingExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY})
|
||||||
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
|
||||||
@ -63,11 +68,4 @@ IF(WIN32)
|
|||||||
ARCHIVE DESTINATION Examples/OpenGL/lib
|
ARCHIVE DESTINATION Examples/OpenGL/lib
|
||||||
COMPONENT example
|
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)
|
ENDIF(WIN32)
|
||||||
|
@ -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<PositionMaterialNormal>& 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<PositionMaterialNormal>& 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(PositionMaterialNormal), 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);
|
|
||||||
|
|
||||||
//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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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(PositionMaterialNormal), 0);
|
|
||||||
glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (GLvoid*)12);
|
|
||||||
|
|
||||||
glDrawRangeElements(GL_TRIANGLES, m_uBeginIndex, m_uEndIndex-1, m_uEndIndex - m_uBeginIndex, GL_UNSIGNED_INT, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
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,67 +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::PositionMaterialNormal>& 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__
|
|
@ -24,20 +24,18 @@ freely, subject to the following restrictions:
|
|||||||
#include "OpenGLWidget.h"
|
#include "OpenGLWidget.h"
|
||||||
#include "Perlin.h"
|
#include "Perlin.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/MaterialDensityPair.h"
|
#include "PolyVox/MaterialDensityPair.h"
|
||||||
#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.h"
|
#include "PolyVox/CubicSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVox/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/Pager.h"
|
#include "PolyVox/Mesh.h"
|
||||||
#include "PolyVoxCore/RLEBlockCompressor.h"
|
#include "PolyVox/PagedVolume.h"
|
||||||
#include "PolyVoxCore/SurfaceMesh.h"
|
|
||||||
#include "PolyVoxCore/LargeVolume.h"
|
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
//Use the PolyVox namespace
|
//Use the PolyVox namespace
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
|
|
||||||
void createSphereInVolume(LargeVolume<MaterialDensityPair44>& volData, Vector3DFloat v3dVolCenter, float fRadius)
|
void createSphereInVolume(PagedVolume<MaterialDensityPair44>& volData, Vector3DFloat v3dVolCenter, float fRadius)
|
||||||
{
|
{
|
||||||
//This vector hold the position of the center of the volume
|
//This vector hold the position of the center of the volume
|
||||||
//Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
//Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
||||||
@ -79,24 +77,20 @@ void createSphereInVolume(LargeVolume<MaterialDensityPair44>& volData, Vector3DF
|
|||||||
/**
|
/**
|
||||||
* Generates data using Perlin noise.
|
* Generates data using Perlin noise.
|
||||||
*/
|
*/
|
||||||
class PerlinNoisePager : public PolyVox::Pager<MaterialDensityPair44>
|
class PerlinNoisePager : public PolyVox::PagedVolume<MaterialDensityPair44>::Pager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
/// Constructor
|
||||||
PerlinNoisePager()
|
PerlinNoisePager()
|
||||||
:Pager<MaterialDensityPair44>()
|
:PagedVolume<MaterialDensityPair44>::Pager()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
virtual ~PerlinNoisePager() {};
|
virtual ~PerlinNoisePager() {};
|
||||||
|
|
||||||
virtual void pageIn(const PolyVox::Region& region, CompressedBlock<MaterialDensityPair44>* pBlockData)
|
virtual void pageIn(const PolyVox::Region& region, PagedVolume<MaterialDensityPair44>::Chunk* pChunk)
|
||||||
{
|
{
|
||||||
// FIXME - this isn't a great example... it's a shame we have to hard clode the block size and also create/destroy
|
|
||||||
// a compressor each time. These could at least be moved outside somewhere if we can't fix it in a better way...
|
|
||||||
UncompressedBlock<MaterialDensityPair44> block(256);
|
|
||||||
|
|
||||||
Perlin perlin(2,2,1,234);
|
Perlin perlin(2,2,1,234);
|
||||||
|
|
||||||
for(int x = region.getLowerX(); x <= region.getUpperX(); x++)
|
for(int x = region.getLowerX(); x <= region.getUpperX(); x++)
|
||||||
@ -130,21 +124,16 @@ public:
|
|||||||
voxel.setDensity(MaterialDensityPair44::getMinDensity());
|
voxel.setDensity(MaterialDensityPair44::getMinDensity());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Voxel position within a block always start from zero. So if a block represents region (4, 8, 12) to (11, 19, 15)
|
// Voxel position within a chunk always start from zero. So if a chunk represents region (4, 8, 12) to (11, 19, 15)
|
||||||
// then the valid block voxels are from (0, 0, 0) to (7, 11, 3). Hence we subtract the lower corner position of the
|
// then the valid chunk voxels are from (0, 0, 0) to (7, 11, 3). Hence we subtract the lower corner position of the
|
||||||
// region from the volume space position in order to get the block space position.
|
// region from the volume space position in order to get the chunk space position.
|
||||||
block.setVoxelAt(x - region.getLowerX(), y - region.getLowerY(), z - region.getLowerZ(), voxel);
|
pChunk->setVoxelAt(x - region.getLowerX(), y - region.getLowerY(), z - region.getLowerZ(), voxel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now compress the computed data into the provided block.
|
virtual void pageOut(const PolyVox::Region& region, PagedVolume<MaterialDensityPair44>::Chunk* /*pChunk*/)
|
||||||
RLEBlockCompressor<MaterialDensityPair44>* compressor = new RLEBlockCompressor<MaterialDensityPair44>();
|
|
||||||
compressor->compress(&block, pBlockData);
|
|
||||||
delete compressor;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void pageOut(const PolyVox::Region& region, CompressedBlock<MaterialDensityPair44>* /*pBlockData*/)
|
|
||||||
{
|
{
|
||||||
std::cout << "warning unloading region: " << region.getLowerCorner() << " -> " << region.getUpperCorner() << std::endl;
|
std::cout << "warning unloading region: " << region.getLowerCorner() << " -> " << region.getUpperCorner() << std::endl;
|
||||||
}
|
}
|
||||||
@ -157,44 +146,40 @@ int main(int argc, char *argv[])
|
|||||||
OpenGLWidget openGLWidget(0);
|
OpenGLWidget openGLWidget(0);
|
||||||
openGLWidget.show();
|
openGLWidget.show();
|
||||||
|
|
||||||
RLEBlockCompressor<MaterialDensityPair44>* compressor = new RLEBlockCompressor<MaterialDensityPair44>();
|
|
||||||
PerlinNoisePager* pager = new PerlinNoisePager();
|
PerlinNoisePager* pager = new PerlinNoisePager();
|
||||||
LargeVolume<MaterialDensityPair44> volData(PolyVox::Region::MaxRegion, compressor, pager, 256);
|
PagedVolume<MaterialDensityPair44> volData(PolyVox::Region::MaxRegion(), pager, 64);
|
||||||
volData.setMaxNumberOfBlocksInMemory(4096);
|
volData.setMemoryUsageLimit(8 * 1024 * 1024); // 8Mb
|
||||||
volData.setMaxNumberOfUncompressedBlocks(64);
|
|
||||||
|
|
||||||
//volData.setMaxNumberOfUncompressedBlocks(4096);
|
|
||||||
//createSphereInVolume(volData, 30);
|
//createSphereInVolume(volData, 30);
|
||||||
//createPerlinTerrain(volData);
|
//createPerlinTerrain(volData);
|
||||||
//createPerlinVolumeSlow(volData);
|
//createPerlinVolumeSlow(volData);
|
||||||
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
||||||
std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
//std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
||||||
//volData.setBlockCacheSize(64);
|
|
||||||
PolyVox::Region reg(Vector3DInt32(-255,0,0), Vector3DInt32(255,255,255));
|
PolyVox::Region reg(Vector3DInt32(-255,0,0), Vector3DInt32(255,255,255));
|
||||||
std::cout << "Prefetching region: " << reg.getLowerCorner() << " -> " << reg.getUpperCorner() << std::endl;
|
std::cout << "Prefetching region: " << reg.getLowerCorner() << " -> " << reg.getUpperCorner() << std::endl;
|
||||||
volData.prefetch(reg);
|
volData.prefetch(reg);
|
||||||
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
||||||
std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
//std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
||||||
PolyVox::Region reg2(Vector3DInt32(0,0,0), Vector3DInt32(255,255,255));
|
PolyVox::Region reg2(Vector3DInt32(0,0,0), Vector3DInt32(255,255,255));
|
||||||
std::cout << "Flushing region: " << reg2.getLowerCorner() << " -> " << reg2.getUpperCorner() << std::endl;
|
std::cout << "Flushing region: " << reg2.getLowerCorner() << " -> " << reg2.getUpperCorner() << std::endl;
|
||||||
volData.flush(reg2);
|
volData.flush(reg2);
|
||||||
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
||||||
std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
//std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
||||||
std::cout << "Flushing entire volume" << std::endl;
|
std::cout << "Flushing entire volume" << std::endl;
|
||||||
volData.flushAll();
|
volData.flushAll();
|
||||||
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
||||||
std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
//std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
||||||
|
|
||||||
//Extract the surface
|
//Extract the surface
|
||||||
SurfaceMesh<PositionMaterialNormal> mesh;
|
auto mesh = extractCubicMesh(&volData, reg2);
|
||||||
CubicSurfaceExtractorWithNormals< LargeVolume<MaterialDensityPair44> > surfaceExtractor(&volData, reg, &mesh);
|
|
||||||
//MarchingCubesSurfaceExtractor< LargeVolume<MaterialDensityPair44> > surfaceExtractor(&volData, reg, &mesh);
|
|
||||||
//CubicSurfaceExtractorWithNormals<MaterialDensityPair44> surfaceExtractor(&volData, reg, &mesh);
|
|
||||||
surfaceExtractor.execute();
|
|
||||||
std::cout << "#vertices: " << mesh.getNoOfVertices() << std::endl;
|
std::cout << "#vertices: " << mesh.getNoOfVertices() << std::endl;
|
||||||
|
|
||||||
|
auto decodedMesh = decodeMesh(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)
|
||||||
|
@ -19,12 +19,14 @@
|
|||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||||
|
|
||||||
PROJECT(SmoothLODExample)
|
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
|
||||||
@ -34,25 +36,28 @@ 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} ${PolyVoxHeaders_SOURCE_DIR} ${GLEW_SOURCE_DIR})
|
||||||
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
|
||||||
|
#This will include the shader files inside the compiled binary
|
||||||
|
QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
||||||
|
|
||||||
|
# Put the resources in a seperate folder in Visual Studio
|
||||||
|
SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC})
|
||||||
|
|
||||||
#Build
|
#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 Qt5::OpenGL ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
TARGET_LINK_LIBRARIES(SmoothLODExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY})
|
||||||
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
|
||||||
@ -61,11 +66,4 @@ IF(WIN32)
|
|||||||
ARCHIVE DESTINATION Examples/OpenGL/lib
|
ARCHIVE DESTINATION Examples/OpenGL/lib
|
||||||
COMPONENT example
|
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)
|
ENDIF(WIN32)
|
||||||
|
@ -1,186 +0,0 @@
|
|||||||
#include "OpenGLWidget.h"
|
|
||||||
|
|
||||||
#include <QMouseEvent>
|
|
||||||
|
|
||||||
using namespace PolyVox;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
OpenGLWidget::OpenGLWidget(QWidget *parent)
|
|
||||||
:QGLWidget(parent)
|
|
||||||
,m_xRotation(0)
|
|
||||||
,m_yRotation(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh<PositionMaterialNormal>& surfaceMesh)
|
|
||||||
{
|
|
||||||
//Convienient access to the vertices and indices
|
|
||||||
const vector<uint32_t>& vecIndices = surfaceMesh.getIndices();
|
|
||||||
const vector<PositionMaterialNormal>& 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(PositionMaterialNormal), pVertices, GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
m_uBeginIndex = 0;
|
|
||||||
m_uEndIndex = vecIndices.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLWidget::setSurfaceMeshToRenderLowLOD(const PolyVox::SurfaceMesh<PositionMaterialNormal>& surfaceMesh)
|
|
||||||
{
|
|
||||||
//Convienient access to the vertices and indices
|
|
||||||
const vector<uint32_t>& vecIndices = surfaceMesh.getIndices();
|
|
||||||
const vector<PositionMaterialNormal>& 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(PositionMaterialNormal), 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(PositionMaterialNormal), 0);
|
|
||||||
glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (GLvoid*)12);
|
|
||||||
|
|
||||||
glDrawRangeElements(GL_TRIANGLES, m_uBeginIndex, m_uEndIndex-1, m_uEndIndex - m_uBeginIndex, GL_UNSIGNED_INT, 0);
|
|
||||||
|
|
||||||
//Bind the index buffer
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferLow);
|
|
||||||
|
|
||||||
//Bind the vertex buffer
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferLow);
|
|
||||||
glVertexPointer(3, GL_FLOAT, sizeof(PositionMaterialNormal), 0);
|
|
||||||
glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (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::PositionMaterialNormal>& surfaceMesh);
|
|
||||||
void setSurfaceMeshToRenderLowLOD(const PolyVox::SurfaceMesh<PolyVox::PositionMaterialNormal>& 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__
|
|
@ -23,19 +23,19 @@ freely, subject to the following restrictions:
|
|||||||
|
|
||||||
#include "OpenGLWidget.h"
|
#include "OpenGLWidget.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/Density.h"
|
#include "PolyVox/Density.h"
|
||||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVox/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/SurfaceMesh.h"
|
#include "PolyVox/Mesh.h"
|
||||||
#include "PolyVoxCore/RawVolume.h"
|
#include "PolyVox/RawVolume.h"
|
||||||
#include "PolyVoxCore/SimpleVolume.h"
|
#include "PolyVox/PagedVolume.h"
|
||||||
#include "PolyVoxCore/VolumeResampler.h"
|
#include "PolyVox/VolumeResampler.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
//Use the PolyVox namespace
|
//Use the PolyVox namespace
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
|
|
||||||
void createSphereInVolume(SimpleVolume<uint8_t>& volData, float fRadius)
|
void createSphereInVolume(PagedVolume<uint8_t>& volData, float fRadius)
|
||||||
{
|
{
|
||||||
//This vector hold the position of the center of the volume
|
//This vector hold the position of the center of the volume
|
||||||
Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
||||||
@ -76,34 +76,34 @@ int main(int argc, char *argv[])
|
|||||||
openGLWidget.show();
|
openGLWidget.show();
|
||||||
|
|
||||||
//Create an empty volume and then place a sphere in it
|
//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)));
|
PagedVolume<uint8_t> volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(63, 63, 63)));
|
||||||
createSphereInVolume(volData, 28);
|
createSphereInVolume(volData, 28);
|
||||||
|
|
||||||
//Smooth the data - should reimplement this using LowPassFilter
|
//Smooth the data - should reimplement this using LowPassFilter
|
||||||
//smoothRegion<SimpleVolume, Density8>(volData, volData.getEnclosingRegion());
|
//smoothRegion<PagedVolume, Density8>(volData, volData.getEnclosingRegion());
|
||||||
//smoothRegion<SimpleVolume, Density8>(volData, volData.getEnclosingRegion());
|
//smoothRegion<PagedVolume, Density8>(volData, volData.getEnclosingRegion());
|
||||||
//smoothRegion<SimpleVolume, Density8>(volData, volData.getEnclosingRegion());
|
//smoothRegion<PagedVolume, Density8>(volData, volData.getEnclosingRegion());
|
||||||
|
|
||||||
RawVolume<uint8_t> volDataLowLOD(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(15, 31, 31)));
|
RawVolume<uint8_t> volDataLowLOD(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(15, 31, 31)));
|
||||||
|
|
||||||
VolumeResampler< SimpleVolume<uint8_t>, RawVolume<uint8_t> > volumeResampler(&volData, PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(31, 63, 63)), &volDataLowLOD, volDataLowLOD.getEnclosingRegion());
|
VolumeResampler< PagedVolume<uint8_t>, RawVolume<uint8_t> > volumeResampler(&volData, PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(31, 63, 63)), &volDataLowLOD, volDataLowLOD.getEnclosingRegion());
|
||||||
volumeResampler.execute();
|
volumeResampler.execute();
|
||||||
|
|
||||||
//Extract the surface
|
//Extract the surface
|
||||||
SurfaceMesh<PositionMaterialNormal> meshLowLOD;
|
auto meshLowLOD = extractMarchingCubesMesh(&volDataLowLOD, volDataLowLOD.getEnclosingRegion());
|
||||||
MarchingCubesSurfaceExtractor< RawVolume<uint8_t> > surfaceExtractor(&volDataLowLOD, volDataLowLOD.getEnclosingRegion(), &meshLowLOD);
|
// The returned mesh needs to be decoded to be appropriate for GPU rendering.
|
||||||
surfaceExtractor.execute();
|
auto decodedMeshLowLOD = decodeMesh(meshLowLOD);
|
||||||
meshLowLOD.scaleVertices(/*2.0f*/63.0f / 31.0f);
|
|
||||||
|
|
||||||
//Extract the surface
|
//Extract the surface
|
||||||
SurfaceMesh<PositionMaterialNormal> meshHighLOD;
|
auto meshHighLOD = extractMarchingCubesMesh(&volData, PolyVox::Region(Vector3DInt32(30, 0, 0), Vector3DInt32(63, 63, 63)));
|
||||||
MarchingCubesSurfaceExtractor< SimpleVolume<uint8_t> > surfaceExtractorHigh(&volData, PolyVox::Region(Vector3DInt32(30,0,0), Vector3DInt32(63, 63, 63)), &meshHighLOD);
|
// The returned mesh needs to be decoded to be appropriate for GPU rendering.
|
||||||
surfaceExtractorHigh.execute();
|
auto decodedMeshHighLOD = decodeMesh(meshHighLOD);
|
||||||
meshHighLOD.translateVertices(Vector3DFloat(30, 0, 0));
|
|
||||||
|
|
||||||
//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, meshData.indexType, 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
|
||||||
|
}
|
160
examples/common/OpenGLWidget.h
Normal file
160
examples/common/OpenGLWidget.h
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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 "PolyVox/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;
|
||||||
|
GLenum indexType;
|
||||||
|
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 MeshType>
|
||||||
|
void addMesh(const MeshType& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f)
|
||||||
|
{
|
||||||
|
// Convienient access to the vertices and indices
|
||||||
|
const auto& vecIndices = surfaceMesh.getIndices();
|
||||||
|
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(typename MeshType::VertexType), 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(typename MeshType::IndexType), 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(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type)
|
||||||
|
|
||||||
|
// Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor
|
||||||
|
// does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the
|
||||||
|
// shader. This is mostly just to simplify this example code - in a real application you will know whether your
|
||||||
|
// chosen surface extractor generates normals and can skip uploading them if not.
|
||||||
|
glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals.
|
||||||
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, normal)));
|
||||||
|
|
||||||
|
// Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code
|
||||||
|
// we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here.
|
||||||
|
glEnableVertexAttribArray(2); //We're talking about shader attribute '2'
|
||||||
|
GLint size = (std::min)(sizeof(typename MeshType::VertexType::DataType), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type)
|
||||||
|
glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, data)));
|
||||||
|
|
||||||
|
// We're done uploading and can now unbind.
|
||||||
|
glBindVertexArray(0);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// Set 16 or 32-bit index buffer size.
|
||||||
|
meshData.indexType = sizeof(typename MeshType::IndexType) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
@ -22,32 +22,115 @@
|
|||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||||
|
|
||||||
PROJECT(PolyVox)
|
PROJECT(PolyVoxHeaders)
|
||||||
|
|
||||||
add_subdirectory(PolyVoxCore)
|
#Projects headers files
|
||||||
add_subdirectory(PolyVoxUtil)
|
SET(CORE_INC_FILES
|
||||||
add_subdirectory(bindings)
|
PolyVox/AmbientOcclusionCalculator.h
|
||||||
|
PolyVox/AmbientOcclusionCalculator.inl
|
||||||
|
PolyVox/Array.h
|
||||||
|
PolyVox/AStarPathfinder.h
|
||||||
|
PolyVox/AStarPathfinder.inl
|
||||||
|
PolyVox/BaseVolume.h
|
||||||
|
PolyVox/BaseVolume.inl
|
||||||
|
PolyVox/BaseVolumeSampler.inl
|
||||||
|
PolyVox/CubicSurfaceExtractor.h
|
||||||
|
PolyVox/CubicSurfaceExtractor.inl
|
||||||
|
PolyVox/DefaultIsQuadNeeded.h
|
||||||
|
PolyVox/DefaultMarchingCubesController.h
|
||||||
|
PolyVox/Density.h
|
||||||
|
PolyVox/FilePager.h
|
||||||
|
PolyVox/GradientEstimators.h
|
||||||
|
PolyVox/GradientEstimators.inl
|
||||||
|
PolyVox/Interpolation.h
|
||||||
|
PolyVox/IteratorController.h
|
||||||
|
PolyVox/IteratorController.inl
|
||||||
|
PolyVox/LargeVolume.h
|
||||||
|
PolyVox/LowPassFilter.h
|
||||||
|
PolyVox/LowPassFilter.inl
|
||||||
|
PolyVox/MarchingCubesSurfaceExtractor.h
|
||||||
|
PolyVox/MarchingCubesSurfaceExtractor.inl
|
||||||
|
PolyVox/Material.h
|
||||||
|
PolyVox/MaterialDensityPair.h
|
||||||
|
PolyVox/Mesh.h
|
||||||
|
PolyVox/Mesh.inl
|
||||||
|
PolyVox/PagedVolume.h
|
||||||
|
PolyVox/PagedVolume.inl
|
||||||
|
PolyVox/PagedVolumeChunk.inl
|
||||||
|
PolyVox/PagedVolumeSampler.inl
|
||||||
|
PolyVox/PolyVoxForwardDeclarations.h
|
||||||
|
PolyVox/Picking.h
|
||||||
|
PolyVox/Picking.inl
|
||||||
|
PolyVox/RawVolume.h
|
||||||
|
PolyVox/RawVolume.inl
|
||||||
|
PolyVox/RawVolumeSampler.inl
|
||||||
|
PolyVox/Raycast.h
|
||||||
|
PolyVox/Raycast.inl
|
||||||
|
PolyVox/Region.h
|
||||||
|
PolyVox/Region.inl
|
||||||
|
PolyVox/SimpleVolume.h
|
||||||
|
PolyVox/Vector.h
|
||||||
|
PolyVox/Vector.inl
|
||||||
|
PolyVox/Vertex.h
|
||||||
|
PolyVox/VolumeResampler.h
|
||||||
|
PolyVox/VolumeResampler.inl
|
||||||
|
PolyVox/VoxelFilters.h
|
||||||
|
PolyVox/VoxelFilters.inl
|
||||||
|
)
|
||||||
|
|
||||||
|
SET(IMPL_INC_FILES
|
||||||
|
PolyVox/Impl/AStarPathfinderImpl.h
|
||||||
|
PolyVox/Impl/Config.h
|
||||||
|
PolyVox/Impl/ErrorHandling.h
|
||||||
|
PolyVox/Impl/Logging.h
|
||||||
|
PolyVox/Impl/MarchingCubesTables.h
|
||||||
|
PolyVox/Impl/RandomUnitVectors.h
|
||||||
|
PolyVox/Impl/RandomVectors.h
|
||||||
|
PolyVox/Impl/Timer.h
|
||||||
|
PolyVox/Impl/TypeDef.h
|
||||||
|
PolyVox/Impl/Utility.h
|
||||||
|
)
|
||||||
|
|
||||||
|
#NOTE: The following line should be uncommented when building shared libs.
|
||||||
|
|
||||||
|
#"Sources" and "Headers" are the group names in Visual Studio.
|
||||||
|
#They may have other uses too...
|
||||||
|
#SOURCE_GROUP("Source Files" FILES ${CORE_SRC_FILES})
|
||||||
|
SOURCE_GROUP("Header Files" FILES ${CORE_INC_FILES})
|
||||||
|
|
||||||
|
#SOURCE_GROUP("Source Files\\Impl" FILES ${IMPL_SRC_FILES})
|
||||||
|
SOURCE_GROUP("Header Files\\Impl" FILES ${IMPL_INC_FILES})
|
||||||
|
|
||||||
|
#Tell CMake the paths
|
||||||
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
#Core
|
||||||
|
|
||||||
|
#Build
|
||||||
|
# Although we don't build anything for PolyVox, we still add this custom target (which
|
||||||
|
# doesn't do anything) so that we can browse the source code from within Visual Studio.
|
||||||
|
ADD_CUSTOM_TARGET(PolyVoxCore SOURCES ${CORE_INC_FILES})
|
||||||
|
|
||||||
|
#Install the core header files, including the ones in the Impl subfolder.
|
||||||
|
INSTALL(DIRECTORY PolyVox/ DESTINATION include/PolyVox COMPONENT development PATTERN "*.git*" EXCLUDE)
|
||||||
|
|
||||||
#Set up install paths e.g. for PolyVoxConfig.cmake
|
#Set up install paths e.g. for PolyVoxConfig.cmake
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(CONFIG_FILE_DIR "CMake")
|
set(CONFIG_FILE_DIR "CMake")
|
||||||
set(PolyVoxCore_LIBRARY_INSTALL_DIRS "PolyVoxCore/lib")
|
set(PolyVoxCore_LIBRARY_INSTALL_DIRS "PolyVoxCore/lib")
|
||||||
set(PolyVoxUtil_LIBRARY_INSTALL_DIRS "PolyVoxUtil/lib")
|
|
||||||
set(PolyVoxCore_INCLUDE_INSTALL_DIRS "PolyVoxCore/include")
|
set(PolyVoxCore_INCLUDE_INSTALL_DIRS "PolyVoxCore/include")
|
||||||
set(PolyVoxUtil_INCLUDE_INSTALL_DIRS "PolyVoxUtil/include")
|
|
||||||
set(PolyVox_DOC_INSTALL_DIR "PolyVox/doc")
|
set(PolyVox_DOC_INSTALL_DIR "PolyVox/doc")
|
||||||
else(WIN32)
|
else(WIN32)
|
||||||
set(CONFIG_FILE_DIR "share/PolyVox/cmake")
|
set(CONFIG_FILE_DIR "share/PolyVox/cmake")
|
||||||
set(PolyVoxCore_LIBRARY_INSTALL_DIRS "lib")
|
set(PolyVoxCore_LIBRARY_INSTALL_DIRS "lib")
|
||||||
set(PolyVoxUtil_LIBRARY_INSTALL_DIRS "lib")
|
|
||||||
set(PolyVoxCore_INCLUDE_INSTALL_DIRS "include/PolyVoxCore")
|
set(PolyVoxCore_INCLUDE_INSTALL_DIRS "include/PolyVoxCore")
|
||||||
set(PolyVoxUtil_INCLUDE_INSTALL_DIRS "include/PolyVoxUtil")
|
|
||||||
set(PolyVox_DOC_INSTALL_DIR "share/doc/packages/polyvox")
|
set(PolyVox_DOC_INSTALL_DIR "share/doc/packages/polyvox")
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/PolyVoxConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/PolyVoxConfig.cmake @ONLY)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/PolyVoxConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/PolyVoxConfig.cmake @ONLY)
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/PolyVoxConfig.cmake DESTINATION ${CONFIG_FILE_DIR} COMPONENT development)
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/PolyVoxConfig.cmake DESTINATION ${CONFIG_FILE_DIR} COMPONENT development)
|
||||||
|
|
||||||
|
#Documentation
|
||||||
if(DOXYGEN_FOUND)
|
if(DOXYGEN_FOUND)
|
||||||
#configure_file(${CMAKE_CURRENT_SOURCE_DIR}/polyvox.css ${CMAKE_CURRENT_BINARY_DIR}/polyvox.css)
|
#configure_file(${CMAKE_CURRENT_SOURCE_DIR}/polyvox.css ${CMAKE_CURRENT_BINARY_DIR}/polyvox.css)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
|
||||||
@ -82,5 +165,3 @@ if(DOXYGEN_FOUND)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#add_subdirectory(bindings)
|
|
@ -27,8 +27,6 @@ freely, subject to the following restrictions:
|
|||||||
#include "Impl/AStarPathfinderImpl.h"
|
#include "Impl/AStarPathfinderImpl.h"
|
||||||
#include "Impl/TypeDef.h"
|
#include "Impl/TypeDef.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/Array.h"
|
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <stdexcept> //For runtime_error
|
#include <stdexcept> //For runtime_error
|
||||||
@ -39,9 +37,43 @@ namespace PolyVox
|
|||||||
const float sqrt_2 = 1.4143f;
|
const float sqrt_2 = 1.4143f;
|
||||||
const float sqrt_3 = 1.7321f;
|
const float sqrt_3 = 1.7321f;
|
||||||
|
|
||||||
extern const POLYVOX_API Vector3DInt32 arrayPathfinderFaces[6];
|
const Vector3DInt32 arrayPathfinderFaces[6] =
|
||||||
extern const POLYVOX_API Vector3DInt32 arrayPathfinderEdges[12];
|
{
|
||||||
extern const POLYVOX_API Vector3DInt32 arrayPathfinderCorners[8];
|
Vector3DInt32(0, 0, -1),
|
||||||
|
Vector3DInt32(0, 0, +1),
|
||||||
|
Vector3DInt32(0, -1, 0),
|
||||||
|
Vector3DInt32(0, +1, 0),
|
||||||
|
Vector3DInt32(-1, 0, 0),
|
||||||
|
Vector3DInt32(+1, 0, 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
const Vector3DInt32 arrayPathfinderEdges[12] =
|
||||||
|
{
|
||||||
|
Vector3DInt32(0, -1, -1),
|
||||||
|
Vector3DInt32(0, -1, +1),
|
||||||
|
Vector3DInt32(0, +1, -1),
|
||||||
|
Vector3DInt32(0, +1, +1),
|
||||||
|
Vector3DInt32(-1, 0, -1),
|
||||||
|
Vector3DInt32(-1, 0, +1),
|
||||||
|
Vector3DInt32(+1, 0, -1),
|
||||||
|
Vector3DInt32(+1, 0, +1),
|
||||||
|
Vector3DInt32(-1, -1, 0),
|
||||||
|
Vector3DInt32(-1, +1, 0),
|
||||||
|
Vector3DInt32(+1, -1, 0),
|
||||||
|
Vector3DInt32(+1, +1, 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
const Vector3DInt32 arrayPathfinderCorners[8] =
|
||||||
|
{
|
||||||
|
Vector3DInt32(-1, -1, -1),
|
||||||
|
Vector3DInt32(-1, -1, +1),
|
||||||
|
Vector3DInt32(-1, +1, -1),
|
||||||
|
Vector3DInt32(-1, +1, +1),
|
||||||
|
Vector3DInt32(+1, -1, -1),
|
||||||
|
Vector3DInt32(+1, -1, +1),
|
||||||
|
Vector3DInt32(+1, +1, -1),
|
||||||
|
Vector3DInt32(+1, +1, +1)
|
||||||
|
};
|
||||||
|
|
||||||
/// This function provides the default method for checking whether a given voxel
|
/// This function provides the default method for checking whether a given voxel
|
||||||
/// is valid for the path computed by the AStarPathfinder.
|
/// is valid for the path computed by the AStarPathfinder.
|
||||||
@ -192,6 +224,6 @@ namespace PolyVox
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "PolyVoxCore/AStarPathfinder.inl"
|
#include "PolyVox/AStarPathfinder.inl"
|
||||||
|
|
||||||
#endif //__PolyVox_AStarPathfinder_H__
|
#endif //__PolyVox_AStarPathfinder_H__
|
@ -21,7 +21,7 @@ freely, subject to the following restrictions:
|
|||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVoxCore/Impl/ErrorHandling.h"
|
#include "PolyVox/Impl/ErrorHandling.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
@ -27,13 +27,13 @@ freely, subject to the following restrictions:
|
|||||||
#include "Impl/RandomUnitVectors.h"
|
#include "Impl/RandomUnitVectors.h"
|
||||||
#include "Impl/RandomVectors.h"
|
#include "Impl/RandomVectors.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/Array.h"
|
#include "PolyVox/Array.h"
|
||||||
#include "PolyVoxCore/Region.h"
|
#include "PolyVox/Region.h"
|
||||||
#include "PolyVoxCore/Raycast.h"
|
#include "PolyVox/Raycast.h"
|
||||||
|
|
||||||
//These two should not be here!
|
//These two should not be here!
|
||||||
#include "PolyVoxCore/Material.h"
|
#include "PolyVox/Material.h"
|
||||||
#include "PolyVoxCore/SimpleVolume.h"
|
#include "PolyVox/PagedVolume.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ namespace PolyVox
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator()(const SimpleVolume<uint8_t>::Sampler& sampler)
|
bool operator()(const PagedVolume<uint8_t>::Sampler& sampler)
|
||||||
{
|
{
|
||||||
uint8_t sample = sampler.getVoxel();
|
uint8_t sample = sampler.getVoxel();
|
||||||
bool func = mIsVoxelTransparentCallback(sample);
|
bool func = mIsVoxelTransparentCallback(sample);
|
||||||
@ -77,6 +77,6 @@ namespace PolyVox
|
|||||||
void calculateAmbientOcclusion(VolumeType* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement, IsVoxelTransparentCallback isVoxelTransparentCallback);
|
void calculateAmbientOcclusion(VolumeType* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement, IsVoxelTransparentCallback isVoxelTransparentCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "PolyVoxCore/AmbientOcclusionCalculator.inl"
|
#include "PolyVox/AmbientOcclusionCalculator.inl"
|
||||||
|
|
||||||
#endif //__AmbientOcclusionCalculator_H__
|
#endif //__AmbientOcclusionCalculator_H__
|
@ -128,7 +128,7 @@ namespace PolyVox
|
|||||||
POLYVOX_ASSERT((fVisibility >= 0.0f) && (fVisibility <= 1.0f), "Visibility value out of range.");
|
POLYVOX_ASSERT((fVisibility >= 0.0f) && (fVisibility <= 1.0f), "Visibility value out of range.");
|
||||||
}
|
}
|
||||||
|
|
||||||
(*arrayResult)[z / iRatioZ][y / iRatioY][x / iRatioX] = static_cast<uint8_t>(255.0f * fVisibility);
|
(*arrayResult)(z / iRatioZ, y / iRatioY, x / iRatioX) = static_cast<uint8_t>(255.0f * fVisibility);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
193
include/PolyVox/Array.h
Normal file
193
include/PolyVox/Array.h
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
Copyright (c) 2005-20014 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_Array_H__
|
||||||
|
#define __PolyVox_Array_H__
|
||||||
|
|
||||||
|
#include <PolyVox/Impl/ErrorHandling.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace PolyVox
|
||||||
|
{
|
||||||
|
template <uint32_t noOfDims, typename ElementType>
|
||||||
|
class Array
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
Array(uint32_t width)
|
||||||
|
:m_pElements(0)
|
||||||
|
{
|
||||||
|
static_assert(noOfDims == 1, "This constructor can only be used with a one-dimensional array");
|
||||||
|
|
||||||
|
m_uDimensions[0] = width;
|
||||||
|
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
Array(uint32_t width, uint32_t height)
|
||||||
|
:m_pElements(0)
|
||||||
|
{
|
||||||
|
static_assert(noOfDims == 2, "This constructor can only be used with a two-dimensional array");
|
||||||
|
|
||||||
|
m_uDimensions[0] = width;
|
||||||
|
m_uDimensions[1] = height;
|
||||||
|
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
Array(uint32_t width, uint32_t height, uint32_t depth)
|
||||||
|
:m_pElements(0)
|
||||||
|
{
|
||||||
|
static_assert(noOfDims == 3, "This constructor can only be used with a three-dimensional array");
|
||||||
|
|
||||||
|
m_uDimensions[0] = width;
|
||||||
|
m_uDimensions[1] = height;
|
||||||
|
m_uDimensions[2] = depth;
|
||||||
|
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are deleted to avoid accidental copying.
|
||||||
|
Array<noOfDims, ElementType>(const Array<noOfDims, ElementType>&) = delete;
|
||||||
|
Array<noOfDims, ElementType>& operator=(const Array<noOfDims, ElementType>&) = delete;
|
||||||
|
|
||||||
|
~Array()
|
||||||
|
{
|
||||||
|
delete[] m_pElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementType& operator()(uint32_t x) const
|
||||||
|
{
|
||||||
|
static_assert(noOfDims == 1, "This accessor can only be used with a one-dimensional array");
|
||||||
|
POLYVOX_ASSERT(x < m_uDimensions[0], "Array access is out-of-range.");
|
||||||
|
return m_pElements[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementType& operator()(uint32_t x, uint32_t y) const
|
||||||
|
{
|
||||||
|
static_assert(noOfDims == 2, "This accessor can only be used with a two-dimensional array");
|
||||||
|
POLYVOX_ASSERT(x < m_uDimensions[0] && y < m_uDimensions[1], "Array access is out-of-range.");
|
||||||
|
return m_pElements[y * m_uDimensions[0] + x];
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementType& operator()(uint32_t x, uint32_t y, uint32_t z) const
|
||||||
|
{
|
||||||
|
static_assert(noOfDims == 3, "This accessor can only be used with a three-dimensional array");
|
||||||
|
POLYVOX_ASSERT(x < m_uDimensions[0] && y < m_uDimensions[1] && z < m_uDimensions[2], "Array access is out-of-range.");
|
||||||
|
return m_pElements[z * m_uDimensions[0] * m_uDimensions[1] + y * m_uDimensions[0] + x];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getDimension(uint32_t dimension)
|
||||||
|
{
|
||||||
|
return m_uDimensions[dimension];
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementType* getRawData()
|
||||||
|
{
|
||||||
|
return m_pElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getNoOfElements()
|
||||||
|
{
|
||||||
|
return m_uNoOfElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(Array& other)
|
||||||
|
{
|
||||||
|
ElementType* temp = other.m_pElements;
|
||||||
|
other.m_pElements = m_pElements;
|
||||||
|
m_pElements = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void initialize(void)
|
||||||
|
{
|
||||||
|
// Calculate the total number of elements in the array.
|
||||||
|
m_uNoOfElements = 1;
|
||||||
|
for (uint32_t i = 0; i < noOfDims; i++)
|
||||||
|
{
|
||||||
|
m_uNoOfElements *= m_uDimensions[i];
|
||||||
|
}
|
||||||
|
m_pElements = new ElementType[m_uNoOfElements];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t m_uDimensions[noOfDims];
|
||||||
|
uint32_t m_uNoOfElements;
|
||||||
|
ElementType* m_pElements;
|
||||||
|
};
|
||||||
|
|
||||||
|
///A 1D Array of floats.
|
||||||
|
typedef Array<1, float> Array1DFloat;
|
||||||
|
///A 1D Array of doubles.
|
||||||
|
typedef Array<1, double> Array1DDouble;
|
||||||
|
///A 1D Array of signed 8-bit values.
|
||||||
|
typedef Array<1, int8_t> Array1DInt8;
|
||||||
|
///A 1D Array of unsigned 8-bit values.
|
||||||
|
typedef Array<1, uint8_t> Array1DUint8;
|
||||||
|
///A 1D Array of signed 16-bit values.
|
||||||
|
typedef Array<1, int16_t> Array1DInt16;
|
||||||
|
///A 1D Array of unsigned 16-bit values.
|
||||||
|
typedef Array<1, uint16_t> Array1DUint16;
|
||||||
|
///A 1D Array of signed 32-bit values.
|
||||||
|
typedef Array<1, int32_t> Array1DInt32;
|
||||||
|
///A 1D Array of unsigned 32-bit values.
|
||||||
|
typedef Array<1, uint32_t> Array1DUint32;
|
||||||
|
|
||||||
|
///A 2D Array of floats.
|
||||||
|
typedef Array<2, float> Array2DFloat;
|
||||||
|
///A 2D Array of doubles.
|
||||||
|
typedef Array<2, double> Array2DDouble;
|
||||||
|
///A 2D Array of signed 8-bit values.
|
||||||
|
typedef Array<2, int8_t> Array2DInt8;
|
||||||
|
///A 2D Array of unsigned 8-bit values.
|
||||||
|
typedef Array<2, uint8_t> Array2DUint8;
|
||||||
|
///A 2D Array of signed 16-bit values.
|
||||||
|
typedef Array<2, int16_t> Array2DInt16;
|
||||||
|
///A 2D Array of unsigned 16-bit values.
|
||||||
|
typedef Array<2, uint16_t> Array2DUint16;
|
||||||
|
///A 2D Array of signed 32-bit values.
|
||||||
|
typedef Array<2, int32_t> Array2DInt32;
|
||||||
|
///A 2D Array of unsigned 32-bit values.
|
||||||
|
typedef Array<2, uint32_t> Array2DUint32;
|
||||||
|
|
||||||
|
///A 3D Array of floats.
|
||||||
|
typedef Array<3, float> Array3DFloat;
|
||||||
|
///A 3D Array of doubles.
|
||||||
|
typedef Array<3, double> Array3DDouble;
|
||||||
|
///A 3D Array of signed 8-bit values.
|
||||||
|
typedef Array<3, int8_t> Array3DInt8;
|
||||||
|
///A 3D Array of unsigned 8-bit values.
|
||||||
|
typedef Array<3, uint8_t> Array3DUint8;
|
||||||
|
///A 3D Array of signed 16-bit values.
|
||||||
|
typedef Array<3, int16_t> Array3DInt16;
|
||||||
|
///A 3D Array of unsigned 16-bit values.
|
||||||
|
typedef Array<3, uint16_t> Array3DUint16;
|
||||||
|
///A 3D Array of signed 32-bit values.
|
||||||
|
typedef Array<3, int32_t> Array3DInt32;
|
||||||
|
///A 3D Array of unsigned 32-bit values.
|
||||||
|
typedef Array<3, uint32_t> Array3DUint32;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //__PolyVox_Array_H__
|
@ -24,15 +24,15 @@ freely, subject to the following restrictions:
|
|||||||
#ifndef __PolyVox_BaseVolume_H__
|
#ifndef __PolyVox_BaseVolume_H__
|
||||||
#define __PolyVox_BaseVolume_H__
|
#define __PolyVox_BaseVolume_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/Region.h"
|
#include "PolyVox/Region.h"
|
||||||
#include "PolyVoxCore/Vector.h"
|
#include "PolyVox/Vector.h"
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
/// The BaseVolume class provides common functionality and an interface for other volume classes to implement. You should not try to create an instance of this
|
/// The BaseVolume class provides common functionality and an interface for other volume classes to implement. You should not try to create an instance of this
|
||||||
/// class directly. Instead you should use RawVolume, SimpleVolume, or LargeVolume.
|
/// class directly. Instead you should use RawVolume or PagedVolume.
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// More details to come...
|
/// More details to come...
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -211,7 +211,7 @@ namespace PolyVox
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "PolyVoxCore/BaseVolume.inl"
|
#include "PolyVox/BaseVolume.inl"
|
||||||
#include "PolyVoxCore/BaseVolumeSampler.inl"
|
#include "PolyVox/BaseVolumeSampler.inl"
|
||||||
|
|
||||||
#endif //__PolyVox_BaseVolume_H__
|
#endif //__PolyVox_BaseVolume_H__
|
@ -26,7 +26,7 @@ namespace PolyVox
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This is protected because you should never create a BaseVolume directly, you should instead use one of the derived classes.
|
/// This is protected because you should never create a BaseVolume directly, you should instead use one of the derived classes.
|
||||||
///
|
///
|
||||||
/// \sa RawVolume, SimpleVolume, LargeVolume
|
/// \sa RawVolume, PagedVolume
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
BaseVolume<VoxelType>::BaseVolume(const Region& regValid)
|
BaseVolume<VoxelType>::BaseVolume(const Region& regValid)
|
@ -21,7 +21,7 @@ freely, subject to the following restrictions:
|
|||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVoxCore/Impl/Utility.h"
|
#include "PolyVox/Impl/Utility.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
@ -28,13 +28,151 @@ freely, subject to the following restrictions:
|
|||||||
|
|
||||||
#include "PolyVoxForwardDeclarations.h"
|
#include "PolyVoxForwardDeclarations.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/Array.h"
|
#include "PolyVox/Array.h"
|
||||||
#include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these?
|
#include "PolyVox/BaseVolume.h" //For wrap modes... should move these?
|
||||||
#include "PolyVoxCore/DefaultIsQuadNeeded.h"
|
#include "PolyVox/DefaultIsQuadNeeded.h"
|
||||||
#include "PolyVoxCore/SurfaceMesh.h"
|
#include "PolyVox/Mesh.h"
|
||||||
|
#include "PolyVox/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;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convienient shorthand for declaring a mesh of 'cubic' vertices
|
||||||
|
// Currently disabled because it requires GCC 4.7
|
||||||
|
//template <typename VertexDataType, typename IndexType = DefaultIndexType>
|
||||||
|
//using CubicMesh = Mesh< CubicVertex<VertexDataType>, IndexType >;
|
||||||
|
|
||||||
|
/// Decodes a position from a CubicVertex
|
||||||
|
inline Vector3DFloat decodePosition(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> decodeVertex(const CubicVertex<DataType>& cubicVertex)
|
||||||
|
{
|
||||||
|
Vertex<DataType> result;
|
||||||
|
result.position = decodePosition(cubicVertex.encodedPosition);
|
||||||
|
result.normal.setElements(0.0f, 0.0f, 0.0f); // Currently not calculated
|
||||||
|
result.data = cubicVertex.data; // Data is not encoded
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Do not use this class directly. Use the 'extractCubicSurface' function instead (see examples).
|
||||||
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
||||||
|
class CubicSurfaceExtractor
|
||||||
|
{
|
||||||
|
struct IndexAndMaterial
|
||||||
|
{
|
||||||
|
int32_t iIndex;
|
||||||
|
typename VolumeType::VoxelType uMaterial;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FaceNames
|
||||||
|
{
|
||||||
|
PositiveX,
|
||||||
|
PositiveY,
|
||||||
|
PositiveZ,
|
||||||
|
NegativeX,
|
||||||
|
NegativeY,
|
||||||
|
NegativeZ,
|
||||||
|
NoOfFaces
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Quad
|
||||||
|
{
|
||||||
|
Quad(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3)
|
||||||
|
{
|
||||||
|
vertices[0] = v0;
|
||||||
|
vertices[1] = v1;
|
||||||
|
vertices[2] = v2;
|
||||||
|
vertices[3] = v3;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t vertices[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
CubicSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true);
|
||||||
|
|
||||||
|
void execute();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32_t addVertex(uint32_t uX, uint32_t uY, uint32_t uZ, typename VolumeType::VoxelType uMaterial, Array<3, IndexAndMaterial>& existingVertices);
|
||||||
|
bool performQuadMerging(std::list<Quad>& quads);
|
||||||
|
bool mergeQuads(Quad& q1, Quad& q2);
|
||||||
|
|
||||||
|
IsQuadNeeded m_funcIsQuadNeededCallback;
|
||||||
|
|
||||||
|
//The volume data and a sampler to access it.
|
||||||
|
VolumeType* m_volData;
|
||||||
|
|
||||||
|
//Information about the region we are currently processing
|
||||||
|
Region m_regSizeInVoxels;
|
||||||
|
|
||||||
|
//The surface patch we are currently filling.
|
||||||
|
MeshType* m_meshCurrent;
|
||||||
|
|
||||||
|
//Used to avoid creating duplicate vertices.
|
||||||
|
Array<3, IndexAndMaterial> m_previousSliceVertices;
|
||||||
|
Array<3, IndexAndMaterial> m_currentSliceVertices;
|
||||||
|
|
||||||
|
//During extraction we create a number of different lists of quads. All the
|
||||||
|
//quads in a given list are in the same plane and facing in the same direction.
|
||||||
|
std::vector< std::list<Quad> > m_vecQuads[NoOfFaces];
|
||||||
|
|
||||||
|
//Controls whether quad merging should be performed. This might be undesirable
|
||||||
|
//is the user needs per-vertex attributes, or to perform per vertex lighting.
|
||||||
|
bool m_bMergeQuads;
|
||||||
|
|
||||||
|
//This constant defines the maximum number of quads which can share a
|
||||||
|
//vertex in a cubic style mesh. See the initialisation for more details.
|
||||||
|
static const uint32_t MaxVerticesPerPosition;
|
||||||
|
|
||||||
|
//The wrap mode
|
||||||
|
WrapMode m_eWrapMode;
|
||||||
|
typename VolumeType::VoxelType m_tBorderValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This version of the function performs the extraction into a user-provided mesh rather than allocating a mesh automatically.
|
||||||
|
// There are a few reasons why this might be useful to more advanced users:
|
||||||
|
//
|
||||||
|
// 1. It leaves the user in control of memory allocation and would allow them to implement e.g. a mesh pooling system.
|
||||||
|
// 2. The user-provided mesh could have a different index type (e.g. 16-bit indices) to reduce memory usage.
|
||||||
|
// 3. The user could provide a custom mesh class, e.g a thin wrapper around an openGL VBO to allow direct writing into this structure.
|
||||||
|
//
|
||||||
|
// We don't provide a default MeshType here. If the user doesn't want to provide a MeshType then it probably makes
|
||||||
|
// more sense to use the other variant of this function where the mesh is a return value rather than a parameter.
|
||||||
|
//
|
||||||
|
// Note: This function is called 'extractCubicMeshCustom' rather than 'extractCubicMesh' to avoid ambiguity when only three parameters
|
||||||
|
// are provided (would the third parameter be a controller or a mesh?). It seems this can be fixed by using enable_if/static_assert to emulate concepts,
|
||||||
|
// but this is relatively complex and I haven't done it yet. Could always add it later as another overload.
|
||||||
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded = DefaultIsQuadNeeded<typename VolumeType::VoxelType> >
|
||||||
|
void extractCubicMeshCustom(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true)
|
||||||
|
{
|
||||||
|
CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded> extractor(volData, region, result, isQuadNeeded, eWrapMode, tBorderValue, bMergeQuads);
|
||||||
|
extractor.execute();
|
||||||
|
}
|
||||||
|
|
||||||
/// 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
|
||||||
@ -68,7 +206,7 @@ namespace PolyVox
|
|||||||
///
|
///
|
||||||
/// \image html CubicSurfaceExtractor3.png
|
/// \image html CubicSurfaceExtractor3.png
|
||||||
///
|
///
|
||||||
/// We could choose to add the quads to *both* regions, but this can cause confusion when one of the region is modified (causing the face to disappear or a new one to be created) as *both* regions need to have their mesh regenerated to correctly represent the new state of the volume data. Such pairs of coplanar quads can also cause problems with physics engines, and may prevent transparent block from rendering correctly. Therefore we choose to instead only add the quad to one of the the regions and we always choose the one with the greater coordinate value in the direction in which they differ. In the above example the regions differ by the 'x' component of their position, and so the quad is added to the region with the greater 'x' value (the one marked in blue).
|
/// We could choose to add the quads to *both* regions, but this can cause confusion when one of the region is modified (causing the face to disappear or a new one to be created) as *both* regions need to have their mesh regenerated to correctly represent the new state of the volume data. Such pairs of coplanar quads can also cause problems with physics engines, and may prevent transparent voxels from rendering correctly. Therefore we choose to instead only add the quad to one of the the regions and we always choose the one with the greater coordinate value in the direction in which they differ. In the above example the regions differ by the 'x' component of their position, and so the quad is added to the region with the greater 'x' value (the one marked in blue).
|
||||||
///
|
///
|
||||||
/// **Note:** *This behaviour has changed recently (September 2012). Earlier versions of PolyVox tried to be smart about this problem by looking beyond the region which was being processed, but this complicated the code and didn't work very well. Ultimatly we decided to simply stick with the convention outlined above.*
|
/// **Note:** *This behaviour has changed recently (September 2012). Earlier versions of PolyVox tried to be smart about this problem by looking beyond the region which was being processed, but this complicated the code and didn't work very well. Ultimatly we decided to simply stick with the convention outlined above.*
|
||||||
///
|
///
|
||||||
@ -76,89 +214,15 @@ 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 IsQuadNeeded = DefaultIsQuadNeeded<typename VolumeType::VoxelType> >
|
||||||
class CubicSurfaceExtractor
|
Mesh<CubicVertex<typename VolumeType::VoxelType> > extractCubicMesh(VolumeType* volData, Region region, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true)
|
||||||
{
|
{
|
||||||
struct IndexAndMaterial
|
Mesh< CubicVertex<typename VolumeType::VoxelType> > result;
|
||||||
{
|
extractCubicMeshCustom(volData, region, &result, isQuadNeeded, eWrapMode, tBorderValue, bMergeQuads);
|
||||||
int32_t iIndex;
|
return result;
|
||||||
int32_t uMaterial; //Should actually use the material type here, but this is ok for now.
|
}
|
||||||
};
|
|
||||||
|
|
||||||
enum FaceNames
|
|
||||||
{
|
|
||||||
PositiveX,
|
|
||||||
PositiveY,
|
|
||||||
PositiveZ,
|
|
||||||
NegativeX,
|
|
||||||
NegativeY,
|
|
||||||
NegativeZ,
|
|
||||||
NoOfFaces
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Quad
|
|
||||||
{
|
|
||||||
Quad(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3)
|
|
||||||
{
|
|
||||||
vertices[0] = v0;
|
|
||||||
vertices[1] = v1;
|
|
||||||
vertices[2] = v2;
|
|
||||||
vertices[3] = v3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t vertices[4];
|
#include "PolyVox/CubicSurfaceExtractor.inl"
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
// This is a bit ugly - it seems that the C++03 syntax is different from the C++11 syntax? See this thread: http://stackoverflow.com/questions/6076015/typename-outside-of-template
|
|
||||||
// Long term we should probably come back to this and if the #ifdef is still needed then maybe it should check for C++11 mode instead of MSVC?
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterial>* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded());
|
|
||||||
#else
|
|
||||||
CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterial>* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void execute();
|
|
||||||
|
|
||||||
private:
|
|
||||||
int32_t addVertex(uint32_t uX, uint32_t uY, uint32_t uZ, uint32_t uMaterial, Array<3, IndexAndMaterial>& existingVertices);
|
|
||||||
bool performQuadMerging(std::list<Quad>& quads);
|
|
||||||
bool mergeQuads(Quad& q1, Quad& q2);
|
|
||||||
|
|
||||||
IsQuadNeeded m_funcIsQuadNeededCallback;
|
|
||||||
|
|
||||||
//The volume data and a sampler to access it.
|
|
||||||
VolumeType* m_volData;
|
|
||||||
|
|
||||||
//Information about the region we are currently processing
|
|
||||||
Region m_regSizeInVoxels;
|
|
||||||
|
|
||||||
//The surface patch we are currently filling.
|
|
||||||
SurfaceMesh<PositionMaterial>* m_meshCurrent;
|
|
||||||
|
|
||||||
//Used to avoid creating duplicate vertices.
|
|
||||||
Array<3, IndexAndMaterial> m_previousSliceVertices;
|
|
||||||
Array<3, IndexAndMaterial> m_currentSliceVertices;
|
|
||||||
|
|
||||||
//During extraction we create a number of different lists of quads. All the
|
|
||||||
//quads in a given list are in the same plane and facing in the same direction.
|
|
||||||
std::vector< std::list<Quad> > m_vecQuads[NoOfFaces];
|
|
||||||
|
|
||||||
//Controls whether quad merging should be performed. This might be undesirable
|
|
||||||
//is the user needs per-vertex attributes, or to perform per vertex lighting.
|
|
||||||
bool m_bMergeQuads;
|
|
||||||
|
|
||||||
//This constant defines the maximum number of quads which can share a
|
|
||||||
//vertex in a cubic style mesh. See the initialisation for more details.
|
|
||||||
static const uint32_t MaxVerticesPerPosition;
|
|
||||||
|
|
||||||
//The wrap mode
|
|
||||||
WrapMode m_eWrapMode;
|
|
||||||
typename VolumeType::VoxelType m_tBorderValue;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "PolyVoxCore/CubicSurfaceExtractor.inl"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -21,7 +21,7 @@ freely, subject to the following restrictions:
|
|||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVoxCore/Impl/Timer.h"
|
#include "PolyVox/Impl/Timer.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
@ -32,33 +32,41 @@ 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<PositionMaterial>* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded)
|
CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::CubicSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads)
|
||||||
:m_volData(volData)
|
:m_volData(volData)
|
||||||
,m_regSizeInVoxels(region)
|
,m_regSizeInVoxels(region)
|
||||||
,m_meshCurrent(result)
|
,m_meshCurrent(result)
|
||||||
|
,m_previousSliceVertices(m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2, m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2, MaxVerticesPerPosition)
|
||||||
|
,m_currentSliceVertices(m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2, m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2, MaxVerticesPerPosition)
|
||||||
,m_bMergeQuads(bMergeQuads)
|
,m_bMergeQuads(bMergeQuads)
|
||||||
,m_eWrapMode(eWrapMode)
|
,m_eWrapMode(eWrapMode)
|
||||||
,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();
|
||||||
|
|
||||||
uint32_t uArrayWidth = m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2;
|
//uint32_t uArrayWidth = m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2;
|
||||||
uint32_t uArrayHeight = m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2;
|
//uint32_t uArrayHeight = m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2;
|
||||||
|
|
||||||
uint32_t arraySize[3]= {uArrayWidth, uArrayHeight, MaxVerticesPerPosition};
|
//uint32_t arraySize[3]= {uArrayWidth, uArrayHeight, MaxVerticesPerPosition};
|
||||||
m_previousSliceVertices.resize(arraySize);
|
//m_previousSliceVertices.resize(arraySize);
|
||||||
m_currentSliceVertices.resize(arraySize);
|
//m_currentSliceVertices.resize(arraySize);
|
||||||
memset(m_previousSliceVertices.getRawData(), 0xff, m_previousSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
memset(m_previousSliceVertices.getRawData(), 0xff, m_previousSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
||||||
memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
||||||
|
|
||||||
@ -88,7 +96,7 @@ namespace PolyVox
|
|||||||
{
|
{
|
||||||
uint32_t regX = x - m_regSizeInVoxels.getLowerX();
|
uint32_t regX = x - m_regSizeInVoxels.getLowerX();
|
||||||
|
|
||||||
uint32_t material; //Filled in by callback
|
typename VolumeType::VoxelType material; //Filled in by callback
|
||||||
typename VolumeType::VoxelType currentVoxel = volumeSampler.getVoxel();
|
typename VolumeType::VoxelType currentVoxel = volumeSampler.getVoxel();
|
||||||
typename VolumeType::VoxelType negXVoxel = volumeSampler.peekVoxel1nx0py0pz();
|
typename VolumeType::VoxelType negXVoxel = volumeSampler.peekVoxel1nx0py0pz();
|
||||||
typename VolumeType::VoxelType negYVoxel = volumeSampler.peekVoxel0px1ny0pz();
|
typename VolumeType::VoxelType negYVoxel = volumeSampler.peekVoxel0px1ny0pz();
|
||||||
@ -184,44 +192,41 @@ 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, uint32_t 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++)
|
||||||
{
|
{
|
||||||
IndexAndMaterial& rEntry = existingVertices[uX][uY][ct];
|
IndexAndMaterial& rEntry = existingVertices(uX, uY, ct);
|
||||||
|
|
||||||
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(PositionMaterial(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
//If we have an existing vertex and the material matches then we can return it.
|
//If we have an existing vertex and the material matches then we can return it.
|
||||||
if(rEntry.uMaterial == static_cast<int32_t>(uMaterialIn))
|
if(rEntry.uMaterial == uMaterialIn)
|
||||||
{
|
{
|
||||||
return rEntry.iIndex;
|
return rEntry.iIndex;
|
||||||
}
|
}
|
||||||
@ -233,8 +238,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 +268,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(std::abs(m_meshCurrent->getVertices()[q1.vertices[0]].getMaterial() - m_meshCurrent->getVertices()[q2.vertices[0]].getMaterial()) < 0.001)
|
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
|
@ -24,7 +24,7 @@ freely, subject to the following restrictions:
|
|||||||
#ifndef __PolyVox_DefaultIsQuadNeeded_H__
|
#ifndef __PolyVox_DefaultIsQuadNeeded_H__
|
||||||
#define __PolyVox_DefaultIsQuadNeeded_H__
|
#define __PolyVox_DefaultIsQuadNeeded_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
#include "PolyVox/Impl/TypeDef.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
@ -34,11 +34,11 @@ namespace PolyVox
|
|||||||
class DefaultIsQuadNeeded
|
class DefaultIsQuadNeeded
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool operator()(VoxelType back, VoxelType front, uint32_t& materialToUse)
|
bool operator()(VoxelType back, VoxelType front, VoxelType& materialToUse)
|
||||||
{
|
{
|
||||||
if((back > 0) && (front == 0))
|
if((back > 0) && (front == 0))
|
||||||
{
|
{
|
||||||
materialToUse = static_cast<uint32_t>(back);
|
materialToUse = static_cast<VoxelType>(back);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
@ -24,7 +24,7 @@ freely, subject to the following restrictions:
|
|||||||
#ifndef __PolyVox_MarchingCubesController_H__
|
#ifndef __PolyVox_MarchingCubesController_H__
|
||||||
#define __PolyVox_MarchingCubesController_H__
|
#define __PolyVox_MarchingCubesController_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/BaseVolume.h"
|
#include "PolyVox/BaseVolume.h"
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
@ -64,10 +64,8 @@ namespace PolyVox
|
|||||||
public:
|
public:
|
||||||
/// Used to inform the MarchingCubesSurfaceExtractor about which type it should use for representing densities.
|
/// Used to inform the MarchingCubesSurfaceExtractor about which type it should use for representing densities.
|
||||||
typedef VoxelType DensityType;
|
typedef VoxelType DensityType;
|
||||||
/// Used to inform the MarchingCubesSurfaceExtractor about which type it should use for representing materials. We're using a float here
|
/// Used to inform the MarchingCubesSurfaceExtractor about which type it should use for representing materials.
|
||||||
/// because this implementation always returns a constant value off 1.0f. PolyVox also uses floats to store the materials in the mesh vertices
|
typedef VoxelType MaterialType;
|
||||||
/// but this is not really desirable on modern hardware. We'll probably come back to material representation in the future.
|
|
||||||
typedef float MaterialType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
@ -77,8 +75,15 @@ namespace PolyVox
|
|||||||
* if the voxel type is 'float' then the representable range is -FLT_MAX to FLT_MAX and the threshold will be set to zero.
|
* if the voxel type is 'float' then the representable range is -FLT_MAX to FLT_MAX and the threshold will be set to zero.
|
||||||
*/
|
*/
|
||||||
DefaultMarchingCubesController(void)
|
DefaultMarchingCubesController(void)
|
||||||
:m_tThreshold(((std::numeric_limits<DensityType>::min)() + (std::numeric_limits<DensityType>::max)()) / 2)
|
|
||||||
{
|
{
|
||||||
|
if (std::is_signed<DensityType>())
|
||||||
|
{
|
||||||
|
m_tThreshold = DensityType(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_tThreshold = (((std::numeric_limits<DensityType>::min)() + (std::numeric_limits<DensityType>::max)()) / 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
@ -24,7 +24,7 @@ freely, subject to the following restrictions:
|
|||||||
#ifndef __PolyVox_Density_H__
|
#ifndef __PolyVox_Density_H__
|
||||||
#define __PolyVox_Density_H__
|
#define __PolyVox_Density_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/DefaultMarchingCubesController.h" //We'll specialise the controller contained in here
|
#include "PolyVox/DefaultMarchingCubesController.h" //We'll specialise the controller contained in here
|
||||||
|
|
||||||
#include "Impl/TypeDef.h"
|
#include "Impl/TypeDef.h"
|
||||||
|
|
@ -24,16 +24,17 @@ freely, subject to the following restrictions:
|
|||||||
#ifndef __PolyVox_FilePager_H__
|
#ifndef __PolyVox_FilePager_H__
|
||||||
#define __PolyVox_FilePager_H__
|
#define __PolyVox_FilePager_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
#include "PolyVox/Impl/TypeDef.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/Pager.h"
|
#include "PolyVox/PagedVolume.h"
|
||||||
#include "PolyVoxCore/Region.h"
|
#include "PolyVox/Region.h"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
@ -41,14 +42,21 @@ namespace PolyVox
|
|||||||
* Provides an interface for performing paging of data.
|
* Provides an interface for performing paging of data.
|
||||||
*/
|
*/
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
class FilePager : public Pager<VoxelType>
|
class FilePager : public PagedVolume<VoxelType>::Pager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
/// Constructor
|
||||||
FilePager(const std::string& strFolderName)
|
FilePager(const std::string& strFolderName = ".")
|
||||||
:Pager<VoxelType>()
|
:PagedVolume<VoxelType>::Pager()
|
||||||
,m_strFolderName(strFolderName)
|
,m_strFolderName(strFolderName)
|
||||||
{
|
{
|
||||||
|
// Add the trailing slash, assuming the user dind't already do it.
|
||||||
|
if ((m_strFolderName.back() != '/') && (m_strFolderName.back() != '\\'))
|
||||||
|
{
|
||||||
|
m_strFolderName.append("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build a unique prefix to avoid multiple pagers using the same filenames.
|
||||||
srand(static_cast<unsigned int>(time(0)));
|
srand(static_cast<unsigned int>(time(0)));
|
||||||
int iRandomValue = rand();
|
int iRandomValue = rand();
|
||||||
|
|
||||||
@ -62,16 +70,16 @@ namespace PolyVox
|
|||||||
{
|
{
|
||||||
for(std::vector<std::string>::iterator iter = m_vecCreatedFiles.begin(); iter < m_vecCreatedFiles.end(); iter++)
|
for(std::vector<std::string>::iterator iter = m_vecCreatedFiles.begin(); iter < m_vecCreatedFiles.end(); iter++)
|
||||||
{
|
{
|
||||||
POLYVOX_LOG_WARNING_IF(!std::remove(iter->c_str()), "Failed to delete '" << *iter << "' when destroying FilePager");
|
POLYVOX_LOG_WARNING_IF(std::remove(iter->c_str()) != 0, "Failed to delete '" << *iter << "' when destroying FilePager");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vecCreatedFiles.clear();
|
m_vecCreatedFiles.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void pageIn(const Region& region, CompressedBlock<VoxelType>* pBlockData)
|
virtual void pageIn(const Region& region, typename PagedVolume<VoxelType>::Chunk* pChunk)
|
||||||
{
|
{
|
||||||
POLYVOX_ASSERT(pBlockData, "Attempting to page in NULL block");
|
POLYVOX_ASSERT(pChunk, "Attempting to page in NULL chunk");
|
||||||
//POLYVOX_ASSERT(pBlockData->hasUncompressedData() == false, "Block should not have uncompressed data");
|
POLYVOX_ASSERT(pChunk->getData(), "Chunk must have valid data");
|
||||||
|
|
||||||
std::stringstream ssFilename;
|
std::stringstream ssFilename;
|
||||||
ssFilename << m_strFolderName << "/" << m_strRandomPrefix << "-"
|
ssFilename << m_strFolderName << "/" << m_strRandomPrefix << "-"
|
||||||
@ -88,18 +96,20 @@ namespace PolyVox
|
|||||||
{
|
{
|
||||||
POLYVOX_LOG_TRACE("Paging in data for " << region);
|
POLYVOX_LOG_TRACE("Paging in data for " << region);
|
||||||
|
|
||||||
fseek(pFile, 0L, SEEK_END);
|
/*fseek(pFile, 0L, SEEK_END);
|
||||||
size_t fileSizeInBytes = ftell(pFile);
|
size_t fileSizeInBytes = ftell(pFile);
|
||||||
fseek(pFile, 0L, SEEK_SET);
|
fseek(pFile, 0L, SEEK_SET);
|
||||||
|
|
||||||
uint8_t* buffer = new uint8_t[fileSizeInBytes];
|
uint8_t* buffer = new uint8_t[fileSizeInBytes];
|
||||||
fread(buffer, sizeof(uint8_t), fileSizeInBytes, pFile);
|
fread(buffer, sizeof(uint8_t), fileSizeInBytes, pFile);
|
||||||
pBlockData->setData(buffer, fileSizeInBytes);
|
pChunk->setData(buffer, fileSizeInBytes);
|
||||||
delete[] buffer;
|
delete[] buffer;*/
|
||||||
|
|
||||||
|
fread(pChunk->getData(), sizeof(uint8_t), pChunk->getDataSizeInBytes(), pFile);
|
||||||
|
|
||||||
if(ferror(pFile))
|
if(ferror(pFile))
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(std::runtime_error, "Error reading in block data, even though a file exists.");
|
POLYVOX_THROW(std::runtime_error, "Error reading in chunk data, even though a file exists.");
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
@ -110,10 +120,10 @@ namespace PolyVox
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void pageOut(const Region& region, CompressedBlock<VoxelType>* pBlockData)
|
virtual void pageOut(const Region& region, typename PagedVolume<VoxelType>::Chunk* pChunk)
|
||||||
{
|
{
|
||||||
POLYVOX_ASSERT(pBlockData, "Attempting to page out NULL block");
|
POLYVOX_ASSERT(pChunk, "Attempting to page out NULL chunk");
|
||||||
//POLYVOX_ASSERT(pBlockData->hasUncompressedData() == false, "Block should not have uncompressed data");
|
POLYVOX_ASSERT(pChunk->getData(), "Chunk must have valid data");
|
||||||
|
|
||||||
POLYVOX_LOG_TRACE("Paging out data for " << region);
|
POLYVOX_LOG_TRACE("Paging out data for " << region);
|
||||||
|
|
||||||
@ -130,17 +140,17 @@ namespace PolyVox
|
|||||||
FILE* pFile = fopen(filename.c_str(), "wb");
|
FILE* pFile = fopen(filename.c_str(), "wb");
|
||||||
if(!pFile)
|
if(!pFile)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(std::runtime_error, "Unable to open file to write out block data.");
|
POLYVOX_THROW(std::runtime_error, "Unable to open file to write out chunk data.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//The file has been created, so add it to the list to delete on shutdown.
|
//The file has been created, so add it to the list to delete on shutdown.
|
||||||
m_vecCreatedFiles.push_back(filename);
|
m_vecCreatedFiles.push_back(filename);
|
||||||
|
|
||||||
fwrite(pBlockData->getData(), sizeof(uint8_t), pBlockData->getDataSizeInBytes(), pFile);
|
fwrite(pChunk->getData(), sizeof(uint8_t), pChunk->getDataSizeInBytes(), pFile);
|
||||||
|
|
||||||
if(ferror(pFile))
|
if(ferror(pFile))
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(std::runtime_error, "Error writing out block data.");
|
POLYVOX_THROW(std::runtime_error, "Error writing out chunk data.");
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(pFile);
|
fclose(pFile);
|
@ -24,8 +24,8 @@ freely, subject to the following restrictions:
|
|||||||
#ifndef __PolyVox_GradientEstimators_H__
|
#ifndef __PolyVox_GradientEstimators_H__
|
||||||
#define __PolyVox_GradientEstimators_H__
|
#define __PolyVox_GradientEstimators_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/Vector.h"
|
#include "PolyVox/Vector.h"
|
||||||
#include "PolyVoxCore/VoxelFilters.h"
|
#include "PolyVox/VoxelFilters.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -55,10 +55,10 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "PolyVoxCore/GradientEstimators.inl"
|
#include "PolyVox/GradientEstimators.inl"
|
||||||
|
|
||||||
#endif //__PolyVox_GradientEstimators_H__
|
#endif //__PolyVox_GradientEstimators_H__
|
@ -24,7 +24,7 @@ freely, subject to the following restrictions:
|
|||||||
#ifndef __PolyVox_AStarPathfinderImpl_H__
|
#ifndef __PolyVox_AStarPathfinderImpl_H__
|
||||||
#define __PolyVox_AStarPathfinderImpl_H__
|
#define __PolyVox_AStarPathfinderImpl_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/Vector.h"
|
#include "PolyVox/Vector.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits> //For numeric_limits
|
#include <limits> //For numeric_limits
|
@ -24,9 +24,9 @@ freely, subject to the following restrictions:
|
|||||||
#ifndef __PolyVox_ErrorHandling_H__
|
#ifndef __PolyVox_ErrorHandling_H__
|
||||||
#define __PolyVox_ErrorHandling_H__
|
#define __PolyVox_ErrorHandling_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/Impl/Config.h"
|
#include "PolyVox/Impl/Config.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/Impl/Logging.h"
|
#include "PolyVox/Impl/Logging.h"
|
||||||
|
|
||||||
#include <cstdlib> // For std::exit
|
#include <cstdlib> // For std::exit
|
||||||
#include <iostream> // For std::cerr
|
#include <iostream> // For std::cerr
|
||||||
@ -155,8 +155,49 @@ freely, subject to the following restrictions:
|
|||||||
{
|
{
|
||||||
typedef void (*ThrowHandler)(std::exception& e, const char* file, int line);
|
typedef void (*ThrowHandler)(std::exception& e, const char* file, int line);
|
||||||
|
|
||||||
ThrowHandler getThrowHandler();
|
inline void defaultThrowHandler(std::exception& e, const char* file, int line)
|
||||||
void setThrowHandler(ThrowHandler newHandler);
|
{
|
||||||
|
std::stringstream ss; \
|
||||||
|
ss << "\n"; \
|
||||||
|
ss << " PolyVox exception thrown!"; \
|
||||||
|
ss << " ========================="; \
|
||||||
|
ss << " PolyVox has tried to throw an exception but it was built without support"; \
|
||||||
|
ss << " for exceptions. In this scenario PolyVox will call a 'throw handler'"; \
|
||||||
|
ss << " and this message is being printed by the default throw handler."; \
|
||||||
|
ss << "\n"; \
|
||||||
|
ss << " If you don't want to enable exceptions then you should try to determine why"; \
|
||||||
|
ss << " this exception was thrown and make sure it doesn't happen again. If it was"; \
|
||||||
|
ss << " due to something like an invalid argument to a function then you should be"; \
|
||||||
|
ss << " able to fix it quite easily by validating parameters as appropriate. More"; \
|
||||||
|
ss << " complex exception scenarios (out of memory, etc) might be harder to fix and"; \
|
||||||
|
ss << " you should replace this default handler with something which is more"; \
|
||||||
|
ss << " meaningful to your users."; \
|
||||||
|
ss << "\n"; \
|
||||||
|
ss << " Exception details"; \
|
||||||
|
ss << " -----------------"; \
|
||||||
|
ss << " Line: " << line; \
|
||||||
|
ss << " File: " << file; \
|
||||||
|
ss << " Message: " << e.what(); \
|
||||||
|
ss << "\n"; \
|
||||||
|
PolyVox::Impl::getLoggerInstance()->logFatalMessage(ss.str()); \
|
||||||
|
POLYVOX_HALT(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ThrowHandler& getThrowHandlerInstance()
|
||||||
|
{
|
||||||
|
static ThrowHandler s_fThrowHandler = &defaultThrowHandler;
|
||||||
|
return s_fThrowHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ThrowHandler getThrowHandler()
|
||||||
|
{
|
||||||
|
return getThrowHandlerInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setThrowHandler(ThrowHandler fNewHandler)
|
||||||
|
{
|
||||||
|
getThrowHandlerInstance() = fNewHandler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define POLYVOX_THROW_IF(condition, type, message) \
|
#define POLYVOX_THROW_IF(condition, type, message) \
|
@ -24,7 +24,7 @@ freely, subject to the following restrictions:
|
|||||||
#ifndef __PolyVox_Logging_H__
|
#ifndef __PolyVox_Logging_H__
|
||||||
#define __PolyVox_Logging_H__
|
#define __PolyVox_Logging_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/Impl/Config.h"
|
#include "PolyVox/Impl/Config.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -70,10 +70,17 @@ namespace PolyVox
|
|||||||
|
|
||||||
namespace Impl
|
namespace Impl
|
||||||
{
|
{
|
||||||
Logger*& getLoggerInstance();
|
inline Logger*& getLoggerInstance()
|
||||||
|
{
|
||||||
|
static Logger* s_pLogger = new DefaultLogger;
|
||||||
|
return s_pLogger;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLogger(Logger* pLogger);
|
inline void setLogger(Logger* pLogger)
|
||||||
|
{
|
||||||
|
Impl::getLoggerInstance() = pLogger;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef POLYVOX_LOG_TRACE_ENABLED
|
#ifdef POLYVOX_LOG_TRACE_ENABLED
|
335
include/PolyVox/Impl/MarchingCubesTables.h
Normal file
335
include/PolyVox/Impl/MarchingCubesTables.h
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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_MarchingCubeTables_H__
|
||||||
|
#define __PolyVox_MarchingCubeTables_H__
|
||||||
|
|
||||||
|
#include "PolyVox/Impl/TypeDef.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace PolyVox
|
||||||
|
{
|
||||||
|
//These tables were based on the article "Polygonising a scalar field".
|
||||||
|
//They have been optimised to allow a more efficient algorithm via bitwise operations.
|
||||||
|
|
||||||
|
// http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/index.html
|
||||||
|
|
||||||
|
const uint16_t edgeTable[256] =
|
||||||
|
{
|
||||||
|
0x000, 0x109, 0x203, 0x30a, 0x80c, 0x905, 0xa0f, 0xb06,
|
||||||
|
0x406, 0x50f, 0x605, 0x70c, 0xc0a, 0xd03, 0xe09, 0xf00,
|
||||||
|
0x190, 0x099, 0x393, 0x29a, 0x99c, 0x895, 0xb9f, 0xa96,
|
||||||
|
0x596, 0x49f, 0x795, 0x69c, 0xd9a, 0xc93, 0xf99, 0xe90,
|
||||||
|
0x230, 0x339, 0x033, 0x13a, 0xa3c, 0xb35, 0x83f, 0x936,
|
||||||
|
0x636, 0x73f, 0x435, 0x53c, 0xe3a, 0xf33, 0xc39, 0xd30,
|
||||||
|
0x3a0, 0x2a9, 0x1a3, 0x0aa, 0xbac, 0xaa5, 0x9af, 0x8a6,
|
||||||
|
0x7a6, 0x6af, 0x5a5, 0x4ac, 0xfaa, 0xea3, 0xda9, 0xca0,
|
||||||
|
0x8c0, 0x9c9, 0xac3, 0xbca, 0x0cc, 0x1c5, 0x2cf, 0x3c6,
|
||||||
|
0xcc6, 0xdcf, 0xec5, 0xfcc, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
|
||||||
|
0x950, 0x859, 0xb53, 0xa5a, 0x15c, 0x055, 0x35f, 0x256,
|
||||||
|
0xd56, 0xc5f, 0xf55, 0xe5c, 0x55a, 0x453, 0x759, 0x650,
|
||||||
|
0xaf0, 0xbf9, 0x8f3, 0x9fa, 0x2fc, 0x3f5, 0x0ff, 0x1f6,
|
||||||
|
0xef6, 0xfff, 0xcf5, 0xdfc, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
|
||||||
|
0xb60, 0xa69, 0x963, 0x86a, 0x36c, 0x265, 0x16f, 0x066,
|
||||||
|
0xf66, 0xe6f, 0xd65, 0xc6c, 0x76a, 0x663, 0x569, 0x460,
|
||||||
|
0x460, 0x569, 0x663, 0x76a, 0xc6c, 0xd65, 0xe6f, 0xf66,
|
||||||
|
0x066, 0x16f, 0x265, 0x36c, 0x86a, 0x963, 0xa69, 0xb60,
|
||||||
|
0x5f0, 0x4f9, 0x7f3, 0x6fa, 0xdfc, 0xcf5, 0xfff, 0xef6,
|
||||||
|
0x1f6, 0x0ff, 0x3f5, 0x2fc, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
|
||||||
|
0x650, 0x759, 0x453, 0x55a, 0xe5c, 0xf55, 0xc5f, 0xd56,
|
||||||
|
0x256, 0x35f, 0x055, 0x15c, 0xa5a, 0xb53, 0x859, 0x950,
|
||||||
|
0x7c0, 0x6c9, 0x5c3, 0x4ca, 0xfcc, 0xec5, 0xdcf, 0xcc6,
|
||||||
|
0x3c6, 0x2cf, 0x1c5, 0x0cc, 0xbca, 0xac3, 0x9c9, 0x8c0,
|
||||||
|
0xca0, 0xda9, 0xea3, 0xfaa, 0x4ac, 0x5a5, 0x6af, 0x7a6,
|
||||||
|
0x8a6, 0x9af, 0xaa5, 0xbac, 0x0aa, 0x1a3, 0x2a9, 0x3a0,
|
||||||
|
0xd30, 0xc39, 0xf33, 0xe3a, 0x53c, 0x435, 0x73f, 0x636,
|
||||||
|
0x936, 0x83f, 0xb35, 0xa3c, 0x13a, 0x033, 0x339, 0x230,
|
||||||
|
0xe90, 0xf99, 0xc93, 0xd9a, 0x69c, 0x795, 0x49f, 0x596,
|
||||||
|
0xa96, 0xb9f, 0x895, 0x99c, 0x29a, 0x393, 0x099, 0x190,
|
||||||
|
0xf00, 0xe09, 0xd03, 0xc0a, 0x70c, 0x605, 0x50f, 0x406,
|
||||||
|
0xb06, 0xa0f, 0x905, 0x80c, 0x30a, 0x203, 0x109, 0x000
|
||||||
|
};
|
||||||
|
|
||||||
|
const int8_t triTable[256][16] =
|
||||||
|
{
|
||||||
|
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1, },
|
||||||
|
{ 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1, },
|
||||||
|
{ 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1, },
|
||||||
|
{ 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1, },
|
||||||
|
{ 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1, },
|
||||||
|
{ 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1, },
|
||||||
|
{ 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1, },
|
||||||
|
{ 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1, },
|
||||||
|
{ 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1, },
|
||||||
|
{ 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1, },
|
||||||
|
{ 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1, },
|
||||||
|
{ 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1, },
|
||||||
|
{ 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1, },
|
||||||
|
{ 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1, },
|
||||||
|
{ 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1, },
|
||||||
|
{ 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1, },
|
||||||
|
{ 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1, },
|
||||||
|
{ 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1, },
|
||||||
|
{ 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1, },
|
||||||
|
{ 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1, },
|
||||||
|
{ 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1, },
|
||||||
|
{ 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1, },
|
||||||
|
{ 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1, },
|
||||||
|
{ 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1, },
|
||||||
|
{ 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1, },
|
||||||
|
{ 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1, },
|
||||||
|
{ 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1, },
|
||||||
|
{ 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1, },
|
||||||
|
{ 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1, },
|
||||||
|
{ 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1, },
|
||||||
|
{ 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1, },
|
||||||
|
{ 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1, },
|
||||||
|
{ 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1, },
|
||||||
|
{ 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1, },
|
||||||
|
{ 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1, },
|
||||||
|
{ 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1, },
|
||||||
|
{ 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1, },
|
||||||
|
{ 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1, },
|
||||||
|
{ 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1, },
|
||||||
|
{ 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1, },
|
||||||
|
{ 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1, },
|
||||||
|
{ 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1, },
|
||||||
|
{ 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1, },
|
||||||
|
{ 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1, },
|
||||||
|
{ 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1, },
|
||||||
|
{ 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1, },
|
||||||
|
{ 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1, },
|
||||||
|
{ 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1, },
|
||||||
|
{ 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1, },
|
||||||
|
{ 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1, },
|
||||||
|
{ 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1, },
|
||||||
|
{ 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1, },
|
||||||
|
{ 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, },
|
||||||
|
{ 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1, },
|
||||||
|
{ 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1, },
|
||||||
|
{ 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1, },
|
||||||
|
{ 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1, },
|
||||||
|
{ 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1, },
|
||||||
|
{ 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1, },
|
||||||
|
{ 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1, },
|
||||||
|
{ 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1, },
|
||||||
|
{ 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1, },
|
||||||
|
{ 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1, },
|
||||||
|
{ 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1, },
|
||||||
|
{ 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1, },
|
||||||
|
{ 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1, },
|
||||||
|
{ 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1, },
|
||||||
|
{ 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1, },
|
||||||
|
{ 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1, },
|
||||||
|
{ 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1, },
|
||||||
|
{ 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1, },
|
||||||
|
{ 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1, },
|
||||||
|
{ 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1, },
|
||||||
|
{ 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1, },
|
||||||
|
{ 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1, },
|
||||||
|
{ 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1, },
|
||||||
|
{ 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1, },
|
||||||
|
{ 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1, },
|
||||||
|
{ 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1, },
|
||||||
|
{ 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1, },
|
||||||
|
{ 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1, },
|
||||||
|
{ 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1, },
|
||||||
|
{ 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1, },
|
||||||
|
{ 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1, },
|
||||||
|
{ 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1, },
|
||||||
|
{ 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1, },
|
||||||
|
{ 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1, },
|
||||||
|
{ 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1, },
|
||||||
|
{ 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1, },
|
||||||
|
{ 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1, },
|
||||||
|
{ 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1, },
|
||||||
|
{ 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1, },
|
||||||
|
{ 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1, },
|
||||||
|
{ 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1, },
|
||||||
|
{ 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1, },
|
||||||
|
{ 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1, },
|
||||||
|
{ 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1, },
|
||||||
|
{ 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1, },
|
||||||
|
{ 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1, },
|
||||||
|
{ 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1, },
|
||||||
|
{ 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1, },
|
||||||
|
{ 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1, },
|
||||||
|
{ 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1, },
|
||||||
|
{ 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1, },
|
||||||
|
{ 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1, },
|
||||||
|
{ 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1, },
|
||||||
|
{ 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||||
|
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -21,11 +21,16 @@ freely, subject to the following restrictions:
|
|||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVoxCore/Impl/RandomUnitVectors.h"
|
#ifndef __PolyVox_RandomUnitVectors_H__
|
||||||
|
#define __PolyVox_RandomUnitVectors_H__
|
||||||
|
|
||||||
|
#include "PolyVox/Impl/TypeDef.h"
|
||||||
|
|
||||||
|
#include "PolyVox/Vector.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
extern const Vector3DFloat randomUnitVectors[1024] =
|
const Vector3DFloat randomUnitVectors[1024] =
|
||||||
{
|
{
|
||||||
Vector3DFloat(+0.339922f, +0.827727f, -0.446454f),
|
Vector3DFloat(+0.339922f, +0.827727f, -0.446454f),
|
||||||
Vector3DFloat(+0.084104f, -0.552666f, -0.829148f),
|
Vector3DFloat(+0.084104f, -0.552666f, -0.829148f),
|
||||||
@ -1053,3 +1058,5 @@ namespace PolyVox
|
|||||||
Vector3DFloat(-0.526640f, +0.820445f, +0.222533f)
|
Vector3DFloat(-0.526640f, +0.820445f, +0.222533f)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //__PolyVox_RandomUnitVectors_H__
|
@ -21,11 +21,16 @@ freely, subject to the following restrictions:
|
|||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVoxCore/Impl/RandomVectors.h"
|
#ifndef __PolyVox_RandomVectors_H__
|
||||||
|
#define __PolyVox_RandomVectors_H__
|
||||||
|
|
||||||
|
#include "PolyVox/Impl/TypeDef.h"
|
||||||
|
|
||||||
|
#include "PolyVox/Vector.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
extern const Vector3DFloat randomVectors[1024] =
|
const Vector3DFloat randomVectors[1024] =
|
||||||
{
|
{
|
||||||
Vector3DFloat(+0.348918f, -0.385662f, +0.650197f),
|
Vector3DFloat(+0.348918f, -0.385662f, +0.650197f),
|
||||||
Vector3DFloat(-0.259255f, +0.791559f, +0.920957f),
|
Vector3DFloat(-0.259255f, +0.791559f, +0.920957f),
|
||||||
@ -1053,3 +1058,5 @@ namespace PolyVox
|
|||||||
Vector3DFloat(-0.002289f, +0.568834f, -0.069185f)
|
Vector3DFloat(-0.002289f, +0.568834f, -0.069185f)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //__PolyVox_RandomVectors_H__
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user