Compare commits
No commits in common. "develop" and "hotfix/v0.2.1" have entirely different histories.
develop
...
hotfix/v0.
20
.gitattributes
vendored
20
.gitattributes
vendored
@ -1,20 +0,0 @@
|
|||||||
# 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
|
|
@ -1,81 +1,3 @@
|
|||||||
Changes for PolyVox version 0.3
|
|
||||||
===============================
|
|
||||||
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.
|
|
||||||
|
|
||||||
Voxel access
|
|
||||||
------------
|
|
||||||
The getVoxelAt() and setVoxelAt() functions have been deprecated and replaced by getVoxel() and setVoxel(). These new functions provide more control over how edge cases are handled and can potentially be faster as well. Please see the 'Volumes' section of the user manual for more information about how voxel access should be performed.
|
|
||||||
|
|
||||||
LargeVolume
|
|
||||||
-----------
|
|
||||||
Behaviour and interface of the LargeVolume has changed significantly and code which uses it will certainly need to be updated. Plese see the LargeVolume API docs for full details of how it now works.
|
|
||||||
|
|
||||||
It is now possible to provide custom compressors for the data which is stored in a LargeVolume. Two compressor implementation are provided with PolyVox - RLECompressor which is suitable for cubic-style terrain, and MinizCompressor which uses the 'miniz' zlib implementation for smooth terrain or general purpose use. Users can provide their own implementation of the compressor interface if they wish.
|
|
||||||
|
|
||||||
Note that the setCompressionEnabled() functionality has been removed and a compressor must always be provided when constructing the volume. The ability to disable compression was of questionable benefit and was complicating the logic in the code.
|
|
||||||
|
|
||||||
The LargeVolume also supports custom paging code which can be supplied by providing a subclass of Pager and implementing the relevant methods. This replaces the dataRequiredHandler() and dataOverflowHandler() functions.
|
|
||||||
|
|
||||||
These changes regarding compression and paging have also affected the LargeVolume constructors(s). Please see the API docs to see how they look now.
|
|
||||||
|
|
||||||
Error Handling
|
|
||||||
--------------
|
|
||||||
PolyVox now has it's own POLYVOX_ASSERT() macro rather than using the standard assert(). This has some advantages such as allowing a message to be printed and providing file/line information, and it is also possible to enable/disable it independantly of whether you are making a debug or release build.
|
|
||||||
|
|
||||||
A simple logging system has also been added, and the output can be redirected by user code.
|
|
||||||
|
|
||||||
Please see the 'Error Handling' section of the user manual for more information about these changes.
|
|
||||||
|
|
||||||
Volume wrap modes
|
|
||||||
-----------------
|
|
||||||
This release has seen a overhaul of the way PolyVox handles voxel positions which are outside of the volume. It used to be the case that you could specify a border value which would be returned whenever an out-of-volume access was performed, but this was not flexible enough for all use cases. You can now choose between different wrapping modes (border, clamp, etc) and apply them to both the volume itself or to samplers. If you have multiple samplers pointing at the same volume then you can choose to have different wrap modes for each of them.
|
|
||||||
|
|
||||||
Within the Volume class the getVoxelAt() and setBorderValue() functions have been deprecated. Please see the 'Volumes' section of the user manual for more information about how voxel access should now be performed.
|
|
||||||
|
|
||||||
Various algorithms have also been updated to allow wrap modes to be specified when executing them.
|
|
||||||
|
|
||||||
Region class
|
|
||||||
------------
|
|
||||||
The Region class has been tidied up and enhanced with new functionality. It now contains functions for growing and shrinking regions, as well as 'accumulate()' functions which ensure the Region contains a given point. The concept of an invalid region has also been introduced - this is one whose lower corner is greater than it's upper corner.
|
|
||||||
|
|
||||||
Vector class
|
|
||||||
------------
|
|
||||||
The Vector class has been tidied up. Most notably it now makes use of an 'OperationType' which is used for internal calculations and some results. The documentation has also been updated.
|
|
||||||
|
|
||||||
Deprecated functionality
|
|
||||||
------------------------
|
|
||||||
Vector::operator<() has been deprecated. It was only present to allow Vectors to be used as the key to an std::map, but it makes more sense for this to be specified seperatly as a std::map comparison function. This is now done in the OpenGLExample (search for VectorCompare).
|
|
||||||
|
|
||||||
getVoxelAt() and setBorderValue() have been deprecated in the Volume class. See the section of this file on 'Volume wrap modes' for details.
|
|
||||||
|
|
||||||
Removed functionality
|
|
||||||
--------------------
|
|
||||||
Functionality deprecated for the previous release has now been removed. This includes:
|
|
||||||
|
|
||||||
- Region::getWidth() and related functions. You should now use Region::getWidthInVoxels() or Region::getWidthInCells.
|
|
||||||
- The MeshDecimator. We don't have a direct replacement for this so you should consider an alternative such as downsampling the volume or using an external mesh processing library.
|
|
||||||
- The SimpleInterface. This was primarily for the bindings, and we are making other efforts to get those working.
|
|
||||||
- Serialisation. You should implement any required serialisation yourself.
|
|
||||||
- This had a number of problems and was a little too high-level for PolyVox. You should implement change tracking yourself.
|
|
||||||
|
|
||||||
|
|
||||||
Changes for PolyVox version 0.2
|
Changes for PolyVox version 0.2
|
||||||
===============================
|
===============================
|
||||||
This is the first revision for which we have produced a changelog, as we are now trying to streamline our development and release process. Hence this changelog entry is not going to be as structured as we hope they will be in the future. We're writing it from memory, rather than having carefully kept track of all the relevant changes as we made them.
|
This is the first revision for which we have produced a changelog, as we are now trying to streamline our development and release process. Hence this changelog entry is not going to be as structured as we hope they will be in the future. We're writing it from memory, rather than having carefully kept track of all the relevant changes as we made them.
|
||||||
|
106
CMakeLists.txt
106
CMakeLists.txt
@ -1,28 +1,26 @@
|
|||||||
################################################################################
|
# Copyright (c) 2007-2012 Matt Williams
|
||||||
# The MIT License (MIT)
|
# Copyright (c) 2007-2012 David Williams
|
||||||
#
|
#
|
||||||
# Copyright (c) 2015 Matthew Williams and 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 hereby granted, free of charge, to any person obtaining a copy
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# in the Software without restriction, including without limitation the rights
|
# freely, subject to the following restrictions:
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
#
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
# 1. The origin of this software must not be misrepresented; you must not
|
||||||
# copies or substantial portions of the Software.
|
# 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.
|
||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# misrepresented as being the original software.
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
#
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# 3. This notice may not be removed or altered from any source
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# distribution.
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.6)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3)
|
||||||
|
|
||||||
PROJECT(PolyVox)
|
PROJECT(PolyVox)
|
||||||
|
|
||||||
@ -35,19 +33,51 @@ MARK_AS_ADVANCED(FORCE POLYVOX_VERSION)
|
|||||||
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
|
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
|
|
||||||
IF(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") #Maybe "OR MINGW"
|
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_PROPERTY(CACHE LIBRARY_TYPE PROPERTY STRINGS DYNAMIC STATIC)
|
||||||
|
IF(WIN32)
|
||||||
|
SET(LIBRARY_TYPE "STATIC")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# 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})
|
||||||
|
if(CMAKE_VERSION VERSION_LESS "2.8.6")
|
||||||
|
set_package_info(Doxygen "API documentation generator" http://www.doxygen.org "Building the API documentation")
|
||||||
|
set_package_info(Qt4 "C++ framework" http://qt-project.org "Building the examples and tests")
|
||||||
|
else()
|
||||||
|
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")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(MSVC AND (MSVC_VERSION LESS 1600))
|
||||||
|
# Require boost for older (pre-vc2010) Visual Studio compilers
|
||||||
|
# See library/include/polyvoxcore/impl/TypeDef.h
|
||||||
|
find_package(Boost REQUIRED)
|
||||||
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
IF(CMAKE_COMPILER_IS_GNUCXX) #Maybe "OR MINGW"
|
||||||
ADD_DEFINITIONS(-std=c++0x) #Enable C++0x mode
|
ADD_DEFINITIONS(-std=c++0x) #Enable C++0x mode
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
if(CMAKE_CXX_COMPILER MATCHES "clang")
|
||||||
|
ADD_DEFINITIONS(-std=c++0x) #Enable C++0x mode
|
||||||
|
endif()
|
||||||
|
|
||||||
IF(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
ADD_SUBDIRECTORY(library)
|
||||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
ADD_SUBDIRECTORY(include)
|
|
||||||
|
|
||||||
OPTION(ENABLE_EXAMPLES "Should the examples be built" ON)
|
OPTION(ENABLE_EXAMPLES "Should the examples be built" ON)
|
||||||
IF(ENABLE_EXAMPLES)
|
IF(ENABLE_EXAMPLES AND QT_QTOPENGL_FOUND)
|
||||||
ADD_SUBDIRECTORY(examples)
|
ADD_SUBDIRECTORY(examples/Basic)
|
||||||
|
ADD_SUBDIRECTORY(examples/Paging)
|
||||||
|
ADD_SUBDIRECTORY(examples/OpenGL)
|
||||||
|
ADD_SUBDIRECTORY(examples/SmoothLOD)
|
||||||
|
SET(BUILD_EXAMPLES ON)
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(BUILD_EXAMPLES OFF)
|
SET(BUILD_EXAMPLES OFF)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
@ -55,22 +85,30 @@ ENDIF()
|
|||||||
INCLUDE(Packaging.cmake)
|
INCLUDE(Packaging.cmake)
|
||||||
|
|
||||||
OPTION(ENABLE_TESTS "Should the tests be built" ON)
|
OPTION(ENABLE_TESTS "Should the tests be built" ON)
|
||||||
IF(ENABLE_TESTS)
|
IF(ENABLE_TESTS AND QT_QTTEST_FOUND)
|
||||||
INCLUDE(CTest)
|
INCLUDE(CTest)
|
||||||
|
MARK_AS_ADVANCED(FORCE DART_TESTING_TIMEOUT) #This is only needed to hide the variable in the GUI (CMake bug) until 2.8.5
|
||||||
MARK_AS_ADVANCED(FORCE BUILD_TESTING)
|
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()
|
||||||
|
|
||||||
ADD_SUBDIRECTORY(documentation)
|
#Check if we will building _and_ bundling the docs
|
||||||
|
IF(DOXYGEN_FOUND AND QT_QCOLLECTIONGENERATOR_EXECUTABLE)
|
||||||
|
SET(BUILD_AND_BUNDLE_DOCS ON)
|
||||||
|
ELSE()
|
||||||
|
SET(BUILD_AND_BUNDLE_DOCS OFF)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
ADD_SUBDIRECTORY(bindings)
|
ADD_SUBDIRECTORY(documentation)
|
||||||
|
|
||||||
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")
|
||||||
add_feature_info("API docs" BUILD_DOCS "HTML documentation of the API")
|
add_feature_info("API docs" DOXYGEN_FOUND "HTML documentation of the API")
|
||||||
|
add_feature_info("Qt Help" BUILD_AND_BUNDLE_DOCS "API docs in Qt Help format")
|
||||||
add_feature_info("Manual" BUILD_MANUAL "HTML user's manual")
|
add_feature_info("Manual" BUILD_MANUAL "HTML user's manual")
|
||||||
|
|
||||||
feature_summary(WHAT ALL)
|
feature_summary(WHAT ALL)
|
||||||
@ -79,9 +117,11 @@ feature_summary(WHAT ALL)
|
|||||||
MESSAGE(STATUS "")
|
MESSAGE(STATUS "")
|
||||||
MESSAGE(STATUS "Summary")
|
MESSAGE(STATUS "Summary")
|
||||||
MESSAGE(STATUS "-------")
|
MESSAGE(STATUS "-------")
|
||||||
|
MESSAGE(STATUS "Library type: " ${LIBRARY_TYPE})
|
||||||
MESSAGE(STATUS "Build examples: " ${BUILD_EXAMPLES})
|
MESSAGE(STATUS "Build examples: " ${BUILD_EXAMPLES})
|
||||||
MESSAGE(STATUS "Build tests: " ${BUILD_TESTS})
|
MESSAGE(STATUS "Build tests: " ${BUILD_TESTS})
|
||||||
MESSAGE(STATUS "Build bindings: " ${BUILD_BINDINGS})
|
MESSAGE(STATUS "Build bindings: " ${BUILD_BINDINGS})
|
||||||
MESSAGE(STATUS "API Docs available: " ${BUILD_DOCS})
|
MESSAGE(STATUS "API Docs available: " ${DOXYGEN_FOUND})
|
||||||
|
MESSAGE(STATUS " - Qt Help bundling: " ${BUILD_AND_BUNDLE_DOCS})
|
||||||
MESSAGE(STATUS "Build manual: " ${BUILD_MANUAL})
|
MESSAGE(STATUS "Build manual: " ${BUILD_MANUAL})
|
||||||
MESSAGE(STATUS "")
|
MESSAGE(STATUS "")
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
David Williams - Lead programmer.
|
David Williams - Lead programmer.
|
||||||
Matthew Williams - Linux port, build system, support and maintenance.
|
Matthew Williams - Linux port, build system, support and maintenance.
|
||||||
Oliver Schneider - Very large Volumes
|
Oliver Schneider - Very large Volumes
|
||||||
|
|
||||||
Acknowledgements
|
|
||||||
----------------
|
|
||||||
PolyVox uses the 'miniz' for data compression. 'miniz' is public domain software and does not affect the license of PolyVox or of code using PolyVox. More details here: http://code.google.com/p/miniz/
|
|
@ -1,26 +1,23 @@
|
|||||||
################################################################################
|
# Copyright (c) 2010-2012 Matt Williams
|
||||||
# The MIT License (MIT)
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2015 Matthew Williams and 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 hereby granted, free of charge, to any person obtaining a copy
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# in the Software without restriction, including without limitation the rights
|
# freely, subject to the following restrictions:
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
#
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
# 1. The origin of this software must not be misrepresented; you must not
|
||||||
# copies or substantial portions of the Software.
|
# 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.
|
||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# misrepresented as being the original software.
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
#
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# 3. This notice may not be removed or altered from any source
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# distribution.
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
set(CTEST_PROJECT_NAME "PolyVox")
|
set(CTEST_PROJECT_NAME "PolyVox")
|
||||||
set(CTEST_NIGHTLY_START_TIME "00:00:00 GMT")
|
set(CTEST_NIGHTLY_START_TIME "00:00:00 GMT")
|
||||||
|
23
INSTALL.txt
23
INSTALL.txt
@ -2,31 +2,21 @@
|
|||||||
Building PolyVox
|
Building PolyVox
|
||||||
****************
|
****************
|
||||||
|
|
||||||
.. warning ::
|
|
||||||
Before reading this information, be aware that *you may not actually need to build PolyVox in order to use it*. PolyVox is a header-only library and in many cases it is sufficient to simply copy the ``include/PolyVox`` folder into your source tree. This folder contains all the PolyVox header files, and you can probably then include them directly with ``#include "PolyVox/SomeHeaderHere.h"`` without even needing to change your compiler search paths.
|
|
||||||
|
|
||||||
That said, you *will* need to read the instructions below if you want to build the examples, tests, bindings or documentation which may be helpful in getting you started with PolyVox.
|
|
||||||
|
|
||||||
Requirements
|
Requirements
|
||||||
============
|
============
|
||||||
|
|
||||||
To build PolyVox you need:
|
To build PolyVox you need:
|
||||||
|
|
||||||
* `CMake <http://cmake.org>`_ (tested on version 2.8.12.2, later versions should also work)
|
* `CMake <http://cmake.org>`_ 2.8.3 or greater
|
||||||
* A C++ compiler with support for some C++11 features (tested on GCC 4.8 and VC 2013)
|
* A C++ compiler with support for some C++0x features (GCC 4.3 or VC 2010 seem to work)
|
||||||
|
|
||||||
With the following optional packages:
|
With the following optional packages:
|
||||||
|
|
||||||
* `Qt version 5.2 of later <https://www.qt.io/>`_ for building the tests and the example applications
|
* `Qt <http://qt.nokia.com>`_ for building the tests and the example applications
|
||||||
* ``qcollectiongenerator`` which comes with Qt Assistant is used for bundling the docs for installation
|
* ``qcollectiongenerator`` which comes with Qt Assistant is used for bundling the docs for installation
|
||||||
* `Doxygen <http://doxygen.org>`_ for building the documentation. Version 1.5.7 is needed to build the Qt Assistant docs. 1.7.0 or greater is recommended
|
* `Doxygen <http://doxygen.org>`_ for building the documentation. Version 1.5.7 is needed to build the Qt Assistant docs. 1.7.0 or greater is recommended
|
||||||
* `Python <http://python.org>`_, `Sphinx <http://sphinx.pocoo.org>`_ and `PyParsing <http://pyparsing.wikispaces.com/>`_ for generating the PolyVox manual in HTML
|
* `Python <http://python.org>`_, `Sphinx <http://sphinx.pocoo.org>`_ and `PyParsing <http://pyparsing.wikispaces.com/>`_ for generating the PolyVox manual in HTML
|
||||||
* Version 2 required - see note below.
|
|
||||||
* `Python development libraries <http://python.org>`_, `SWIG <http://swig.org/>`_ for generating the Python bindings
|
* `Python development libraries <http://python.org>`_, `SWIG <http://swig.org/>`_ for generating the Python bindings
|
||||||
* Version 3 required - see note below.
|
|
||||||
|
|
||||||
.. note ::
|
|
||||||
Currently we use different versions of Python for generating the documentation (version 2) vs. building the bindings (version 3). However, it is unlikely that you as a user will want to build the documentation as it is available online, or you can view the source *.rst files directly. But if you do want to build both the documentation and the bindings yourself then you will need both versions of Python installed.
|
|
||||||
|
|
||||||
Linux
|
Linux
|
||||||
=====
|
=====
|
||||||
@ -61,6 +51,9 @@ The other available settings for PolyVox are:
|
|||||||
``ENABLE_BINDINGS`` (``ON`` or ``OFF``)
|
``ENABLE_BINDINGS`` (``ON`` or ``OFF``)
|
||||||
Should the Python bindings to PolyVox be built. This requires the Python development libraries and SWIG to be installed. Defaults to ``ON``.
|
Should the Python bindings to PolyVox be built. This requires the Python development libraries and SWIG to be installed. Defaults to ``ON``.
|
||||||
|
|
||||||
|
``LIBRARY_TYPE`` (``DYNAMIC`` or ``STATIC``)
|
||||||
|
Choose whether static (``.a``) or dynamic libraries (``.so``) should be built. On Linux ``DYNAMIC`` is the default and on Windows ``STATIC`` is the default.
|
||||||
|
|
||||||
``CMAKE_BUILD_TYPE`` (``Debug``, ``Release``, ``RelWithDebInfo`` or ``MinSizeRel``)
|
``CMAKE_BUILD_TYPE`` (``Debug``, ``Release``, ``RelWithDebInfo`` or ``MinSizeRel``)
|
||||||
String option to set the type of build. This will automatically set some compilation flags such as the optimisation level or define ``NDEBUG``.
|
String option to set the type of build. This will automatically set some compilation flags such as the optimisation level or define ``NDEBUG``.
|
||||||
|
|
||||||
@ -121,14 +114,14 @@ If you do not have Python and Sphinx installed and do not want to install them t
|
|||||||
Windows
|
Windows
|
||||||
=======
|
=======
|
||||||
|
|
||||||
The earlier information about the dependencies, CMake configuration variables and buildable targets is still valid for Windows, so look at the Linux build information in the section above. Then see the notes below on using the CMake GUI.
|
For information about the dependencies, CMake configuration variables and buildable targets look at the Linux build information in the section above.
|
||||||
|
|
||||||
CMake
|
CMake
|
||||||
-----
|
-----
|
||||||
|
|
||||||
You need CMake installed so get the binary distribution from `CMake.org <http://cmake.org/cmake/resources/software.html>`_. Install it and run the CMake GUI.
|
You need CMake installed so get the binary distribution from `CMake.org <http://cmake.org/cmake/resources/software.html>`_. Install it and run the CMake GUI.
|
||||||
|
|
||||||
Point the source directory to the PolyVox root directory (the directory holding the 'INSTALL.txt' file) and the build directory to the ``build`` subdirectory. Then, click the ``Configure`` button. Click through the dialog box that appears and once you've clicked ``Finish`` you should see text appearing in the bottom text area. Once this has finished, some options will appear in the top area. The purpose of these options in detailed in the Linux→CMake section above. Once you have set these options to what you please, click ``Configure`` again. If it completes without errors then you can click ``Generate`` which will generate your compilers project files in the build directory.
|
Point the source directory to the directory holding this file and the build directory to the ``build`` subdirectory. Then, click the ``Configure`` button. Click through the dialog box that appears and once you've clicked ``Finish`` you should see text appearing in the bottom text area. Once this has finished, some options will appear in the top area. The purpose of these options in detailed in the Linux→CMake section above. Once you have set these options to what you please, click ``Configure`` again. If it completes without errors then you can click ``Generate`` which will generate your compilers project files in the build directory.
|
||||||
|
|
||||||
Building
|
Building
|
||||||
--------
|
--------
|
||||||
|
20
LICENSE.TXT
Normal file
20
LICENSE.TXT
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
Copyright (c) 2005-2012 David Williams and Matthew 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.
|
21
LICENSE.txt
21
LICENSE.txt
@ -1,21 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2015 David Williams and Matthew Williams
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
@ -1,26 +1,23 @@
|
|||||||
################################################################################
|
# Copyright (c) 2009-2012 Matt Williams
|
||||||
# The MIT License (MIT)
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2015 Matthew Williams and 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 hereby granted, free of charge, to any person obtaining a copy
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# in the Software without restriction, including without limitation the rights
|
# freely, subject to the following restrictions:
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
#
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
# 1. The origin of this software must not be misrepresented; you must not
|
||||||
# copies or substantial portions of the Software.
|
# 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.
|
||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# misrepresented as being the original software.
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
#
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# 3. This notice may not be removed or altered from any source
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# distribution.
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
#INCLUDE(InstallRequiredSystemLibraries)
|
#INCLUDE(InstallRequiredSystemLibraries)
|
||||||
|
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
PolyVox - The voxel management and manipulation library
|
PolyVox - The voxel management and manipulation library
|
||||||
=======================================================
|
=======================================================
|
||||||
.. attention ::
|
PolyVox is the core technology which lies behind our games. It is a fast, lightweight C++ library for the storage and processing of volumetric (voxel-based) environments. It has applications in both games and medical/scientific visualisation, and is released under the terms of the `zlib license <http://www.tldrlegal.com/l/ZLIB>`_.
|
||||||
This system is no longer under active development. For more details please see this blog post: http://www.volumesoffun.com/wrapping-up-polyvox-development-to-focus-on-cubiquity-2/
|
|
||||||
|
|
||||||
PolyVox is the core technology which lies behind our games. It is a fast, lightweight C++ library for the storage and processing of volumetric (voxel-based) environments. It has applications in both games and medical/scientific visualisation, and is released under the terms of the `MIT license <https://www.tldrlegal.com/l/mit>`_.
|
|
||||||
|
|
||||||
PolyVox is a relatively low-level library, and you will need experience in C++ and computer graphics/shaders to use it effectively. It is designed to be easily integrated into existing applications and is independent of your chosen graphics API. For more details please see `this page <http://www.volumesoffun.com/polyvox-about/>`_ on our website.
|
PolyVox is a relatively low-level library, and you will need experience in C++ and computer graphics/shaders to use it effectively. It is designed to be easily integrated into existing applications and is independent of your chosen graphics API. For more details please see `this page <http://www.volumesoffun.com/polyvox-about/>`_ on our website.
|
@ -1,8 +0,0 @@
|
|||||||
%module SimpleVolume
|
|
||||||
%{
|
|
||||||
#include "BaseVolume.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "BaseVolume.h"
|
|
||||||
|
|
||||||
VOLUMETYPES(BaseVolume)
|
|
@ -1,9 +0,0 @@
|
|||||||
%module Block
|
|
||||||
%{
|
|
||||||
#include "Block.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "Block.h"
|
|
||||||
|
|
||||||
VOLUMETYPES(Block)
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
|||||||
%module BlockCompressor
|
|
||||||
%{
|
|
||||||
#include "BlockCompressor.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "BlockCompressor.h"
|
|
||||||
|
|
||||||
VOLUMETYPES(BlockCompressor)
|
|
@ -1,68 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# The MIT License (MIT)
|
|
||||||
#
|
|
||||||
# Copyright (c) 2015 Matthew Williams and David Williams
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
|
||||||
# in the Software without restriction, including without limitation the rights
|
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
|
||||||
# copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
option(ENABLE_BINDINGS "Build bindings" OFF) #Off by default
|
|
||||||
if(ENABLE_BINDINGS)
|
|
||||||
find_package(SWIG)
|
|
||||||
mark_as_advanced(SWIG_DIR SWIG_VERSION)
|
|
||||||
find_package(PythonLibs 3)
|
|
||||||
if(CMAKE_VERSION VERSION_LESS "2.8.6")
|
|
||||||
set_package_info(SWIG "Bindings generator" http://www.swig.org)
|
|
||||||
set_package_info(PythonLibs "Programming language" http://www.python.org)
|
|
||||||
else()
|
|
||||||
set_package_properties(SWIG PROPERTIES DESCRIPTION "Bindings generator" URL http://www.swig.org)
|
|
||||||
set_package_properties(PythonLibs PROPERTIES DESCRIPTION "Programming language" URL http://www.python.org)
|
|
||||||
endif()
|
|
||||||
if(SWIG_FOUND)
|
|
||||||
set(BUILD_BINDINGS ON CACHE BOOL "Will the bindings be built" FORCE)
|
|
||||||
include(${SWIG_USE_FILE})
|
|
||||||
|
|
||||||
set(CMAKE_SWIG_FLAGS "")
|
|
||||||
set_source_files_properties(PolyVoxCore.i PROPERTIES CPLUSPLUS ON)
|
|
||||||
|
|
||||||
include_directories(${PolyVoxHeaders_SOURCE_DIR} ${PolyVoxHeaders_SOURCE_DIR}/PolyVox)
|
|
||||||
if(PYTHONLIBS_FOUND)
|
|
||||||
include_directories(${PYTHON_INCLUDE_PATH})
|
|
||||||
link_directories(${PolyVoxCore_BINARY_DIR})
|
|
||||||
|
|
||||||
#set_source_files_properties(PolyVoxCore.i PROPERTIES SWIG_FLAGS "-builtin")
|
|
||||||
set(SWIG_MODULE_PolyVoxCorePython_EXTRA_FLAGS "-py3")
|
|
||||||
swig_add_module(PolyVoxCorePython python PolyVoxCore.i)
|
|
||||||
swig_link_libraries(PolyVoxCorePython ${PYTHON_LIBRARIES})
|
|
||||||
set_target_properties(${SWIG_MODULE_PolyVoxCorePython_REAL_NAME} PROPERTIES OUTPUT_NAME _PolyVoxCore)
|
|
||||||
#set_target_properties(${SWIG_MODULE_PolyVoxCore_REAL_NAME} PROPERTIES SUFFIX ".pyd")
|
|
||||||
SET_PROPERTY(TARGET ${SWIG_MODULE_PolyVoxCorePython_REAL_NAME} PROPERTY FOLDER "Bindings")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(SWIG_MODULE_PolyVoxCoreCSharp_EXTRA_FLAGS "-dllimport;PolyVoxCoreCSharp") #This _should_ be inside UseSWIG.cmake - http://www.cmake.org/Bug/view.php?id=13814
|
|
||||||
swig_add_module(PolyVoxCoreCSharp csharp PolyVoxCore.i)
|
|
||||||
swig_link_libraries(PolyVoxCoreCSharp)
|
|
||||||
SET_PROPERTY(TARGET ${SWIG_MODULE_PolyVoxCoreCSharp_REAL_NAME} PROPERTY FOLDER "Bindings")
|
|
||||||
else()
|
|
||||||
set(BUILD_BINDINGS OFF CACHE BOOL "Will the bindings be built" FORCE)
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(BUILD_BINDINGS OFF CACHE BOOL "Will the bindings be built" FORCE)
|
|
||||||
endif()
|
|
||||||
mark_as_advanced(FORCE BUILD_BINDINGS)
|
|
@ -1,9 +0,0 @@
|
|||||||
%module Chunk
|
|
||||||
%{
|
|
||||||
#include "Chunk.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "Chunk.h"
|
|
||||||
|
|
||||||
VOLUMETYPES(Chunk)
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
|||||||
%module CompressedBlock
|
|
||||||
%{
|
|
||||||
#include "CompressedBlock.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "CompressedBlock.h"
|
|
||||||
|
|
||||||
VOLUMETYPES(CompressedBlock)
|
|
@ -1,9 +0,0 @@
|
|||||||
%module CubicSurfaceExtractor
|
|
||||||
%{
|
|
||||||
#include "CubicSurfaceExtractor.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "CubicSurfaceExtractor.h"
|
|
||||||
|
|
||||||
%template(extractCubicMeshSimpleVolumeuint8) extractCubicMesh<PolyVox::PagedVolume<uint8_t> >;
|
|
||||||
//EXTRACTORS(CubicSurfaceExtractor)
|
|
@ -1,8 +0,0 @@
|
|||||||
%module CubicSurfaceExtractorWithNormals
|
|
||||||
%{
|
|
||||||
#include "CubicSurfaceExtractorWithNormals.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "CubicSurfaceExtractorWithNormals.h"
|
|
||||||
|
|
||||||
%template(CubicSurfaceExtractorWithNormalsSimpleVolumeuint8) PolyVox::CubicSurfaceExtractorWithNormals<PolyVox::SimpleVolume<uint8_t>, PolyVox::DefaultIsQuadNeeded<uint8_t> >;
|
|
@ -1,6 +0,0 @@
|
|||||||
%module FilePager
|
|
||||||
%{
|
|
||||||
#include "FilePager.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "FilePager.h"
|
|
@ -1,8 +0,0 @@
|
|||||||
%module LargeVolume
|
|
||||||
%{
|
|
||||||
#include "LargeVolume.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "LargeVolume.h"
|
|
||||||
|
|
||||||
VOLUMETYPES(LargeVolume)
|
|
@ -1,8 +0,0 @@
|
|||||||
%module MarchingCubesSurfaceExtractor
|
|
||||||
%{
|
|
||||||
#include "MarchingCubesSurfaceExtractor.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "MarchingCubesSurfaceExtractor.h"
|
|
||||||
|
|
||||||
EXTRACTORS(MarchingCubesSurfaceExtractor)
|
|
@ -1,6 +0,0 @@
|
|||||||
%module MinizBlockCompressor
|
|
||||||
%{
|
|
||||||
#include "MinizBlockCompressor.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "MinizBlockCompressor.h"
|
|
@ -1,50 +0,0 @@
|
|||||||
%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)
|
|
@ -1,6 +0,0 @@
|
|||||||
%module Pager
|
|
||||||
%{
|
|
||||||
#include "Pager.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "Pager.h"
|
|
@ -1,8 +0,0 @@
|
|||||||
%module Picking
|
|
||||||
%{
|
|
||||||
#include "Picking.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "Picking.h"
|
|
||||||
|
|
||||||
EXTRACTORS(pickVoxel)
|
|
@ -1,93 +0,0 @@
|
|||||||
%module PolyVoxCore
|
|
||||||
|
|
||||||
#define POLYVOX_API
|
|
||||||
%include "Impl/PlatformDefinitions.h"
|
|
||||||
#define __attribute__(x) //Silence DEPRECATED errors
|
|
||||||
|
|
||||||
//This macro allows us to use Python properties on our classes
|
|
||||||
%define PROPERTY(type,name,getter,setter)
|
|
||||||
%extend type {
|
|
||||||
%pythoncode %{
|
|
||||||
__swig_getmethods__["name"] = getter
|
|
||||||
__swig_setmethods__["name"] = setter
|
|
||||||
if _newclass: name = property(getter, setter)
|
|
||||||
%}
|
|
||||||
};
|
|
||||||
%enddef
|
|
||||||
|
|
||||||
//Put this in an %extend section to wrap operator<< as __str__
|
|
||||||
%define STR()
|
|
||||||
const char* __str__() {
|
|
||||||
std::ostringstream out;
|
|
||||||
out << *$self;
|
|
||||||
return out.str().c_str();
|
|
||||||
}
|
|
||||||
%enddef
|
|
||||||
|
|
||||||
//Centralise this to avoid repeating ourselves
|
|
||||||
//This macro will be called in the volume interface files to define the various volume types.
|
|
||||||
%define VOLUMETYPES(class)
|
|
||||||
%template(class ## int8) PolyVox::class<int8_t>;
|
|
||||||
//%template(class ## int16) PolyVox::class<int16_t>;
|
|
||||||
//%template(class ## int32) PolyVox::class<int32_t>;
|
|
||||||
//%template(class ## uint8) PolyVox::class<uint8_t>;
|
|
||||||
//%template(class ## uint16) PolyVox::class<uint16_t>;
|
|
||||||
//%template(class ## uint32) PolyVox::class<uint32_t>;
|
|
||||||
//%template(class ## float) PolyVox::class<float>;
|
|
||||||
%enddef
|
|
||||||
|
|
||||||
//Template based on voxel type
|
|
||||||
%define EXTRACTOR(class, volumetype)
|
|
||||||
%template(class ## volumetype ## int8) PolyVox::class<PolyVox::volumetype<int8_t> >;
|
|
||||||
//%template(class ## volumetype ## int16) PolyVox::class<PolyVox::volumetype<int16_t> >;
|
|
||||||
//%template(class ## volumetype ## int32) PolyVox::class<PolyVox::volumetype<int32_t> >;
|
|
||||||
//%template(class ## volumetype ## uint8) PolyVox::class<PolyVox::volumetype<uint8_t> >;
|
|
||||||
//%template(class ## volumetype ## uint16) PolyVox::class<PolyVox::volumetype<uint16_t> >;
|
|
||||||
//%template(class ## volumetype ## uint32) PolyVox::class<PolyVox::volumetype<uint32_t> >;
|
|
||||||
//%template(class ## volumetype ## float) PolyVox::class<PolyVox::volumetype<float> >;
|
|
||||||
%enddef
|
|
||||||
|
|
||||||
//Template based on volume type
|
|
||||||
%define EXTRACTORS(shortname)
|
|
||||||
EXTRACTOR(shortname, PagedVolume)
|
|
||||||
EXTRACTOR(shortname, RawVolume)
|
|
||||||
%enddef
|
|
||||||
|
|
||||||
%feature("autodoc", "1");
|
|
||||||
|
|
||||||
#ifdef SWIGPYTHON
|
|
||||||
//This will rename "operator=" to "assign" since Python doesn't have assignment
|
|
||||||
%rename(assign) *::operator=;
|
|
||||||
#endif
|
|
||||||
#ifdef SWIGCSHARP
|
|
||||||
//These operators are not wrappable in C# and their function is provided by other means
|
|
||||||
%ignore *::operator=;
|
|
||||||
%ignore *::operator+=;
|
|
||||||
%ignore *::operator-=;
|
|
||||||
%ignore *::operator*=;
|
|
||||||
%ignore *::operator/=;
|
|
||||||
%ignore *::operator<<; //This is covered by STR()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
%include "stdint.i"
|
|
||||||
%include "std_vector.i"
|
|
||||||
%include "Vector.i"
|
|
||||||
%include "DefaultMarchingCubesController.i"
|
|
||||||
%include "Region.i"
|
|
||||||
//%include "Chunk.i"
|
|
||||||
//%include "CompressedBlock.i"
|
|
||||||
//%include "UncompressedBlock.i"
|
|
||||||
//%include "BlockCompressor.i"
|
|
||||||
//%include "Pager.i"
|
|
||||||
//%include "FilePager.i"
|
|
||||||
//%include "MinizBlockCompressor.i"
|
|
||||||
//%include "RLEBlockCompressor.i"
|
|
||||||
%include "BaseVolume.i"
|
|
||||||
//%include "RawVolume.i"
|
|
||||||
//%include "PagedVolume.i"
|
|
||||||
//%include "VertexTypes.i"
|
|
||||||
//%include "SurfaceMesh.i"
|
|
||||||
////%include "MarchingCubesSurfaceExtractor.i"
|
|
||||||
////%include "CubicSurfaceExtractor.i"
|
|
||||||
//%include "Raycast.i"
|
|
||||||
//%include "Picking.i"
|
|
@ -1,6 +0,0 @@
|
|||||||
%module RLEBlockCompressor
|
|
||||||
%{
|
|
||||||
#include "RLEBlockCompressor.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "RLEBlockCompressor.h"
|
|
@ -1,8 +0,0 @@
|
|||||||
%module RawVolume
|
|
||||||
%{
|
|
||||||
#include "RawVolume.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "RawVolume.h"
|
|
||||||
|
|
||||||
VOLUMETYPES(RawVolume)
|
|
@ -1,61 +0,0 @@
|
|||||||
%module Raycast
|
|
||||||
%{
|
|
||||||
#include "Raycast.h"
|
|
||||||
|
|
||||||
#ifdef SWIGPYTHON
|
|
||||||
|
|
||||||
template<typename VolumeType>
|
|
||||||
class PyCallback
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
PyObject *func;
|
|
||||||
PyCallback& operator=(const PyCallback&); // Not allowed
|
|
||||||
public:
|
|
||||||
PyCallback(const PyCallback& o) : func(o.func)
|
|
||||||
{
|
|
||||||
Py_XINCREF(func);
|
|
||||||
}
|
|
||||||
PyCallback(PyObject *func) : func(func)
|
|
||||||
{
|
|
||||||
Py_XINCREF(this->func);
|
|
||||||
assert(PyCallable_Check(this->func));
|
|
||||||
}
|
|
||||||
~PyCallback()
|
|
||||||
{
|
|
||||||
Py_XDECREF(func);
|
|
||||||
}
|
|
||||||
bool operator()(const typename VolumeType::Sampler& sampler)
|
|
||||||
{
|
|
||||||
if (!func || Py_None == func || !PyCallable_Check(func))
|
|
||||||
{
|
|
||||||
return false; //Make this raise a Python exception
|
|
||||||
}
|
|
||||||
PyObject *args = Py_BuildValue("(l)", sampler.getVoxel()); //TODO pass the sampler object itself in
|
|
||||||
PyObject *result = PyObject_Call(func,args,0);
|
|
||||||
Py_DECREF(args);
|
|
||||||
Py_XDECREF(result);
|
|
||||||
return (PyInt_AsLong(result) == 0) ? false : true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename VolumeType, typename Callback>
|
|
||||||
PolyVox::RaycastResult raycastWithEndpointsPython(VolumeType* volData, const PolyVox::Vector3DFloat& v3dStart, const PolyVox::Vector3DFloat& v3dEnd, PyObject *callback)
|
|
||||||
{
|
|
||||||
PyCallback<VolumeType> newCallback(callback);
|
|
||||||
return PolyVox::raycastWithEndpoints(volData, v3dStart, v3dEnd, newCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "Raycast.h"
|
|
||||||
|
|
||||||
#ifdef SWIGPYTHON
|
|
||||||
|
|
||||||
template<typename VolumeType, typename Callback>
|
|
||||||
PolyVox::RaycastResult raycastWithEndpointsPython(VolumeType* volData, const PolyVox::Vector3DFloat& v3dStart, const PolyVox::Vector3DFloat& v3dEnd, PyObject *callback);
|
|
||||||
|
|
||||||
%template(raycastWithEndpointsSimpleVolumeuint8) raycastWithEndpointsPython<PolyVox::SimpleVolume<uint8_t>, PyCallback<PolyVox::SimpleVolume<uint8_t> > >;
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,8 +0,0 @@
|
|||||||
%module SimpleVolume
|
|
||||||
%{
|
|
||||||
#include "SimpleVolume.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "SimpleVolume.h"
|
|
||||||
|
|
||||||
VOLUMETYPES(SimpleVolume)
|
|
@ -1,20 +0,0 @@
|
|||||||
%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 >;
|
|
@ -1,8 +0,0 @@
|
|||||||
%module UncompressedBlock
|
|
||||||
%{
|
|
||||||
#include "UncompressedBlock.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "UncompressedBlock.h"
|
|
||||||
|
|
||||||
VOLUMETYPES(UncompressedBlock)
|
|
@ -1,121 +0,0 @@
|
|||||||
%module Vector
|
|
||||||
%{
|
|
||||||
#include "Vector.h"
|
|
||||||
#include <sstream>
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "Vector.h"
|
|
||||||
|
|
||||||
#ifdef SWIGPYTHON
|
|
||||||
PROPERTY(PolyVox::Vector, x, getX, setX)
|
|
||||||
PROPERTY(PolyVox::Vector, y, getY, setY)
|
|
||||||
PROPERTY(PolyVox::Vector, z, getZ, setZ)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
%rename(Plus) operator +;
|
|
||||||
%rename(Minus) operator -;
|
|
||||||
%rename(Multiply) operator *;
|
|
||||||
%rename(Divide) operator /;
|
|
||||||
%rename(Equal) operator ==;
|
|
||||||
%rename(NotEqual) operator !=;
|
|
||||||
|
|
||||||
%extend PolyVox::Vector {
|
|
||||||
#ifdef SWIGPYTHON
|
|
||||||
PolyVox::Vector __add__(const PolyVox::Vector& rhs) {
|
|
||||||
return *$self + rhs;
|
|
||||||
}
|
|
||||||
PolyVox::Vector __sub__(const PolyVox::Vector& rhs) {
|
|
||||||
return *$self - rhs;
|
|
||||||
}
|
|
||||||
PolyVox::Vector __div__(const PolyVox::Vector& rhs) {
|
|
||||||
return *$self / rhs;
|
|
||||||
}
|
|
||||||
PolyVox::Vector __div__(const StorageType& rhs) {
|
|
||||||
return *$self / rhs;
|
|
||||||
}
|
|
||||||
PolyVox::Vector __mul__(const PolyVox::Vector& rhs) {
|
|
||||||
return *$self * rhs;
|
|
||||||
}
|
|
||||||
PolyVox::Vector __mul__(const StorageType& rhs) {
|
|
||||||
return *$self * rhs;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
STR()
|
|
||||||
};
|
|
||||||
|
|
||||||
%feature("pythonprepend") PolyVox::Vector::operator< %{
|
|
||||||
import warnings
|
|
||||||
warnings.warn("deprecated", DeprecationWarning)
|
|
||||||
%}
|
|
||||||
|
|
||||||
//%csattributes PolyVox::Vector::operator< "[System.Obsolete(\"deprecated\")]"
|
|
||||||
|
|
||||||
%define VECTOR3(StorageType,OperationType,ReducedStorageType)
|
|
||||||
#if SWIGCSHARP
|
|
||||||
%extend PolyVox::Vector<3,StorageType,OperationType> {
|
|
||||||
PolyVox::Vector<3,StorageType,OperationType> operator+(const PolyVox::Vector<3,StorageType,OperationType>& rhs) {return *$self + rhs;}
|
|
||||||
PolyVox::Vector<3,StorageType,OperationType> operator-(const PolyVox::Vector<3,StorageType,OperationType>& rhs) {return *$self - rhs;}
|
|
||||||
PolyVox::Vector<3,StorageType,OperationType> operator*(const PolyVox::Vector<3,StorageType,OperationType>& rhs) {return *$self * rhs;}
|
|
||||||
PolyVox::Vector<3,StorageType,OperationType> operator/(const PolyVox::Vector<3,StorageType,OperationType>& rhs) {return *$self / rhs;}
|
|
||||||
PolyVox::Vector<3,StorageType,OperationType> operator*(const StorageType& rhs) {return *$self * rhs;}
|
|
||||||
PolyVox::Vector<3,StorageType,OperationType> operator/(const StorageType& rhs) {return *$self / rhs;}
|
|
||||||
};
|
|
||||||
%typemap(cscode) PolyVox::Vector<3,StorageType,OperationType> %{
|
|
||||||
public static Vector3D##StorageType operator+(Vector3D##StorageType lhs, Vector3D##StorageType rhs) {
|
|
||||||
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
|
||||||
newVec = lhs.Plus(rhs);
|
|
||||||
return newVec;
|
|
||||||
}
|
|
||||||
public static Vector3D##StorageType operator-(Vector3D##StorageType lhs, Vector3D##StorageType rhs) {
|
|
||||||
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
|
||||||
newVec = lhs.Minus(rhs);
|
|
||||||
return newVec;
|
|
||||||
}
|
|
||||||
public static Vector3D##StorageType operator*(Vector3D##StorageType lhs, Vector3D##StorageType rhs) {
|
|
||||||
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
|
||||||
newVec = lhs.Multiply(rhs);
|
|
||||||
return newVec;
|
|
||||||
}
|
|
||||||
public static Vector3D##StorageType operator/(Vector3D##StorageType lhs, Vector3D##StorageType rhs) {
|
|
||||||
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
|
||||||
newVec = lhs.Divide(rhs);
|
|
||||||
return newVec;
|
|
||||||
}
|
|
||||||
public static Vector3D##StorageType operator*(Vector3D##StorageType lhs, $typemap(cstype, StorageType) rhs) {
|
|
||||||
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
|
||||||
newVec = lhs.Multiply(rhs);
|
|
||||||
return newVec;
|
|
||||||
}
|
|
||||||
public static Vector3D##StorageType operator/(Vector3D##StorageType lhs, $typemap(cstype, StorageType) rhs) {
|
|
||||||
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
|
||||||
newVec = lhs.Divide(rhs);
|
|
||||||
return newVec;
|
|
||||||
}
|
|
||||||
public bool Equals(Vector3D##StorageType rhs) {
|
|
||||||
if ((object)rhs == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return Equal(rhs);
|
|
||||||
}
|
|
||||||
%}
|
|
||||||
%ignore PolyVox::Vector<3,StorageType,OperationType>::operator<; //This is deprecated
|
|
||||||
#endif
|
|
||||||
%ignore PolyVox::Vector<3,StorageType,OperationType>::Vector(ReducedStorageType,ReducedStorageType,ReducedStorageType,ReducedStorageType);
|
|
||||||
%ignore PolyVox::Vector<3,StorageType,OperationType>::Vector(ReducedStorageType,ReducedStorageType);
|
|
||||||
%ignore PolyVox::Vector<3,StorageType,OperationType>::getW() const;
|
|
||||||
%ignore PolyVox::Vector<3,StorageType,OperationType>::setW(ReducedStorageType);
|
|
||||||
%ignore PolyVox::Vector<3,StorageType,OperationType>::setElements(ReducedStorageType,ReducedStorageType,ReducedStorageType,ReducedStorageType);
|
|
||||||
%template(Vector3D ## StorageType) PolyVox::Vector<3,StorageType,OperationType>;
|
|
||||||
%enddef
|
|
||||||
|
|
||||||
VECTOR3(float,float,float)
|
|
||||||
VECTOR3(double,double,double)
|
|
||||||
VECTOR3(int8_t,int32_t,signed char)
|
|
||||||
VECTOR3(uint8_t,int32_t,unsigned char)
|
|
||||||
VECTOR3(int16_t,int32_t,signed short)
|
|
||||||
VECTOR3(uint16_t,int32_t,unsigned short)
|
|
||||||
VECTOR3(int32_t,int32_t,signed int)
|
|
||||||
VECTOR3(uint32_t,int32_t,unsigned int)
|
|
||||||
|
|
||||||
//%rename(assign) Vector3DFloat::operator=;
|
|
@ -1,26 +1,23 @@
|
|||||||
################################################################################
|
# Copyright (c) 2010-2012 Matt Williams
|
||||||
# The MIT License (MIT)
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2015 Matthew Williams and 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 hereby granted, free of charge, to any person obtaining a copy
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# in the Software without restriction, including without limitation the rights
|
# freely, subject to the following restrictions:
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
#
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
# 1. The origin of this software must not be misrepresented; you must not
|
||||||
# copies or substantial portions of the Software.
|
# 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.
|
||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# misrepresented as being the original software.
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
#
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# 3. This notice may not be removed or altered from any source
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# distribution.
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
find_program(SPHINXBUILD_EXECUTABLE sphinx-build DOC "The location of the sphinx-build executable")
|
find_program(SPHINXBUILD_EXECUTABLE sphinx-build DOC "The location of the sphinx-build executable")
|
||||||
|
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
**************
|
|
||||||
Error Handling
|
|
||||||
**************
|
|
||||||
PolyVox includes a number of error handling features designed to help you identify and/or recover from problematic scenarios. This document describes these features and how they affect you as a user of the library.
|
|
||||||
|
|
||||||
Logging
|
|
||||||
=======
|
|
||||||
PolyVox has a simple logging mechanism which allows it to write messages with an associated severity (from Debug up to Fatal). This logging mechanism is not really intended for use by client code (i.e. calling the logging macros from your own application) but you can of course do so at your own risk. However, it is possible to redirect the output of these logging functions so you can integrate them with your application's logging framework or suppress them completely.
|
|
||||||
|
|
||||||
Fatal messages are only issued in non-recoverable scenarios when the application is about to crash, and may provide the last piece of information you have about what went wrong. Error messages are issued when something has happened which prevents successful completion of a task, for example if you provide invalid parameters to a function (error messages are also issued whenever an exception is thrown). Warning messages mean the system was able to continue but the results may not be what you expected. Info messages are used for general information about what PolyVox is doing. Debug and trace messages produce very verbose output and a lot of detail about what PolyVox is doing internally. In general, debug messages are used for tasks the user has directly initiated (e.g. they might provide timing information for surface extraction) while trace messages are used for things which happen spontaneously (such as data being paged out of memory).
|
|
||||||
|
|
||||||
To redirect log messages you can subclass Logger, create an instance, and set it as active as follows:
|
|
||||||
|
|
||||||
.. sourcecode :: c++
|
|
||||||
|
|
||||||
class CustomLogger : public Logger
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CustomLogger() : Logger() {}
|
|
||||||
virtual ~CustomLogger() {}
|
|
||||||
|
|
||||||
void logTraceMessage(const std::string& message) { /* Do something with the message */ }
|
|
||||||
void logDebugMessage(const std::string& message) { /* Do something with the message */ }
|
|
||||||
void logInfoMessage(const std::string& message) { /* Do something with the message */ }
|
|
||||||
void logWarningMessage(const std::string& message) { /* Do something with the message */ }
|
|
||||||
void logErrorMessage(const std::string& message) { /* Do something with the message */ }
|
|
||||||
void logFatalMessage(const std::string& message) { /* Do something with the message */ }
|
|
||||||
};
|
|
||||||
|
|
||||||
CustomLogger* myCustomLogger = new CustomLogger();
|
|
||||||
|
|
||||||
setLogger(myCustomLogger);
|
|
||||||
|
|
||||||
Note that the default implementation (DefaultLogger) sends the fatal, error and warning streams to std::cerr, the info stream to std:cout, and that the debug and trace streams are suppressed.
|
|
||||||
|
|
||||||
PolyVox logging can be disabled completely in Config.h by undefining POLYVOX_LOG_TRACE_ENABLED through to POLYVOX_LOG_FATAL_ENABLED. Each of these can be disabled individually and the corresponding code will then be completely stripped from PolyVox. This is a compile-time setting - if you wish to change the log level at run-time then in your own implementation you could implement a filtering mechanism which only does something with the messages if some 'log severity' setting is greater than a certain threshold which can be changed at runtime.
|
|
||||||
|
|
||||||
Exceptions
|
|
||||||
==========
|
|
||||||
Error handling in PolyVox is provided by using the C++ exception mechanism. Exceptions can be thrown for a variety of reasons and your code should be prepared to handle them to prevent your application from crashing. It is possible to disable the throwing of exceptions if they are not supported by your compiler.
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
Most functions in PolyVox will validate their input parameters and throw an exception if the provided values do not meet the function's requirements (which should be specified in the API documentation). However, in certain performance critical cases we choose not to spend time validating the parameters and an exception will not be thrown, though we do still use an assertion if these are enabled.
|
|
||||||
|
|
||||||
The most notable example of this is when accessing volume data through the get/setVoxel() functions, as these are designed to be very fast. Validating an input position would require multiple conditional operations which we chose to avoid. Therefore, **accessing a voxel outside of a volume will cause undefined behaviour.**
|
|
||||||
|
|
||||||
Disabling exceptions
|
|
||||||
--------------------
|
|
||||||
Some platforms may not support the use of C++ exceptions (older Android SDKs are the only place we have seen this) so you may need to disable them completely. This is highly undesirable but you may have no choice. To do this you should undefine 'POLYVOX_THROW_ENABLED' in Config.h (we may expose this through CMake in the future).
|
|
||||||
|
|
||||||
If exceptions are disabled then PolyVox will call a 'ThrowHandler' instead of throwing an exception. This is defined as follows:
|
|
||||||
|
|
||||||
.. sourcecode :: c++
|
|
||||||
|
|
||||||
typedef void (*ThrowHandler)(std::exception& e, const char* file, int line);
|
|
||||||
|
|
||||||
The default throw handler will print an error and then terminate, but you can provide a custom throw handler matching the function definition above:
|
|
||||||
|
|
||||||
.. sourcecode :: c++
|
|
||||||
|
|
||||||
setThrowHandler(&myThrowHandler);
|
|
||||||
|
|
||||||
Asserts
|
|
||||||
=======
|
|
||||||
In addition to the C++ exception handling mechanism, PolyVox also makes use of assertions to verify the internal state of the library at various points. This functionality is provided by out own POLYVOX_ASSERT() macro rather than the standard C++ assert() as this has a number of advantages described `here <http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/>`_.
|
|
||||||
|
|
||||||
Assertions inside PolyVox are enabled by defining 'POLYVOX_ASSERTS_ENABLED' in Config.h and again we may expose this through CMake. Note that the presence of assertions is independant of whether you are building a debug or release version of your application.
|
|
||||||
|
|
||||||
As a user you are not really expected to encounter an assertion inside PolyVox - they are mostly there for our purposes as developers of the library. So if you hit one in PolyVox then there is a good chance it is a bug in the library, as user errors should have been prevented by throwing an exceptions. Again, there are exceptions to this rule as some speed-critical functions (getVoxel(), etc) do not validate their parameters.
|
|
@ -12,7 +12,7 @@ PolyVox volumes make it easy to access these neighbours, but the situation gets
|
|||||||
|
|
||||||
Having established that edge cases can be problematic, we can now see that storing your data as a set of adjacent volumes is undesirable because these edge cases then exist throughout the data set. This causes a lot of problems such as gaps between pieces of extracted terrain or discontinuities in the computed normals.
|
Having established that edge cases can be problematic, we can now see that storing your data as a set of adjacent volumes is undesirable because these edge cases then exist throughout the data set. This causes a lot of problems such as gaps between pieces of extracted terrain or discontinuities in the computed normals.
|
||||||
|
|
||||||
The usual reason why people attempt to break their terrain into separate volumes is so that they can perform some more advanced memory management for very big terrain, for example by only loading particular volumes into memory when they are within a certain distance from the camera. However, this kind of paging behaviour is already implemented by the PagedVolume class. The PagedVolume internally stores its data as a set of blocks, and does it in such a way that it is able to perform neighbourhood access across block boundaries. Whenever you find yourself trying to break terrain data into separate volumes you should probably use the PagedVolume instead.
|
The usual reason why people attempt to break their terrain into separate volumes is so that they can perform some more advanced memory management for very big terrain, for example by only loading particular volumes into memory when they are within a certain distance from the camera. However, this kind of paging behaviour is already implemented by the LargeVolume class. The LargeVolume internally stores its data as a set of blocks, and does it in such a way that it is able to perform neighbourhood access across block boundaries. Whenever you find yourself trying to break terrain data into separate volumes you should probably use the LargeVolume instead.
|
||||||
|
|
||||||
Note that although you should only use a single volume for your data, it is still recommended that you split the mesh data into multiple pieces so that they can be culled against the view frustum, and so that you can update the smaller pieces more quickly when you need to. You can extract meshes from different parts of the volume by passing a Region to the surface extractor.
|
Note that although you should only use a single volume for your data, it is still recommended that you split the mesh data into multiple pieces so that they can be culled against the view frustum, and so that you can update the smaller pieces more quickly when you need to. You can extract meshes from different parts of the volume by passing a Region to the surface extractor.
|
||||||
|
|
||||||
@ -20,6 +20,6 @@ Lastly, note that there are exceptions to the 'one volume' rule. An example migh
|
|||||||
|
|
||||||
Can I combine smooth meshes with cubic ones?
|
Can I combine smooth meshes with cubic ones?
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
We have never attempted to do this but in theory it should be possible. One option is simply to generate two meshes (one using extractMarchingCubesSurface() and the other using extractCubicSurface()) and render them on top of each other while allowing the depth buffer to resolve the intersections. Combining these two meshes into a single mesh is likely to be difficult as they use different vertex formats and have different texturing requirements (see the document on texture mapping).
|
We have never attempted to do this but in theory it should be possible. One option is simply to generate two meshes (one using the MarchingCubesSurfaceExtractor and the other using the CubicSurfaceExtractor) and render them on top of each other while allowing the depth buffer to resolve the intersections. Combining these two meshes into a single mesh is likely to be difficult as they use different vertex formats and have different texturing requirements (see the document on texture mapping).
|
||||||
|
|
||||||
An alternative possibility may be to create a new surface extractor based on the Surface Nets (link) algorithm. The idea here is that the mesh would start with a cubic shape, but as the net was stretched it would be smoothed. The degree of smoothing could be controlled by a voxel property which could allow the full range from cubic to smooth to exist in a single mesh. As mentioned above, this may mean that some extra work has to be put into a fragment shader which is capable of texturing this kind of mesh. Come by the forums of you want to discuss this further.
|
An alternative possibility may be to create a new surface extractor based on the Surface Nets (link) algorithm. The idea here is that the mesh would start with a cubic shape, but as the net was stretched it would be smoothed. The degree of smoothing could be controlled by a voxel property which could allow the full range from cubic to smooth to exist in a single mesh. As mentioned above, this may mean that some extra work has to be put into a fragment shader which is capable of texturing this kind of mesh. Come by the forums of you want to discuss this further.
|
@ -7,14 +7,20 @@ For these reasons it is desirable to reduce the triangle count of the meshes as
|
|||||||
|
|
||||||
Cubic Meshes
|
Cubic Meshes
|
||||||
============
|
============
|
||||||
A naive implementation of a cubic surface extractor would generate a mesh containing a quad for each voxel face which lies on the boundary between a solid and an empty voxel. Our extractCubicSurface() function is indeed capable of generating such a mesh, but it also provides the option to merge adjacent quads into a single quad subject to various conditions being satisfied (e.g. the faces must have the same material). This merging process drastically reduces the amount of geometry which must be drawn but does not modify the shape of the mesh. Because of these desirable properties such merging is performed by default, but it can be disabled if necessary.
|
A naive implementation of a cubic surface extractor would generate a mesh containing a quad for voxel face which lies on the boundary between a solid and an empty voxel. The CubicSurfaceExtractor is indeed capable of generating such a mesh, but it also provides the option to merge adjacent quads into a single quad subject to various conditions being satisfied (e.g. the faces must have the same material). This merging process drastically reduces the amount of geometry which must be drawn but does not modify the shape of the mesh. Because of these desirable properties such merging is performed by default, but it can be disabled if necessary.
|
||||||
|
|
||||||
To our knowledge the only drawback of performing this quad merging is that it can create T-junctions in the resulting mesh. T-junctions are an undesirable property of mesh geometry because they can cause tiny cracks (usually just seen as flickering pixels) to occur between quads. Whether it's a problem in practice depends on hardware precision (16/32 bit), distance from origin, number of transforms which are applied, and probably a number of other factors. We have yet to investigate.
|
To our knowledge the only drawback of performing this quad merging is that it can create T-junctions in the resulting mesh. T-junctions are an undesirable property of mesh geometry because they can cause tiny cracks (usually just seen as flickering pixels) to occur between quads. The figure below shows a mesh before quad merging, a mesh where the merged quads have caused T-junctions, and how the resulting rendering might look (note the single pixel holes along the quad border).
|
||||||
|
|
||||||
|
*Add figure here...*
|
||||||
|
|
||||||
|
Vertices C and D are supposed to lie exactly along the line which has A and B as its end points, so in theory the mesh should be valid and should render correctly. The reason T-junctions cause a problem in practice is due to limitations of the floating point number representation. Depending on the transformations which are applied, it may be that the positions of C and/or D can not be represented precisely enough to exactly lie on the line between A and B.
|
||||||
|
|
||||||
|
*Demo correct mesh. mention we don't have a solution to generate it.*
|
||||||
|
|
||||||
|
Whether it's a problem in practice depends on hardware precision (16/32 bit), distance from origin, number of transforms which are applied, and probably a number of other factors. We have yet to investigate.
|
||||||
|
|
||||||
We don't currently have a real solution to this problem. In Voxeliens the borders between voxels were darkened to simulate ambient occlusion and this had the desirable side effect of making any flickering pixels very hard to see. It's also possible that anti-aliasing strategies can reduce the problem, and storing vertex positions as integers may help as well. Lastly, it may be possible to construct some kind of post-process which would repair the image where it identifies single pixel discontinuities in the depth buffer.
|
We don't currently have a real solution to this problem. In Voxeliens the borders between voxels were darkened to simulate ambient occlusion and this had the desirable side effect of making any flickering pixels very hard to see. It's also possible that anti-aliasing strategies can reduce the problem, and storing vertex positions as integers may help as well. Lastly, it may be possible to construct some kind of post-process which would repair the image where it identifies single pixel discontinuities in the depth buffer.
|
||||||
|
|
||||||
For more information on this topic we suggest the following article series: `Meshing in Voxel Engines <https://blackflux.wordpress.com/2014/02/23/meshing-in-voxel-engines-part-1/>`_
|
|
||||||
|
|
||||||
Smooth Meshes
|
Smooth Meshes
|
||||||
=============
|
=============
|
||||||
Level of detail for smooth meshes is a lot more complex than for cubic ones, and we'll admit upfront that we do not currently have a good solution to this problem. None the less, we do have a couple of partial solutions which you might be able to use or adapt for your specific scenario.
|
Level of detail for smooth meshes is a lot more complex than for cubic ones, and we'll admit upfront that we do not currently have a good solution to this problem. None the less, we do have a couple of partial solutions which you might be able to use or adapt for your specific scenario.
|
||||||
@ -27,16 +33,16 @@ The VolumeResampler class can be used to copy volume data from a source region t
|
|||||||
|
|
||||||
One of the problems with this approach is that the lower resolution mesh does not *exactly* line up with the higher resolution mesh, and this can cause cracks to be visible where the two meshes meet. The SmoothLOD sample attempts to avoid this problem by overlapping the meshes slightly but this may not be effective in all situations or from all viewpoints.
|
One of the problems with this approach is that the lower resolution mesh does not *exactly* line up with the higher resolution mesh, and this can cause cracks to be visible where the two meshes meet. The SmoothLOD sample attempts to avoid this problem by overlapping the meshes slightly but this may not be effective in all situations or from all viewpoints.
|
||||||
|
|
||||||
An alternative is the `Transvoxel algorithm <http://www.terathon.com/voxels/>`_ developed by Eric Lengyel. This essentially extends the original Marching Cubes lookup table with additional entries which handle seamless transitions between LOD levels, and it is a very promising solution to level of detail for voxel terrain. At this point in time we do not have an implementation of this algorithm.
|
An alternative is the Transvoxel algorithm (link) developed by Eric Lengyel. This essentially extends the original Marching Cubes lookup table with additional entries which handle seamless transitions between LOD levels, and it is a very promising solution to level of detail for voxel terrain. At this point in time we do not have an implementation of this algorithm but work is being undertaking in the area. For the latest developments see: http://www.volumesoffun.com/phpBB3/viewtopic.php?f=2&t=338
|
||||||
|
|
||||||
However, in all volume reduction approaches there is some uncertainty about how materials should be handled. Creating a lower resolution volume means that several voxel values from the high resolution volume need to be combined into a single value. For density values this is straightforward as a simple average gives good results, but it is not clear how this extends to material identifiers. Averaging them doesn't make sense, and it is hard to imagine an approach which would not lead to visible artifacts as LOD levels change. Perhaps the visible effects can be reduced by blending between two LOD levels, but more investigation needs to be done here.
|
However, in all volume reduction approaches there is some uncertainty about how materials should be handled. Creating a lower resolution volume means that several voxel values from the high resolution volume need to be combined into a single value. For density values this is straightforward as a simple average gives good results, but it is not clear how this extends to material identifiers. Averaging them doesn't make sense, and it is hard to imagine an approach which would not lead to visible artifacts as LOD levels change. Perhaps the visible effects can be reduced by blending between two LOD levels, but more investigation needs to be done here.
|
||||||
|
|
||||||
Mesh Simplification
|
Mesh Simplification
|
||||||
-------------------
|
-------------------
|
||||||
The other main approach is to generate the mesh at the full resolution and then reduce the number of triangles using a postprocessing step. This can draw on the large body of mesh simplification research and typically involves merging adjacent faces or collapsing vertices. When using this approach there are a couple of additional complications compared to the implementations which are normally seen.
|
The other main approach is to generate the mesh at the full resolution and then reduce the number of triangles using a postprocessing step. This can draw on the large body of mesh simplification research (link to survey) and typically involves merging adjacent faces or collapsing vertices. When using this approach there are a couple of additional complications compared to the implementations which are normally seen.
|
||||||
|
|
||||||
The first additional complication is that the decimation algorithm needs to preserve material boundaries so that they don't move between LOD levels. When choosing whether a particular simplification can be made (i.e deciding if one vertex can be collapsed on to another or whether two faces can be merged) a metric is usually used to determine how much the simplification would affect the visual appearance of the mesh. When working with smooth voxel meshes this metric needs to also consider the material identifiers.
|
The first additional complication is that the decimation algorithm needs to preserve material boundaries so that they don't move between LOD levels. When choosing whether a particular simplification can be made (i.e deciding if one vertex can be collapsed on to another or whether two faces can be merged) a metric is usually used to determine how much the simplification would affect the visual appearance of the mesh. When working with smooth voxel meshes this metric needs to also consider the material identifiers.
|
||||||
|
|
||||||
We also need to ensure that the metric preserves the geometric boundary of the mesh, so that no cracks are visible when a simplified mesh is placed next to an original one. Maintaining this geometric boundary can be difficult, as the straightforward approach of locking the edge vertices in place will tend to limit the amount of simplification which can be performed. Alternatively, cracks can be allowed to develop if they are later hidden through the use of 'skirts' around the resulting mesh.
|
We also need to ensure that the metric preserves the geometric boundary of the mesh, so that no cracks are visible when a simplified mesh is place next to an original one. Maintaining this geometric boundary can be difficult, as the straightforward approach of locking the edge vertices in place will tend to limit the amount of simplification which can be performed. Alternatively, cracks can be allowed to develop if they are later hidden through the use of 'skirts' around the resulting mesh.
|
||||||
|
|
||||||
PolyVox used to contain code for performing simplification of the smooth voxel meshes, but unfortunately it had significant performance and functionality issues and so it has been removed. We will instead investigate the use of external mesh simplification libraries and `OpenMesh <http://www.openmesh.org/>`_ may be a good candidate here.
|
PolyVox used to contain code for performing simplification of the smooth voxel meshes, but unfortunately it had significant performance and functionality issues. Therefore it has been deprecated and it will be removed in a future version of the library. We will instead investigate the use of external mesh simplification libraries and OpenMesh (link) may be a good candidate here.
|
||||||
|
@ -11,7 +11,7 @@ Normal Calculation for Smooth Meshes
|
|||||||
------------------------------------
|
------------------------------------
|
||||||
When working with smooth voxel terrain meshes, PolyVox provides vertex normals as part of the extracted surface mesh. A common approach for computing these normals would be to compute normals for each face in the mesh, and then compute the vertex normals as a weighted average of the normals of the faces which share it. Actually this is not the approach used by PolyVox, as PolyVox instead computes the vertex normals directly from the underlying volume data.
|
When working with smooth voxel terrain meshes, PolyVox provides vertex normals as part of the extracted surface mesh. A common approach for computing these normals would be to compute normals for each face in the mesh, and then compute the vertex normals as a weighted average of the normals of the faces which share it. Actually this is not the approach used by PolyVox, as PolyVox instead computes the vertex normals directly from the underlying volume data.
|
||||||
|
|
||||||
More specifically, PolyVox is able to compute the *gradient* of the volume data at any given point using well established image processing methods. The normalised gradient value is used as the vertex normal and in general it is smoother than the value computed by averaging neighbouring faces.
|
More specifically, PolyVox is able to compute the *gradient* of the volume data at any given point using well established image processing methods. The normalised gradient value is used as the vertex normal and in general it is smoother than the value computed by averaging neighbouring faces. Actually there are two approaches to this gradient computation known as *Central Differencing* and *Sobel Filter*. The central differencing approach is generally recommended but the Sobel filter can be used to obtain slightly smoother results but with lower performance. See the MarchingCubesSurfaceExtractor documentation for details on how to select between these (check this exists...).
|
||||||
|
|
||||||
Normal Calculation for Cubic Meshes
|
Normal Calculation for Cubic Meshes
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
@ -19,17 +19,18 @@ For cubic meshes PolyVox doesn't actually generate any vertex normals at all, an
|
|||||||
|
|
||||||
Therefore PolyVox does not generate per-vertex normals for cubic meshes, and as a result the cubic mesh's vertices are both smaller and less numerous. Of course, we still need a way to obtain normals for lighting calculations and so our suggestion is to compute the normals in a fragment program using the *derivative operations* which are provided by modern graphics hardware.
|
Therefore PolyVox does not generate per-vertex normals for cubic meshes, and as a result the cubic mesh's vertices are both smaller and less numerous. Of course, we still need a way to obtain normals for lighting calculations and so our suggestion is to compute the normals in a fragment program using the *derivative operations* which are provided by modern graphics hardware.
|
||||||
|
|
||||||
The description here is rather oversimplified, but the idea behind these operations is that they can tell you how much a variable has changed between two adjacent pixels. If we use our fragment world space position as the input to these derivative operations then we can obtain two vectors which lie on the surface of our face. The cross product of these then gives us a vector which is perpendicular to both and which is therefore our normal.
|
The description here is rather oversimplified, but the idea behind these operation is that they can tell you how much a variable has changed between two adjacent pixels. If we use our fragment world space position as the input to these derivative operations then we can obtain two vectors which lie on the surface of our face. The cross product of these then gives us a vector which is perpendicular to both and which is therefore our normal.
|
||||||
|
|
||||||
Further information about the derivative operations can be found in the OpenGL/Direct3D API documentation, but the implementation in code is quite simple. Firstly you need to make sure that you have access to the fragment's world space position in your shader, which means you need to pass it through from the vertex shader. Then you can use the following code in your fragment shader:
|
Further information about the derivative operations can be found in the OpenGL/Direct3D API documentation, but the implementation in code is quite simple. Firstly you need to make sure that you have access to the fragments world space position in your shader, which means you need to pass it through from the vertex shader. Then you can use the following code in your fragment shader:
|
||||||
|
|
||||||
.. sourcecode:: glsl
|
.. code-block:: glsl
|
||||||
|
|
||||||
vec3 worldNormal = cross(dFdy(inWorldPosition.xyz), dFdx(inWorldPosition.xyz));
|
vec3 worldNormal = cross(dFdy(inWorldPosition.xyz), dFdx(inWorldPosition.xyz));
|
||||||
worldNormal = normalize(worldNormal);
|
worldNormal = normalize(worldNormal);
|
||||||
|
|
||||||
.. note ::
|
**TODO: Check the normal direction**
|
||||||
Depending on your graphics API and/or engine setup, you may actually need to flip the resulting normal.
|
|
||||||
|
Similar code can be implemented in HLSL but you may need to invert the normal due to coordinate system differences between the two APIs. Also, be aware that it may be necessary to use OpenGL ES XXX extension in order to access this derivative functionality on mobile hardware.
|
||||||
|
|
||||||
Shadows
|
Shadows
|
||||||
-------
|
-------
|
||||||
|
@ -5,13 +5,13 @@ The PolyVox library is aimed at experienced games and graphics programmers who w
|
|||||||
|
|
||||||
As a result you will need a decent amount of graphics programming experience to effectively make use of the library. The purpose of this document is to highlight some of the core areas with which you will need to be familiar. In some cases we also provide links to places where you can find more information about the subject in question.
|
As a result you will need a decent amount of graphics programming experience to effectively make use of the library. The purpose of this document is to highlight some of the core areas with which you will need to be familiar. In some cases we also provide links to places where you can find more information about the subject in question.
|
||||||
|
|
||||||
You should also be aware that voxel terrain is still an open research area which is only just seeing widespread adoption in games and simulations. There are many questions to which we do not currently know the best answer and so you may have to do some research and experimentation yourself when trying to obtain your desired result. Please do let us know if you come up with a trick or technique which you think could benefit other users.
|
You should also be aware that voxel terrain is still an open research area and has not yet seen widespread adoption in games and simulations. There are many questions to which we do not currently know the best answer and so you may have to do some research and experimentation yourself when trying to obtain your desired result. Please do let us know if you come up with a trick or technique which you think could benefit other users.
|
||||||
|
|
||||||
Programming
|
Programming
|
||||||
===========
|
===========
|
||||||
This section describes some of the programming concepts with which you will need to be familiar:
|
This section describes some of the programming concepts with which you will need to be familiar:
|
||||||
|
|
||||||
**C++:** PolyVox is written using the C++ language and we expect this is what the majority of our users will be developing in. Note that you do have the option of working with other languages via the SWIG bindings but you may not have as much flexibility with this approach, and you will need to undertake additional work as the bindings are not currently complete.
|
**C++:** PolyVox is written using the C++ language and we expect this is what the majority of our users will be developing in. You will need to be familiar with the basic process of building and linking against external libraries as well as setting up your development environment. Note that you do have the option of working with other languages via the SWIG bindings but you may not have as much flexibility with this approach.
|
||||||
|
|
||||||
**Templates:** PolyVox also makes heavy use of template programming in order to be both fast and generic, so familiarity with templates will be very useful. You shouldn't need to do much template programming yourself but an understanding of them will help you understand errors and resolve any problems.
|
**Templates:** PolyVox also makes heavy use of template programming in order to be both fast and generic, so familiarity with templates will be very useful. You shouldn't need to do much template programming yourself but an understanding of them will help you understand errors and resolve any problems.
|
||||||
|
|
||||||
@ -23,16 +23,16 @@ Several core graphics principles will be useful in understanding and using PolyV
|
|||||||
|
|
||||||
**Volume representation:** PolyVox revolves around the idea of storing and manipulating volume data and using this as a representation of a 3d world. This is a fairly intuitive extension of traditional heightmap terrain but does require the ability to 'think in 3D'. You will need to understand that data stored in this way can become very large, and understand the idea that paging and compression can be used to combat this.
|
**Volume representation:** PolyVox revolves around the idea of storing and manipulating volume data and using this as a representation of a 3d world. This is a fairly intuitive extension of traditional heightmap terrain but does require the ability to 'think in 3D'. You will need to understand that data stored in this way can become very large, and understand the idea that paging and compression can be used to combat this.
|
||||||
|
|
||||||
**Mesh representation:** Most PolyVox projects will involve using one of the surface extractors, which output their data as index and vertex buffers. Therefore you will need to understand this representation in order to pass the data to your rendering engine or in order to perform further modifications to it. You can find out about more about this in the Wikipedia article on `Polygon Meshes <https://en.wikipedia.org/wiki/Polygon_mesh>`_
|
**Mesh representation:** Most PolyVox projects will involve using one of the surface extractors, which output their data as index and vertex buffers. Therefore you will need to understand this representation in order to pass the data to your rendering engine or in order to perform further modifications to it. You can find out about more about this here: (ADD LINK)
|
||||||
|
|
||||||
**Image processing:** For certain advanced applications an understanding of image processing methods can be useful. For example, the process of blurring an image via a low pass filter can be used to effectively smooth out voxel terrain. There are plans to add more image processing operations to PolyVox particularly with regard to morphological operations which you might want to use to modify your environment.
|
**Image processing:** For certain advanced application an understanding of image processing methods can be useful. For example the process of blurring an image via a low pass filter can be used to effectively smooth out voxel terrain. There are plans to add more image processing operations to PolyVox particularly with regard to morphological operations which you might want to use to modify your environment.
|
||||||
|
|
||||||
Rendering
|
Rendering
|
||||||
=========
|
=========
|
||||||
**Runtime geometry creation:** PolyVox is independent of any particular graphics API which means it outputs its data using API-neutral structures such as index and vertex buffers (as mentioned above). You will need to write the code which converts these structures into a format which your API or engine can understand. This is not a difficult task but does require some knowledge of the rendering technology which you are using.
|
**Runtime geometry creation:** PolyVox is independent of any particular graphics API which means it outputs its data using API-neutral structures such as index and vertex buffers (as mentioned above). You will need to write the code which converts these structures into a format which your API or engine can understand. This is not a difficult task but does require some knowledge of the rendering technology which you are using.
|
||||||
|
|
||||||
**Scene management:** PolyVox is only responsible for providing you with the mesh data to be displayed, so your application or engine will need to make sensible decisions about how this data should be organised in terms of a spatial structure (octree, bounding volumes tree, etc). It will also need to provide some approach to visibility determination such as frustum culling or a more advanced approach. If you are integrating PolyVox with an existing rendering engine then you should find that many of these aspects are already handled for you.
|
**Scene management:** PolyVox is only responsible for providing you with the mesh data to be displayed, so you application or engine will need to make sensible decisions about how this data should be organised in terms of a spatial structure (octree, bounding volumes tree, etc). It will also need to provide some approach to visibility determination such as frustum culling or a more advanced approach. If you are integrating PolyVox with an existing rendering engine then you should find that many of these aspects are already handled for you.
|
||||||
|
|
||||||
**Shader programming:** The meshes which are generated by PolyVox are very basic in terms of the vertex data they provide. You get vertex positions, sometimes vertex normals, and sometimes additional data copied/interpolated from the volume. It is the responsibility of application programmer to decide how to use this data to create visually interesting renderings. This means you will almost certainly want to make use of shader programs. Of course, in our :doc:`texturing <texturing>` and :doc:`lighting <lighting>` documents you will find many ideas and common solutions, but you will need strong shader programming experience to make effective use of these.
|
**Shader programming:** The meshes which are generated by PolyVox are very basic in terms of the vertex data they provide. You get vertex positions, a material identifier, and sometimes vertex normals. It is the responsibility of application programmer to decide how to use this data to create visually interesting renderings. This means you will almost certainly want to make use of shader programs. Of course, in our texturing (LINK) and lighting (LINK) documents you will find many ideas and common solutions, but you will need strong shader programming experience to make effective use of these.
|
||||||
|
|
||||||
If you don't have much experience with shader programming then there are many free resources available. The Wikipedia page on `Shaders <https://en.wikipedia.org/wiki/Shader>`_ may provide a starting point, as may the documentation for the `OpenGL <https://www.opengl.org/documentation/>`_ and `Direct3D <https://msdn.microsoft.com/en-us/library/windows/desktop/ff476080>`_ libraries. There is nothing special about PolyVox meshes so you would be advised to practice development on simple meshes such as spheres and cubes before trying to apply it to the output of the mesh extractors.
|
If you don't have much experience with shader programming then there are many free resources available. The Cg Tutorial (LINK) provides a good introduction here (the concepts are applicable to other shader languages) as does the documentation for the main graphics (LINK to OpenGL docs) APIs (Link to D3D docs). there is nothing special about PolyVox meshes so you would be advised to practice development on simple meshes such as spheres and cubes before trying to apply it to the output of the mesh extractors.
|
@ -31,9 +31,9 @@ The rational in the cubic case is almost the opposite. For Minecraft style terra
|
|||||||
|
|
||||||
Triplanar Texturing
|
Triplanar Texturing
|
||||||
-------------------
|
-------------------
|
||||||
The most common approach to texture mapping smooth voxel terrain is to use *triplanar texturing*. The basic idea is to project a texture along all three main axes and blend between the three texture samples according to the surface normal. As an example, suppose that we wish to write a fragment shader to apply a single texture to our terrain, and assume that we have access to both the world space position of the fragment and also its normalised surface normal. Also, note that your textures should be set to wrap because the world space position will quickly go outside the bounds of 0.0-1.0. The world space position will need to have been passed through from earlier in the pipeline while the normal can be computed using one of the approaches in the :doc:`lighting <Lighting>` document. The shader code would then look something like this [footnote: code is untested as is simplified compared to real world code. hopefully it compiles, but if not it should still give you an idea of how it works]:
|
The most common approach to texture mapping smooth voxel terrain is to use *triplanar texturing*. The basic idea is to project a texture along all three main axes and blend between the three texture samples according to the surface normal. As an example, suppose that we wish to write a fragment shader to apply a single texture to our terrain, and assume that we have access to both the world space position of the fragment and also its normalised surface normal. Also, note that your textures should be set to wrap because the world space position will quickly go outside the bounds of 0.0-1.0. The world space position will need to have been passed through from earlier in the pipeline while the normal can be computed using one of the approaches in the lighting (link) document. The shader code would then look something like this [footnote: code is untested as is simplified compared to real world code. hopefully it compiles, but if not it should still give you an idea of how it works]:
|
||||||
|
|
||||||
.. sourcecode:: glsl
|
.. code-block:: glsl
|
||||||
|
|
||||||
// Take the three texture samples
|
// Take the three texture samples
|
||||||
vec4 sampleX = texture2d(inputTexture, worldSpacePos.yz); // Project along x axis
|
vec4 sampleX = texture2d(inputTexture, worldSpacePos.yz); // Project along x axis
|
||||||
@ -47,7 +47,7 @@ Note that this approach will lead to the texture repeating once every world unit
|
|||||||
|
|
||||||
This idea of triplanar texturing can be applied to the cubic meshes as well, and in some ways it can be considered to be even simpler. With cubic meshes the normal always points exactly along one of the main axes, and so it is not necessary to sample the texture three times nor to blend the results. Instead you can use conditional branching in the fragment shader to determine which pair of values out of {x,y,z} should be used as the texture coordinates. Something like:
|
This idea of triplanar texturing can be applied to the cubic meshes as well, and in some ways it can be considered to be even simpler. With cubic meshes the normal always points exactly along one of the main axes, and so it is not necessary to sample the texture three times nor to blend the results. Instead you can use conditional branching in the fragment shader to determine which pair of values out of {x,y,z} should be used as the texture coordinates. Something like:
|
||||||
|
|
||||||
.. sourcecode:: glsl
|
.. code-block:: glsl
|
||||||
|
|
||||||
vec4 sample = vec4(0, 0, 0, 0); // We'll fill this in below
|
vec4 sample = vec4(0, 0, 0, 0); // We'll fill this in below
|
||||||
// Assume the normal is normalised.
|
// Assume the normal is normalised.
|
||||||
@ -67,11 +67,11 @@ Using the material identifier
|
|||||||
-----------------------------
|
-----------------------------
|
||||||
So far we have assumed that only a single material is being used for the entire voxel world, but this is seldom the case. It is common to associate a particular material with each voxel so that it can represent rock, wood, sand or any other type of material as required. The usual approach is to store a simple integer identifier with each voxel, and then map this identifier to material properties within your application.
|
So far we have assumed that only a single material is being used for the entire voxel world, but this is seldom the case. It is common to associate a particular material with each voxel so that it can represent rock, wood, sand or any other type of material as required. The usual approach is to store a simple integer identifier with each voxel, and then map this identifier to material properties within your application.
|
||||||
|
|
||||||
Both extractCubicSurface() and the extractMarchingCubesSurface() include a 'data' member in their vertices, and this is copied/interpolated directly from the corresponding voxels. Therefore you can store a material identifier as part of your voxel type, and then pass this through to your shader as a vertex attribute. You can then use this to affect the way the surface is rendered.
|
Both the CubicSurfaceExtractor and the MarchingCubesSurfacExtractor understand the concept of a material being associated with a voxel, and they will take this into account when generating a mesh. Specifically, they will both copy the material identifier into the vertex data of the output mesh, so you can pass it through to your shaders and use it to affect the way the surface is rendered.
|
||||||
|
|
||||||
The following code snippet assumes that you have passed a material identifier to your shaders and that you can access it in the fragment shader. It then chooses which colour to draw the polygon based on this identifier:
|
The following code snippet assumes that you have passed the material identifier to your shaders and that you can access it in the fragment shader. It then chooses which colour to draw the polygon based on this identifier:
|
||||||
|
|
||||||
.. sourcecode:: glsl
|
.. code-block:: glsl
|
||||||
|
|
||||||
vec4 fragmentColour = vec4(1, 1, 1, 1); // Default value
|
vec4 fragmentColour = vec4(1, 1, 1, 1); // Default value
|
||||||
if(materialId < 0.5) //Avoid '==' when working with floats.
|
if(materialId < 0.5) //Avoid '==' when working with floats.
|
||||||
@ -92,13 +92,17 @@ The following code snippet assumes that you have passed a material identifier to
|
|||||||
|
|
||||||
This is a very simple example, and such use of conditional branching within the shader may not be the best approach as it incurs some performance overhead and becomes unwieldy with a large number of materials. Other approaches include encoding a colour directly into the material identifier, or using the identifier as an index into a texture atlas or array.
|
This is a very simple example, and such use of conditional branching within the shader may not be the best approach as it incurs some performance overhead and becomes unwieldy with a large number of materials. Other approaches include encoding a colour directly into the material identifier, or using the identifier as an index into a texture atlas or array.
|
||||||
|
|
||||||
|
Note that PolyVox currently stores that material identifier for the vertex as a float, but this will probably change in the future to use the same type as is stored in the volume. It will then be up to you which type you pass to the GPU (older GPUs may not support integer values) but if you do use floats then watch out for precision issues and avoid equality comparisons.
|
||||||
|
|
||||||
Blending between materials
|
Blending between materials
|
||||||
--------------------------
|
--------------------------
|
||||||
An additional complication when working with smooth voxel terrain is that it is usually desirable to blend smoothly between adjacent voxels with different materials. This situation does not occur with cubic meshes because the texture is considered to be per-face instead of per-vertex, and PolyVox enforces this by ensuring that all the vertices of a given face have the same material.
|
An additional complication when working with smooth voxel terrain is that it is usually desirable to blend smoothly between adjacent voxels with different materials. This situation does not occur with cubic meshes because the texture is considered to be per-face instead of per-vertex, and PolyVox enforces this by ensuring that all the vertices of a given face have the same material.
|
||||||
|
|
||||||
With a smooth mesh it is possible for each of the three vertices of any given triangle to have different material identifiers. If this is not explicitly handled then the graphics hardware will interpolate these material values across the face of the triangle. Fundamentally, the concept of interpolating between material identifiers does not make sense, because if we have (for example) 1='grass', 2='rock' and 3='sand' then it does not make sense to say rock is the average of grass and sand.
|
With a smooth mesh it is possible for each of the three vertices of any given triangle to have different material identifiers. If this is not explicitly handled then the graphics hardware will interpolate these material values across the face of the triangle. Fundamentally, the concept of interpolating between material identifiers does not make sense, because if we have (for example) 1='grass', 2='rock' and 3='sand' then it does not make sense to say rock is the average of grass and sand.
|
||||||
|
|
||||||
Correctly handling of this is a surprising difficult problem. For now, one approach is described in our article 'Volumetric representation of virtual terrain' which appeared in Game Engine Gems Volume 1 and which is freely available through the Google Books preview here: http://books.google.com/books?id=WNfD2u8nIlIC&lpg=PR1&dq=game%20engine%20gems&pg=PA39#v=onepage&q&f=false
|
Correctly handling of this is a surprising difficult problem. For now, the best approach is described in our article 'Volumetric representation of virtual terrain' which appeared in Game Engine Gems Volume 1 and which is freely available through the Google Books preview here: http://books.google.com/books?id=WNfD2u8nIlIC&lpg=PR1&dq=game%20engine%20gems&pg=PA39#v=onepage&q&f=false
|
||||||
|
|
||||||
|
As off October 2012 we are actively researching alternative solutions to this problem though it will be some time before the results become available.
|
||||||
|
|
||||||
Actual implementation of these material blending approaches is left as an exercise to the reader, though it is possible that in the future we will add some utility functions to PolyVox to assist with tasks such as splitting the mesh or adding the required extra vertex attributes. Our test implementations have performed the mesh processing on the CPU before the mesh is uploaded to the graphics card, but it does seem like there is a lot of potential for implementing these approaches in the geometry shader.
|
Actual implementation of these material blending approaches is left as an exercise to the reader, though it is possible that in the future we will add some utility functions to PolyVox to assist with tasks such as splitting the mesh or adding the required extra vertex attributes. Our test implementations have performed the mesh processing on the CPU before the mesh is uploaded to the graphics card, but it does seem like there is a lot of potential for implementing these approaches in the geometry shader.
|
||||||
|
|
||||||
@ -106,7 +110,7 @@ Storage of textures
|
|||||||
===================
|
===================
|
||||||
The other major challenge in texturing voxel based geometry is handling the large number of textures which such environments often require. As an example, a game like Minecraft has hundreds of different material types each with their own texture. The traditional approach to mesh texturing is to bind textures to *texture units* on the GPU before rendering a batch, but even modern GPUs only allow between 16-64 textures to be bound at a time. In this section we discuss various solutions to overcoming this limitation.
|
The other major challenge in texturing voxel based geometry is handling the large number of textures which such environments often require. As an example, a game like Minecraft has hundreds of different material types each with their own texture. The traditional approach to mesh texturing is to bind textures to *texture units* on the GPU before rendering a batch, but even modern GPUs only allow between 16-64 textures to be bound at a time. In this section we discuss various solutions to overcoming this limitation.
|
||||||
|
|
||||||
There are various trade offs involved, but if you are targeting hardware with support for *texture arrays* (available from OpenGL 3 and Direct3D 10 onwards) then we can save you some time and tell you that they are almost certainly the best solution. Otherwise you have to understand the various pros and cons of the other approaches described below.
|
There are various trade offs involved, but if you are targeting hardware with support for *texture arrays* (available from OpenGL 3 and Direct3D 10 on-wards) then we can save you some time and tell you that they are almost certainly the best solution. Otherwise you have to understand the various pros and cons of the other approaches described below.
|
||||||
|
|
||||||
Separate texture units
|
Separate texture units
|
||||||
----------------------
|
----------------------
|
||||||
@ -118,7 +122,7 @@ If your required number of textures do indeed exceed the available number of tex
|
|||||||
|
|
||||||
A more practical approach would be to break the mesh into a smaller number of pieces such that each mesh uses several textures but less than the maximum number of texture units. For example, our mesh with one hundred materials could be split into ten meshes, the first of which contains those triangles using materials 0-9, the seconds contains those triangles using materials 10-19, and so forth. There is a trade off here between the number of batches and the number of textures units used per batch.
|
A more practical approach would be to break the mesh into a smaller number of pieces such that each mesh uses several textures but less than the maximum number of texture units. For example, our mesh with one hundred materials could be split into ten meshes, the first of which contains those triangles using materials 0-9, the seconds contains those triangles using materials 10-19, and so forth. There is a trade off here between the number of batches and the number of textures units used per batch.
|
||||||
|
|
||||||
Furthermore, you could realise that although your terrain may use hundreds of different textures, any given region is likely to use only a small fraction of those. We have yet to experiment with this, but it seems if you region uses only (for example) materials 12, 47, and 231, then you could conceptually map these materials to the first three textures slots. This means that for each region you draw the mapping between material IDs and texture units would be different. This may require some complex logic in the application but could allow you to do much more with only a few texture units.
|
Furthermore, you could realise that although your terrain may use hundreds of different textures, any given region is likely to use only a small fraction of those. We have yet to experiment with this, but it seems if you region uses only (for example) materials 12, 47, and 231, then you could conceptually map these materials to the first three textures slots. This means that for each region you draw the mapping between material IDs and texture units would be different. This may require some complex logic in the application but could allow you to do much more with only a few texture units. We will investigate this further in the future.
|
||||||
|
|
||||||
Texture atlases
|
Texture atlases
|
||||||
---------------
|
---------------
|
||||||
@ -134,7 +138,7 @@ It is possible to combat these problems but the solutions are non-trivial. You w
|
|||||||
|
|
||||||
3D texture slices
|
3D texture slices
|
||||||
-----------------
|
-----------------
|
||||||
The idea here is similar to the texture atlas approach, but rather than packing textures side-by-side in an atlas they are instead packed as slices in a 3D texture. We haven't actually tested this but in theory it may have a couple of benefits. Firstly, it simplifies the addressing of the texture as there is no need to offset/scale the UV coordinates, and the W coordinate (the slice index) can be more easily computed from the material identifier. Secondly, a single volume texture will usually be able to hold more texels than a single 2D texture (for example, 512x512x512 is bigger than 4096x4096). Lastly, it should simplify the filtering problem as packed textures are no longer tiled and so should wrap correctly.
|
The idea here is similar to the texture atlas approach, but rather than packing texture side-by-side in an atlas they are instead packed as slices in a 3D texture. We haven't actually tested this but in theory it may have a couple of benefits. Firstly, it simplifies the addressing of the texture as there is no need to offset/scale the UV coordinates, and the W coordinate (the slice index) can be more easily computed from the material identifier. Secondly, a single volume texture will usually be able to hold more texels than a single 2D texture (for example, 512x512x512 is bigger than 4096x4096). Lastly, it should simplify the filtering problem as packed textures are no longer tiled and so should wrap correctly.
|
||||||
|
|
||||||
However, MIP mapping will probably be more complex than the texture atlas case because even the first MIP level will involve combining adjacent slices. Volume textures are also not so widely supported and may be particularly problematic on mobile hardware.
|
However, MIP mapping will probably be more complex than the texture atlas case because even the first MIP level will involve combining adjacent slices. Volume textures are also not so widely supported and may be particularly problematic on mobile hardware.
|
||||||
|
|
||||||
|
@ -27,30 +27,30 @@ 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.
|
||||||
|
|
||||||
PagedVolume
|
LargeVolume
|
||||||
-----------
|
-----------
|
||||||
The PagedVolume 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 PagedVolume, 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.
|
||||||
|
|
||||||
Consequences of abuse
|
Consequences of abuse
|
||||||
---------------------
|
---------------------
|
||||||
We have outlined above the rules for multithreaded access of volumes, but what actually happens if you violate these? There's a couple of things to watch out for:
|
We have outlined above the rules for multithreaded access of volumes, but what actually happens if you violate these? There's a couple of things to watch out for:
|
||||||
|
|
||||||
- As mentioned, performing unprotected writes to the volume can cause problems because the data may be copied into the CPU cache and/or registers, and so a subsequent read could retrieve the old value. This is not what you want but probably won't be fatal (i.e. it shouldn't crash). It would basically manifest itself as data corruption.
|
- As mentioned, performing unprotected writes to the volume can cause problems because the data may be copied into the CPU cache and/or registers, and so a subsequent read could retrieve the old value. This is not what you want but probably won't be fatal (i.e. it shouldn't crash). It would basically manifest itself as data corruption.
|
||||||
- If you access the PagedVolume in a multithreaded fashion then you risk trying to access data which has been removed by another thread, and in this case you will get undefined behaviour. This will probably be a crash (out of bounds access) but really anything could happen.
|
- If you access the LargeVolume in a multithreaded fashion then you risk trying to access data which has been removed by another thread, and in this case you will get undefined behaviour. This will probably be a crash (out of bounds access) but really anything could happen.
|
||||||
|
|
||||||
Surface Extraction
|
Surface Extraction
|
||||||
==================
|
==================
|
||||||
Despite the lack of thread safety built in to PolyVox, it is still possible and often desirable to make use of multiple threads for tasks such as surface extraction. Performing surface extraction does not require write access to the data, and we've already established that you can safely perform reads from different threads *provided you are not using the PagedVolume*.
|
Despite the lack of thread safety built in to PolyVox, it is still possible and often desirable to make use of multiple threads for tasks such as surface extraction. Performing surface extraction does not require write access to the data, and we've already established that you can safely perform reads from different threads *provided you are not using the LargeVolume*.
|
||||||
|
|
||||||
Combining multiple surface extraction threads with the *PagedVolume* is something we will need to experiment with in the future, to determine how it can be improved.
|
Combining multiple surface extraction threads with the *LargeVolume* is something we will need to experiment with in the future, to determine how it can be improved.
|
||||||
|
|
||||||
In the future we will expand this section to discuss how to split surface extraction across a number of threads, but for now please see Section 3.4.3 of the book chapter 'Volumetric Representation of Virtual environments', available for free here: http://books.google.nl/books?id=WNfD2u8nIlIC&lpg=PR1&dq=game+engine+gems&pg=PA39&redir_esc=y#v=onepage&q&f=false
|
In the future we will expand this section to discuss how to split surface extraction across a number of threads, but for now please see Section XX of the book chapter 'Volumetric Representation of Virtual environments', available for free here: http://books.google.nl/books?id=WNfD2u8nIlIC&lpg=PR1&dq=game+engine+gems&pg=PA39&redir_esc=y#v=onepage&q&f=false
|
||||||
|
|
||||||
GPU thread safety
|
GPU thread safety
|
||||||
=================
|
=================
|
||||||
Be aware that even if you successfully perform surface extraction across multiple threads then you still need to take care when uploading the data to the GPU. For Direct3D 9.0 and OpenGL 2.0 it is only possible to upload data from the main thread (or more accurately the one which owns the rendering context). So after you have performed your multi-threaded surface extraction you need to bring the data back to the main thread for uploading to the GPU.
|
Be aware that even if you successfully perform surface across multiple threads you still need to take care when uploading the data to the GPU. For Direct3D 9.0 and OpenGL 2.0 it is only possible to upload data from the main thread (or more accurately the one which owns the rendering context). So after you have performed your multi-threaded surface extraction you need to bring the data back to the main thread for uploading to the GPU.
|
||||||
|
|
||||||
More recent versions of the Direct3D and OpenGL APIs lift this restriction and provide means of accessing GPU resources from multiple threads. Please consult the documentation for your API for details.
|
More recent versions of the Direct3D and OpenGL APIs lift this restriction and provide means of accessing GPU resources from multiple threads. Please consult the documentation for your API for details.
|
||||||
|
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
*******
|
|
||||||
Volumes
|
|
||||||
*******
|
|
||||||
The volume classes are the heart and soul of Polyvox, providing storage for the huge amounts of data which volumetric environments often require.
|
|
||||||
|
|
||||||
Volume concepts
|
|
||||||
===============
|
|
||||||
|
|
||||||
The main volume classes
|
|
||||||
=======================
|
|
||||||
|
|
||||||
Basic access to volume data
|
|
||||||
===========================
|
|
||||||
At the simplest level, individual voxels can be read and written by the getVoxel() and setVoxel() member functions which exist for each volume. We will focus on reading voxels first.
|
|
||||||
|
|
||||||
Reading voxels
|
|
||||||
--------------
|
|
||||||
The easiest way to read a particular voxel is as follows:
|
|
||||||
|
|
||||||
.. sourcecode :: c++
|
|
||||||
|
|
||||||
RawVolume<uint8_t>* volume = ... // Get a volume from somewhere.
|
|
||||||
uint8_t uVoxelValue = volume->getVoxel(x, y, z); // Read the voxel at the given position.
|
|
||||||
|
|
||||||
This works great as long as the provided position (x, y, z) does actually represent a valid position inside the volume. If this is not the case then the default behaviour is to throw an exception, so you should be prepared to handle this if you are not certain the position is valid.
|
|
||||||
|
|
||||||
Alternatively you can modify the behaviour which occurs when a position is outside the volume by providing a WrapMode as a fourth parameter to getVoxel(). For example:
|
|
||||||
|
|
||||||
.. sourcecode :: c++
|
|
||||||
|
|
||||||
// This will return the voxel, or '42' if the position is outside the volume
|
|
||||||
uint8_t uVoxelValue = volume->getVoxel(x, y, z, WrapModes::Border, 42);
|
|
||||||
|
|
||||||
Please see the documentation for WrapMode for more information on the avaiable options here. Note in particular that WrapModes::AssumeValid can be used to skip any bounds checking and so you should use this *if you are certain* that you are accessing a valid position, as it may be noticably faster in some cases.
|
|
||||||
|
|
||||||
.. sourcecode :: c++
|
|
||||||
|
|
||||||
// This will result in undefined behaviour if the position is outside the volume
|
|
||||||
uint8_t uVoxelValue = volume->getVoxel(x, y, z, WrapModes::AssumeValid);
|
|
||||||
|
|
||||||
Fast access to voxel data is very important in PolyVox, but the above functions have a drawback in that they need to contain logic to evaluate the provided WrapMode and decide how to proceed. This introduces branching into the execution flow and results in larger functions which may prevent inlining. For even more speed you can use version of the above functions which are templatised on the WrapMode rather than taking it as a parameter. This means the condition can be evaluated at compile time rather than run time: For example:
|
|
||||||
|
|
||||||
.. sourcecode :: c++
|
|
||||||
|
|
||||||
// This will return the voxel, or '42' if the position is outside the volume
|
|
||||||
uint8_t uVoxelValue = volume->getVoxel<WrapModes::Border>(x, y, z, 42);
|
|
||||||
|
|
||||||
Writing voxels
|
|
||||||
--------------
|
|
||||||
The setVoxel() function is used for writting to voxels instread of reading from them, and besides this it has two main behavoural differences when compared to getVoxel(). The first difference is that it is not templatised because the speed of setVoxel() is typically less important than getVoxel() (as writing to voxels is much less common than reading from them). However, we could add these temlatised version in the future if they are needed.
|
|
||||||
|
|
||||||
The second difference is that certain wrap modes such as WrapModes::Border or WrapModes::Clamp do not make much sense when writting to voxel data, and so these are no permitted and will result in an exception being thrown. You should only use WrapModes::Validate (the default) and WrapModes::AssumeValid. For example:
|
|
||||||
|
|
||||||
.. sourcecode :: c++
|
|
||||||
|
|
||||||
RawVolume<uint8_t>* volume = ... // Get a volume from somewhere.
|
|
||||||
volume->setVoxel(x, y, z, 57); // Write the voxel at the given position.
|
|
||||||
volume->setVoxel(x, y, z, 57, WrapMopdes::AssumeValid); // No bounds checks
|
|
||||||
|
|
||||||
Notes on error handling and performance
|
|
||||||
---------------------------------------
|
|
||||||
Overall, you should set the wrap mode to WrapModes::AssumeValid for maximum performance (and use templatised versions where available), but note that even this fast version does still contain a POLYVOX_ASSERT() to try and catch mistakes. It appears that this assert prevents inlining (probably due to the logging it performs), but it is anticipated that you will disable such asserts in the final build of your software.
|
|
@ -41,7 +41,7 @@ master_doc = 'index'
|
|||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u'PolyVox'
|
project = u'PolyVox'
|
||||||
copyright = u'2013, David Williams, Matt Williams'
|
copyright = u'2010, David Williams, Matt Williams'
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
# |version| and |release|, also used in various other places throughout the
|
# |version| and |release|, also used in various other places throughout the
|
||||||
|
@ -14,7 +14,7 @@ User Guide:
|
|||||||
ModifyingTerrain
|
ModifyingTerrain
|
||||||
LevelOfDetail
|
LevelOfDetail
|
||||||
Threading
|
Threading
|
||||||
ErrorHandling
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
@ -22,7 +22,6 @@ Examples:
|
|||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
tutorial1
|
tutorial1
|
||||||
python-bindings
|
|
||||||
|
|
||||||
Other Information:
|
Other Information:
|
||||||
|
|
||||||
|
@ -3,10 +3,12 @@ Principles of PolyVox
|
|||||||
**********************
|
**********************
|
||||||
|
|
||||||
.. warning ::
|
.. warning ::
|
||||||
This section is yet to be fully written and is just a skeleton for now.
|
This section is being written and is just a skeleton for now
|
||||||
|
|
||||||
PolyVox provides a library for managing 3D arrays (volumes) of data (voxels). It gives you the tools to iterate through, randomly access, read and write volumes. The volumes are templatized on voxel type, so that each voxel can be as simple as just an number or as complex as a class with a range of properties.
|
PolyVox provides a library for managing 3D arrays (volumes) of data (voxels). It gives you the tools to iterate through, randomly access, read and write volumes. It supports any type you'd like to represent each voxel whether it's just an ``int`` or a class which encapsulates both density and colour.
|
||||||
|
|
||||||
Once you have created a volume, PolyVox provides a number of tools for turning it into a mesh that you can pass to your rendering engine. These are called `surface extractors`. A 'Marching Cubes' surface extractor and a 'cubic' (Minecraft-style) surface extractor are included, and it is possible to write your own.
|
Once you have a volume, PolyVox provides a number of tools for turning it into something that you can pass to your rendering engine. These are called `surface extractors`.
|
||||||
|
|
||||||
PolyVox primarily handles this task of storing volume data and extracting surfaces from it. Most other aspects of you voxel application or game will need to be implemented by you (rendering, logic, physics, AI, networking, etc) though PolyVox does have a few utility classes for things like the A* algorithm on a 3D grid.
|
Each surface extractor needs to be told how to interperet your voxel type and that is done using...
|
||||||
|
|
||||||
|
Link to a page describing how to write your own voxel type and link it to a surface extractor...
|
||||||
|
@ -1,139 +0,0 @@
|
|||||||
***************
|
|
||||||
Python bindings
|
|
||||||
***************
|
|
||||||
|
|
||||||
Introduction
|
|
||||||
============
|
|
||||||
|
|
||||||
PolyVox itself is a C++ library but in order to make it useful to as many people as possible, we also provide bindings to a number of other languages.
|
|
||||||
These bindings are all generated by `SWIG <http://swig.org>`_ and provide a bridge to a compiled PolyVox library (*DLL* or *.so*) via an interafce which is native to the language.
|
|
||||||
This allows you in a Python script to simpy call ``import PolyVoxCore`` and get access to the whole library's functionality.
|
|
||||||
|
|
||||||
The Python bindings are available for Python 3.
|
|
||||||
|
|
||||||
Comparison with C++
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
All the bindings available for PolyVox (so both the Python bindings and any future supported bindings such as for C♯) follow the PolyVox C++ API quite closely.
|
|
||||||
This means that many PolyVox code examples written in C++ are mostly applicable also to Python.
|
|
||||||
Classes and functions are named the same and take the same set of arguments.
|
|
||||||
The main place this falls down is with templated C++ classes.
|
|
||||||
Since C++ templates are essentially a code-generation system built into the C++ compiler there is no way for a user of the Python bindings to request, at run-time, a specific piece of code to be generated.
|
|
||||||
The way we work around this is by, as part of the bindings generation process, pre-compiling a number of different versions of each templated class.
|
|
||||||
For example, in C++ a 3D vector containing 32-bit integers would be declared as
|
|
||||||
|
|
||||||
.. sourcecode:: c++
|
|
||||||
|
|
||||||
PolyVox::Vector3D<int32_t> my_vec(0,1,4);
|
|
||||||
|
|
||||||
but in Python it would be accessed as
|
|
||||||
|
|
||||||
.. sourcecode:: python
|
|
||||||
|
|
||||||
my_vec = PolyVoxCore.Vector3Dint32_t(0,1,4)
|
|
||||||
|
|
||||||
As a rule, any time in C++ where you see a template instantiation with ``<>``, just remove the angle brackets and it will yield the Python class name.
|
|
||||||
|
|
||||||
The choice of which C++ templates to instantiate is made by the developers of PolyVox in order to try to cover the main use-cases that library users would have.
|
|
||||||
If, however, you want to add your own versions, this can be done by editing the SWIG interface files and recompiling PolyVox.
|
|
||||||
|
|
||||||
Buildings the bindings
|
|
||||||
======================
|
|
||||||
|
|
||||||
The bindings are built as part of the standard PolyVox build process. For details on this please follow the instructions at :doc:`install`.
|
|
||||||
The important things to note there are the requirements for building the bindings: *Python development libraries* and *SWIG*.
|
|
||||||
During the CMake phase of building, it should tell you whether or not the bindings will be built.
|
|
||||||
|
|
||||||
Compiling the whole PolyVox library should then give you two files inside the ``build/library/bindings`` directory:
|
|
||||||
|
|
||||||
``PolyVoxCore.py``
|
|
||||||
This is the main entry point to the library.
|
|
||||||
|
|
||||||
``_PolyVoxCore.so`` (or ``.dll`` on Windows)
|
|
||||||
This contains the compiled code of the PolyVox library.
|
|
||||||
|
|
||||||
This file has a link dependency the main ``libPolyVoxCore.so`` library as well as the Python shared library.
|
|
||||||
|
|
||||||
|
|
||||||
Using the bindings
|
|
||||||
==================
|
|
||||||
|
|
||||||
As discussed above, the Python API is very similar to the C++ one but none-the-less we'll go through an example to see how it works.
|
|
||||||
All the code in this section is taken from ``PythonExample.py`` found in the source distribution of PolyVox in the ``examples/Python`` folder.
|
|
||||||
|
|
||||||
Seting up the volume
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
The first this we do is import the ``PolyVoxCore`` module. We rename it as ``pv`` to make our life easier.
|
|
||||||
|
|
||||||
.. literalinclude:: ../examples/Python/PythonExample.py
|
|
||||||
:language: python
|
|
||||||
:lines: 29
|
|
||||||
|
|
||||||
We create a ``Region`` from two vectors defining the bounds of the area - a volume 64×64×64.
|
|
||||||
Remember that ``pv.Vector3Dint32_t`` refers to a 3D :polyvox:`PolyVox::Vector` templated on a 32-bit integer.
|
|
||||||
|
|
||||||
The second line creates a :polyvox:`SimpleVolume` of the same size as the :polyvox:`Region` where each voxel in the volume is defined an unsigned 8-bit integer.
|
|
||||||
|
|
||||||
.. literalinclude:: ../examples/Python/PythonExample.py
|
|
||||||
:language: python
|
|
||||||
:lines: 31-33
|
|
||||||
|
|
||||||
We're going to fill our volume with a sphere and so we start by finding out where the centre of the volume is and defining the radius of our desired shape.
|
|
||||||
|
|
||||||
.. literalinclude:: ../examples/Python/PythonExample.py
|
|
||||||
:language: python
|
|
||||||
:lines: 35-37
|
|
||||||
|
|
||||||
Then we actually loop over each of the dimensions of the volume such that inside the loop, ``x``, ``y`` and ``z`` refer to the current location.
|
|
||||||
|
|
||||||
.. literalinclude:: ../examples/Python/PythonExample.py
|
|
||||||
:language: python
|
|
||||||
:lines: 38-41
|
|
||||||
|
|
||||||
All we do inside the loop is set all the voxels inside the sphere to have a value of ``255`` and all those outside to have a value of ``0``.
|
|
||||||
|
|
||||||
.. literalinclude:: ../examples/Python/PythonExample.py
|
|
||||||
:language: python
|
|
||||||
:lines: 42-53
|
|
||||||
|
|
||||||
Getting the mesh data
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Extracting the surface mesh for the volume is a two-step process.
|
|
||||||
First we tell PolyVox to generate the appropriate mesh, then we have to convert the PolyVox mesh data to something that our rendering library can understand.
|
|
||||||
|
|
||||||
First we define the sort of mesh that we want. For this example we want a mesh with information on the position, material and normal of each vertex.
|
|
||||||
Once we have out mesh object ready to be filled, we pass it to our surface extractor of choice.
|
|
||||||
PolyVox comes with a number of different surface extractors but for our example here, we want a cubic mesh.
|
|
||||||
|
|
||||||
You should also note that the ungainly looking ``CubicSurfaceExtractorWithNormalsSimpleVolumeuint8`` refers to the C++ class ``CubicSurfaceExtractorWithNormals<SimpleVolume<uint8_t>>``.
|
|
||||||
The ``execute()`` call is when PolyVox actually goes off and generates the requested mesh based on the data contained in the volume.
|
|
||||||
|
|
||||||
.. literalinclude:: ../examples/Python/PythonExample.py
|
|
||||||
:language: python
|
|
||||||
:lines: 55-58
|
|
||||||
|
|
||||||
Up until this point, the Python code has been totally generic with respect to your choice of rendering engine.
|
|
||||||
For this example we will be using `PyOpenGL <http://pyopengl.sourceforge.net/>`_ as it provides a nice pythonic API for many OpenGL functions.
|
|
||||||
|
|
||||||
Regardless of which rendering engine you are using, you will need to be able to wrangle the PolyVox mesh output into something you can insert into your engine.
|
|
||||||
In our case, we want two lists:
|
|
||||||
|
|
||||||
1. All the vertices along with their normals
|
|
||||||
2. The vertex indices which describes how the vertices are put together to make triangles.
|
|
||||||
|
|
||||||
PyOpenGL undersands `NumPy <http://numpy.org>`_ arrays and so we are going to copy our vertex data into two of these.
|
|
||||||
:polyvox:`SurfaceMesh` provides two useful functions here, ``getIndices()`` and ``getVertices()``, the Python versions of which return Python tuples.
|
|
||||||
|
|
||||||
The indices we can pass directly to NumPy as long as we make sure we specify the correct type for the data inside.
|
|
||||||
For the vertices, we want to rearange the data so that OpenGL can read it more efficiently.
|
|
||||||
To this end we explicitly retrieve the vertex positions and normals for each vertex and place them
|
|
||||||
such that the vertex ``x``, ``y`` and ``z`` positions are placed contiguously in memory followed by the normal vector's ``x``, ``y`` and ``z`` values.
|
|
||||||
|
|
||||||
.. literalinclude:: ../examples/Python/PythonExample.py
|
|
||||||
:language: python
|
|
||||||
:lines: 62-69
|
|
||||||
|
|
||||||
From this point on in the example, PolyVox is no longer used directly and all the code is standard PyOpenGL.
|
|
||||||
I won't go through every line here but the source code in ``PythonExample.py`` is commented and should be sufficient to understand how things work.
|
|
@ -12,32 +12,32 @@ Creating a volume
|
|||||||
=================
|
=================
|
||||||
To get started, we need to include the following headers:
|
To get started, we need to include the following headers:
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. code-block:: c++
|
||||||
|
|
||||||
#include "PolyVox/CubicSurfaceExtractor.h"
|
#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.h"
|
||||||
#include "PolyVox/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVox/Mesh.h"
|
#include "PolyVoxCore/SurfaceMesh.h"
|
||||||
#include "PolyVox/RawVolume.h"
|
#include "PolyVoxCore/SimpleVolume.h"
|
||||||
|
|
||||||
The most fundamental construct when working with PolyVox is that of the volume. This is represented by the :polyvox:`RawVolume` class which stores a 3D grid of voxels. Our basic example application creates a volume with the following line of code:
|
The most fundamental construct when working with PolyVox is that of the volume. This is represented by the :polyvox:`SimpleVolume` class which stores a 3D grid of voxels. Our basic example application creates a volume with the following line of code:
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. code-block:: c++
|
||||||
|
|
||||||
RawVolume<uint8_t> volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(63, 63, 63)));
|
SimpleVolume<uint8_t> volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(63, 63, 63)));
|
||||||
|
|
||||||
As can be seen, the RawVolume class is templated upon the voxel type. This means it is straightforward to create a volume of integers, floats, or a custom voxel type (see the :polyvox:`RawVolume documentation <PolyVox::RawVolume>` for more details). In this particular case we have created a volume in which each voxel is of type `uint8_t` which is an unsigned 8-bit integer.
|
As can be seen, the SimpleVolume class is templated upon the voxel type. This means it is straightforward to create a volume of integers, floats, or a custom voxel type (see the :polyvox:`SimpleVolume documentation <PolyVox::SimpleVolume>` for more details). In this particular case we have created a volume in which each voxel is of type `uint8_t` which is an unsigned 8-bit integer.
|
||||||
|
|
||||||
Next, we set some of the voxels in the volume to be 'solid' in order to create a large sphere in the centre of the volume. We do this with the following function call:
|
Next, we set some of the voxels in the volume to be 'solid' in order to create a large sphere in the centre of the volume. We do this with the following function call:
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. code-block:: c++
|
||||||
|
|
||||||
createSphereInVolume(volData, 30);
|
createSphereInVolume(volData, 30);
|
||||||
|
|
||||||
Note that this function is part of the BasicExample (rather than being part of the PolyVox library) and is implemented as follows:
|
Note that this function is part of the BasicExample (rather than being part of the PolyVox library) and is implemented as follows:
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. code-block:: c++
|
||||||
|
|
||||||
void createSphereInVolume(RawVolume<uint8_t>& volData, float fRadius)
|
void createSphereInVolume(SimpleVolume<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);
|
||||||
@ -50,145 +50,117 @@ Note that this function is part of the BasicExample (rather than being part of t
|
|||||||
for (int x = 0; x < volData.getWidth(); x++)
|
for (int x = 0; x < volData.getWidth(); x++)
|
||||||
{
|
{
|
||||||
//Store our current position as a vector...
|
//Store our current position as a vector...
|
||||||
Vector3DFloat v3dCurrentPos(x, y, z);
|
Vector3DFloat v3dCurrentPos(x,y,z);
|
||||||
//And compute how far the current position is from the center of the volume
|
//And compute how far the current position is from the center of the volume
|
||||||
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
||||||
|
|
||||||
uint8_t uVoxelValue = 0;
|
uint8_t uVoxelValue = 0;
|
||||||
|
|
||||||
//If the current voxel is less than 'radius' units from the center then we make it solid.
|
//If the current voxel is less than 'radius' units from the center then we make it solid.
|
||||||
if (fDistToCenter <= fRadius)
|
if(fDistToCenter <= fRadius)
|
||||||
{
|
{
|
||||||
//Our new voxel value
|
//Our new voxel value
|
||||||
uVoxelValue = 255;
|
uVoxelValue = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Wrte the voxel value into the volume
|
//Wrte the voxel value into the volume
|
||||||
volData.setVoxel(x, y, z, uVoxelValue);
|
volData.setVoxelAt(x, y, z, uVoxelValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
This function takes as input the :polyvox:`RawVolume` in which we want to create the sphere, and also a radius specifying how large we want the sphere to be. In our case we have specified a radius of 30 voxels, which will fit nicely inside our :polyvox:`RawVolume` of dimensions 64x64x64.
|
This function takes as input the :polyvox:`SimpleVolume` in which we want to create the sphere, and also a radius specifying how large we want the sphere to be. In our case we have specified a radius of 30 voxels, which will fit nicely inside our :polyvox:`SimpleVolume` of dimensions 64x64x64.
|
||||||
|
|
||||||
Because this is a simple example function it always places the sphere at the centre of the volume. It computes this centre by halving the dimensions of the volume as given by the functions :polyvox:`SimpleVolume::getWidth`, :polyvox:`SimpleVolume::getHeight` and :polyvox:`SimpleVolume::getDepth`. The resulting position is stored using a :polyvox:`Vector3DFloat`. This is simply a typedef from our templatised :polyvox:`Vector` class, meaning that other sizes and storage types are available if you need them.
|
Because this is a simple example function it always places the sphere at the centre of the volume. It computes this centre by halving the dimensions of the volume as given by the functions :polyvox:`SimpleVolume::getWidth`, :polyvox:`SimpleVolume::getHeight` and :polyvox:`SimpleVolume::getDepth`. The resulting position is stored using a :polyvox:`Vector3DFloat`. This is simply a typedef from our templatised :polyvox:`Vector` class, meaning that other sizes and storage types are available if you need them.
|
||||||
|
|
||||||
Next, the function uses a three-level 'for' loop to iterate over each voxel in the volume. For each voxel it computes the distance from the voxel to the centre of the volume. If this distance is less than or equal to the specified radius then the voxel forms part of the sphere and is made solid.
|
Next, the function uses a three-level 'for' loop to iterate over each voxel in the volume. For each voxel it computes the distance from the voxel to the centre of the volume. If this distance is less than or equal to the specified radius then the voxel forms part of the sphere and is made solid. During surface extraction, the voxel will be considered empty if it has a value of zero, and otherwise it will be considered solid. In our case we simply set it to 255 which is the largest value a uint8_t can contain.
|
||||||
|
|
||||||
Extracting the surface
|
Extracting the surface
|
||||||
======================
|
======================
|
||||||
Now that we have built our volume we need to convert it into a triangle mesh for rendering. This process can be performed by the :polyvox:`extractCubicMesh` function:
|
Now that we have built our volume we need to convert it into a triangle mesh for rendering. This process can be performed by the :polyvox:`CubicSurfaceExtractorWithNormals` class. An instance of the :polyvox:`CubicSurfaceExtractorWithNormals` is created as follows:
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. code-block:: c++
|
||||||
|
|
||||||
auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion());
|
SurfaceMesh<PositionMaterialNormal> mesh;
|
||||||
|
CubicSurfaceExtractorWithNormals< SimpleVolume<uint8_t> > surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
|
||||||
|
|
||||||
The :polyvox:`extractCubicMesh` function takes a pointer to the volume data, and also it needs to be told which :polyvox:`Region` of the volume the extraction should be performed on (in more advanced applications this is useful for extracting only those parts of the volume which have been modified since the last extraction). For our purpose the :polyvox:`RawVolume` class provides a convenient :polyvox:`RawVolume::getEnclosingRegion` function which returns a :polyvox:`Region` representing the whole volume.
|
The :polyvox:`CubicSurfaceExtractorWithNormals` takes a pointer to the volume data, and also it needs to be told which :polyvox:`Region` of the volume the extraction should be performed on (in more advanced applications this is useful for extracting only those parts of the volume which have been modified since the last extraction). For our purpose the :polyvox:`SimpleVolume` class provides a convenient :polyvox:`SimpleVolume::getEnclosingRegion` function which returns a :polyvox:`Region` representing the whole volume. The constructor also takes a pointer to a :polyvox:`SurfaceMesh` object where it will store the result, so we need to create one of these before we can construct the :polyvox:`CubicSurfaceExtractorWithNormals`.
|
||||||
|
|
||||||
The resulting mesh has a complex templatized type and so we assign it to a variable declared with 'auto', This way the compiler will determine the correct type for us. PolyVox also makes use of some compression techniques to store the vertex data in a compact way. Therefore the vertices of the mesh need to be decompressed ('decoded') before they can be used. For now the easiest approach is to use the provided ``decode()`` function, though advanced users can actually do this decoding on the GPU (see 'DecodeOnGPUExample'):
|
The actual extraction happens in the :polyvox:`CubicSurfaceExtractorWithNormals::execute` function. This means you can set up a :polyvox:`CubicSurfaceExtractorWithNormals` with the required parameters and then actually execute it later. For this example we just call it straight away.
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. code-block:: c++
|
||||||
|
|
||||||
auto decodedMesh = decodeMesh(mesh);
|
surfaceExtractor.execute();
|
||||||
|
|
||||||
Our ``decodedMesh`` variable contains an index and vertex buffer representing the desired triangle mesh.
|
This fills in our :polyvox:`SurfaceMesh` object, which basically contains an index and vertex buffer representing the desired triangle mesh.
|
||||||
|
|
||||||
Note: If you like you can try swapping the :polyvox:`extractCubicMesh` for :polyvox:`extractMarchingCubesMesh`. We have already included the relevant header, and in the BasicExample you just need to change which line in commented out. The :polyvox:`MarchingCubesSurfaceExtractor` makes use of a smooth density field and will consider a voxel to be solid if it is above a threshold of half the voxel's maximum value (so in this case that's half of 255, which is 127).
|
Note: If you like you can try swapping the :polyvox:`CubicSurfaceExtractorWithNormals` for :polyvox:`MarchingCubesSurfaceExtractor`. We have already included the relevant header, and in the BasicExample you just need to change which line in commented out. The :polyvox:`MarchingCubesSurfaceExtractor` makes use of a smooth density field and will consider a voxel to be solid if it is above a threshold of half the voxel's maximum value (so in this case that's half of 255, which is 127).
|
||||||
|
|
||||||
Rendering the surface
|
Rendering the surface
|
||||||
=====================
|
=====================
|
||||||
Rendering the surface with OpenGL is handled by our ``PolyVoxExample`` which is an ``OpenGLWidget`` subclass. Again, this is not part of PolyVox, it is simply an example based on Qt and OpenGL which demonstrates how rendering can be performed. Within this class there are mainly two functions which are of interest - the PolyVoxExample::addMesh() function which constructs OpenGL buffers from our :polyvox:`Mesh` and the PolyVoxExample::renderOneFrame() function which is called each frame to perform the rendering.
|
Rendering the surface with OpenGL is handled by the OpenGLWidget class. Again, this is not part of PolyVox, it is simply an example based on Qt and OpenGL which demonstrates how rendering can be performed. Within this class there are mainly two functions which are of interest - the OpenGLWidget::setSurfaceMeshToRender() function which constructs OpenGL buffers from our :polyvox:`SurfaceMesh` and the OpenGLWidget::paintGL() function which is called each frame to perform the rendering.
|
||||||
|
|
||||||
The PolyVoxExample::addMesh() function is implemented as follows:
|
The OpenGLWidget::setSurfaceMeshToRender() function is implemented as follows:
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. code-block:: c++
|
||||||
|
|
||||||
template <typename MeshType>
|
void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh<PositionMaterialNormal>& surfaceMesh)
|
||||||
void addMesh(const MeshType& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f)
|
|
||||||
{
|
{
|
||||||
// This struct holds the OpenGL properties (buffer handles, etc) which will be used
|
//Convienient access to the vertices and indices
|
||||||
// to render our mesh. We copy the data from the PolyVox mesh into this structure.
|
const vector<uint32_t>& vecIndices = surfaceMesh.getIndices();
|
||||||
OpenGLMeshData meshData;
|
const vector<PositionMaterialNormal>& vecVertices = surfaceMesh.getVertices();
|
||||||
|
|
||||||
// Create the VAO for the mesh
|
//Build an OpenGL index buffer
|
||||||
glGenVertexArrays(1, &(meshData.vertexArrayObject));
|
glGenBuffers(1, &indexBuffer);
|
||||||
glBindVertexArray(meshData.vertexArrayObject);
|
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);
|
||||||
|
|
||||||
// The GL_ARRAY_BUFFER will contain the list of vertex positions
|
//Build an OpenGL vertex buffer
|
||||||
glGenBuffers(1, &(meshData.vertexBuffer));
|
glGenBuffers(1, &vertexBuffer);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer);
|
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
|
||||||
glBufferData(GL_ARRAY_BUFFER, surfaceMesh.getNoOfVertices() * sizeof(typename MeshType::VertexType), surfaceMesh.getRawVertexData(), GL_STATIC_DRAW);
|
const GLvoid* pVertices = static_cast<const GLvoid*>(&(vecVertices[0]));
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PositionMaterialNormal), pVertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
// and GL_ELEMENT_ARRAY_BUFFER will contain the indices
|
m_uBeginIndex = 0;
|
||||||
glGenBuffers(1, &(meshData.indexBuffer));
|
m_uEndIndex = vecIndices.size();
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshData.indexBuffer);
|
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, surfaceMesh.getNoOfIndices() * sizeof(typename MeshType::IndexType), surfaceMesh.getRawIndexData(), 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 = surfaceMesh.getNoOfIndices();
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
We begin by obtaining direct access to the index and vertex buffer in the :polyvox:`SurfaceMesh` class in order to make the following code slightly cleaner. Both the :polyvox:`SurfaceMesh::getIndices` and :polyvox:`SurfaceMesh::getVertices` functions return an std::vector containing the relevant data.
|
||||||
|
|
||||||
|
The OpenGL functions which are called to construct the index and vertex buffer are best explained by the OpenGL documentation. In both cases we are making an exact copy of the data stored in the :polyvox:`SurfaceMesh`.
|
||||||
|
|
||||||
|
The begin and end indices are used in the OpenGLWidget::paintGL() to control what part of the index buffer is actually rendered. For this simple example we will render the whole buffer from '0' to 'vecIndices.size()'.
|
||||||
|
|
||||||
With the OpenGL index and vertex buffers set up, we can now look at the code which is called each frame to render them:
|
With the OpenGL index and vertex buffers set up, we can now look at the code which is called each frame to render them:
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. code-block:: c++
|
||||||
|
|
||||||
void renderOneFrame() override
|
void OpenGLWidget::paintGL()
|
||||||
{
|
{
|
||||||
// Our example framework only uses a single shader for the scene (for all meshes).
|
//Clear the screen
|
||||||
mShader->bind();
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
// These two matrices are constant for all meshes.
|
//Set up the viewing transformation
|
||||||
mShader->setUniformValue("viewMatrix", viewMatrix());
|
glMatrixMode(GL_MODELVIEW);
|
||||||
mShader->setUniformValue("projectionMatrix", projectionMatrix());
|
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
|
||||||
|
|
||||||
// Iterate over each mesh which the user added to our list, and render it.
|
//Bind the index buffer
|
||||||
for (OpenGLMeshData meshData : mMeshData)
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
|
||||||
{
|
|
||||||
//Set up the model matrrix based on provided translation and scale.
|
|
||||||
QMatrix4x4 modelMatrix;
|
|
||||||
modelMatrix.translate(meshData.translation);
|
|
||||||
modelMatrix.scale(meshData.scale);
|
|
||||||
mShader->setUniformValue("modelMatrix", modelMatrix);
|
|
||||||
|
|
||||||
// Bind the vertex array for the current mesh
|
//Bind the vertex buffer
|
||||||
glBindVertexArray(meshData.vertexArrayObject);
|
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
|
||||||
// Draw the mesh
|
glVertexPointer(3, GL_FLOAT, sizeof(PositionMaterialNormal), 0);
|
||||||
glDrawElements(GL_TRIANGLES, meshData.noOfIndices, meshData.indexType, 0);
|
glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (GLvoid*)12);
|
||||||
// Unbind the vertex array.
|
|
||||||
glBindVertexArray(0);
|
glDrawRangeElements(GL_TRIANGLES, m_uBeginIndex, m_uEndIndex-1, m_uEndIndex - m_uBeginIndex, GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
|
//Error checking code here...
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're done with the shader for this frame.
|
Again, the explanation of this code is best left to the OpenGL documentation. Note that is is called automatically by Qt each time the display needs to be updated.
|
||||||
mShader->release();
|
|
||||||
}
|
|
||||||
|
|
||||||
Again, the explanation of this code is best left to the OpenGL documentation.
|
|
@ -1,62 +1,64 @@
|
|||||||
################################################################################
|
# Copyright (c) 2010-2012 David Williams
|
||||||
# The MIT License (MIT)
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2015 Matthew Williams and 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 hereby granted, free of charge, to any person obtaining a copy
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# in the Software without restriction, including without limitation the rights
|
# freely, subject to the following restrictions:
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
#
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
# 1. The origin of this software must not be misrepresented; you must not
|
||||||
# copies or substantial portions of the Software.
|
# 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.
|
||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# misrepresented as being the original software.
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
#
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# 3. This notice may not be removed or altered from any source
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# distribution.
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||||
################################################################################
|
|
||||||
|
|
||||||
PROJECT(BasicExample)
|
PROJECT(BasicExample)
|
||||||
|
|
||||||
#Projects source files
|
#Projects source files
|
||||||
SET(SRC_FILES
|
SET(SRC_FILES
|
||||||
|
glew/glew.cpp
|
||||||
|
|
||||||
main.cpp
|
main.cpp
|
||||||
../common/PolyVoxExample.cpp
|
OpenGLWidget.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
#Projects headers files
|
#Projects headers files
|
||||||
SET(INC_FILES
|
SET(INC_FILES
|
||||||
../common/OpenGLWidget.h
|
glew/glew.h
|
||||||
../common/OpenGLWidget.inl
|
glew/glxew.h
|
||||||
../common/PolyVoxExample.h
|
glew/wglew.h
|
||||||
)
|
|
||||||
|
OpenGLWidget.h
|
||||||
|
)
|
||||||
|
|
||||||
|
ADD_DEFINITIONS(-DGLEW_STATIC)
|
||||||
|
|
||||||
#"Sources" and "Headers" are the group names in Visual Studio.
|
#"Sources" and "Headers" are the group names in Visual Studio.
|
||||||
#They may have other uses too...
|
#They may have other uses too...
|
||||||
SOURCE_GROUP("Sources" FILES ${SRC_FILES})
|
SOURCE_GROUP("Sources" FILES ${SRC_FILES})
|
||||||
SOURCE_GROUP("Headers" FILES ${INC_FILES})
|
SOURCE_GROUP("Headers" FILES ${INC_FILES})
|
||||||
|
|
||||||
|
FIND_PACKAGE(OpenGL REQUIRED)
|
||||||
|
|
||||||
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
#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} ../common)
|
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_SOURCE_DIR}/include)
|
||||||
|
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
||||||
#This will include the shader files inside the compiled binary
|
|
||||||
QT5_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
|
||||||
|
|
||||||
# Put the resources in a seperate folder in Visual Studio
|
|
||||||
SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC})
|
|
||||||
|
|
||||||
#Build
|
#Build
|
||||||
ADD_EXECUTABLE(BasicExample ${SRC_FILES} ${COMMON_RESOURCES_RCC})
|
ADD_EXECUTABLE(BasicExample ${SRC_FILES})
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
SET_TARGET_PROPERTIES(BasicExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127") #All warnings
|
SET_TARGET_PROPERTIES(BasicExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
|
||||||
ENDIF(MSVC)
|
ENDIF(MSVC)
|
||||||
TARGET_LINK_LIBRARIES(BasicExample Qt5::OpenGL)
|
TARGET_LINK_LIBRARIES(BasicExample ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
||||||
SET_PROPERTY(TARGET BasicExample PROPERTY FOLDER "Examples")
|
SET_PROPERTY(TARGET BasicExample PROPERTY FOLDER "Examples")
|
||||||
|
|
||||||
#Install - Only install the example in Windows
|
#Install - Only install the example in Windows
|
||||||
|
152
examples/Basic/OpenGLWidget.cpp
Normal file
152
examples/Basic/OpenGLWidget.cpp
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
#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::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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
67
examples/Basic/OpenGLWidget.h
Normal file
67
examples/Basic/OpenGLWidget.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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__
|
73
examples/Basic/glew/LICENSE.txt
Normal file
73
examples/Basic/glew/LICENSE.txt
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
The OpenGL Extension Wrangler Library
|
||||||
|
Copyright (C) 2002-2007, Milan Ikits <milan ikits[]ieee org>
|
||||||
|
Copyright (C) 2002-2007, Marcelo E. Magallon <mmagallo[]debian org>
|
||||||
|
Copyright (C) 2002, Lev Povalahev
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
* The name of the author may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
Mesa 3-D graphics library
|
||||||
|
Version: 7.0
|
||||||
|
|
||||||
|
Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (c) 2007 The Khronos Group Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and/or associated documentation files (the
|
||||||
|
"Materials"), to deal in the Materials without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Materials, and to
|
||||||
|
permit persons to whom the Materials are furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Materials.
|
||||||
|
|
||||||
|
THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
16972
examples/Basic/glew/glew.cpp
Normal file
16972
examples/Basic/glew/glew.cpp
Normal file
File diff suppressed because it is too large
Load Diff
17132
examples/Basic/glew/glew.h
Normal file
17132
examples/Basic/glew/glew.h
Normal file
File diff suppressed because it is too large
Load Diff
1637
examples/Basic/glew/glxew.h
Normal file
1637
examples/Basic/glew/glxew.h
Normal file
File diff suppressed because it is too large
Load Diff
1397
examples/Basic/glew/wglew.h
Normal file
1397
examples/Basic/glew/wglew.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,40 +1,39 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
The MIT License (MIT)
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
Copyright (c) 2015 David Williams and Matthew 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 hereby granted, free of charge, to any person obtaining a copy
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
including commercial applications, and to alter it and redistribute it
|
||||||
in the Software without restriction, including without limitation the rights
|
freely, subject to the following restrictions:
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
copies or substantial portions of the Software.
|
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.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
misrepresented as being the original software.
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
3. This notice may not be removed or altered from any source
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
distribution.
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVoxExample.h"
|
#include "OpenGLWidget.h"
|
||||||
|
|
||||||
#include "PolyVox/CubicSurfaceExtractor.h"
|
#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.h"
|
||||||
#include "PolyVox/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVox/Mesh.h"
|
#include "PolyVoxCore/SurfaceMesh.h"
|
||||||
#include "PolyVox/RawVolume.h"
|
#include "PolyVoxCore/SimpleVolume.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
//Use the PolyVox namespace
|
//Use the PolyVox namespace
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
|
|
||||||
void createSphereInVolume(RawVolume<uint8_t>& volData, float fRadius)
|
void createSphereInVolume(SimpleVolume<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);
|
||||||
@ -47,63 +46,50 @@ void createSphereInVolume(RawVolume<uint8_t>& volData, float fRadius)
|
|||||||
for (int x = 0; x < volData.getWidth(); x++)
|
for (int x = 0; x < volData.getWidth(); x++)
|
||||||
{
|
{
|
||||||
//Store our current position as a vector...
|
//Store our current position as a vector...
|
||||||
Vector3DFloat v3dCurrentPos(x, y, z);
|
Vector3DFloat v3dCurrentPos(x,y,z);
|
||||||
//And compute how far the current position is from the center of the volume
|
//And compute how far the current position is from the center of the volume
|
||||||
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
||||||
|
|
||||||
uint8_t uVoxelValue = 0;
|
uint8_t uVoxelValue = 0;
|
||||||
|
|
||||||
//If the current voxel is less than 'radius' units from the center then we make it solid.
|
//If the current voxel is less than 'radius' units from the center then we make it solid.
|
||||||
if (fDistToCenter <= fRadius)
|
if(fDistToCenter <= fRadius)
|
||||||
{
|
{
|
||||||
//Our new voxel value
|
//Our new voxel value
|
||||||
uVoxelValue = 255;
|
uVoxelValue = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Wrte the voxel value into the volume
|
//Wrte the voxel value into the volume
|
||||||
volData.setVoxel(x, y, z, uVoxelValue);
|
volData.setVoxelAt(x, y, z, uVoxelValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BasicExample : public PolyVoxExample
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BasicExample(QWidget *parent)
|
|
||||||
:PolyVoxExample(parent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void initializeExample() override
|
|
||||||
{
|
|
||||||
// Create an empty volume and then place a sphere in it
|
|
||||||
RawVolume<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
|
|
||||||
addMesh(decodedMesh);
|
|
||||||
|
|
||||||
setCameraTransform(QVector3D(100.0f, 100.0f, 100.0f), -(PI / 4.0f), PI + (PI / 4.0f));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
//Create and show the Qt OpenGL window
|
//Create and show the Qt OpenGL window
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
BasicExample openGLWidget(0);
|
OpenGLWidget openGLWidget(0);
|
||||||
openGLWidget.show();
|
openGLWidget.show();
|
||||||
|
|
||||||
|
//Create an empty volume and then place a sphere in it
|
||||||
|
SimpleVolume<uint8_t> volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(63, 63, 63)));
|
||||||
|
createSphereInVolume(volData, 30);
|
||||||
|
|
||||||
|
//A mesh object to hold the result of surface extraction
|
||||||
|
SurfaceMesh<PositionMaterialNormal> mesh;
|
||||||
|
|
||||||
|
//Create a surface extractor. Comment out one of the following two lines to decide which type gets created.
|
||||||
|
CubicSurfaceExtractorWithNormals< SimpleVolume<uint8_t> > surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
|
||||||
|
//MarchingCubesSurfaceExtractor< SimpleVolume<uint8_t> > surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
|
||||||
|
|
||||||
|
//Execute the surface extractor.
|
||||||
|
surfaceExtractor.execute();
|
||||||
|
|
||||||
|
//Pass the surface to the OpenGL window
|
||||||
|
openGLWidget.setSurfaceMeshToRender(mesh);
|
||||||
|
|
||||||
//Run the message pump.
|
//Run the message pump.
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
@ -1,40 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# The MIT License (MIT)
|
|
||||||
#
|
|
||||||
# Copyright (c) 2015 Matthew Williams and David Williams
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
|
||||||
# in the Software without restriction, including without limitation the rights
|
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
|
||||||
# copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
find_package(Qt5OpenGL 5.2)
|
|
||||||
|
|
||||||
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(Qt5OpenGL_FOUND)
|
|
||||||
SET(BUILD_EXAMPLES ON PARENT_SCOPE)
|
|
||||||
ADD_SUBDIRECTORY(Basic)
|
|
||||||
ADD_SUBDIRECTORY(Paging)
|
|
||||||
ADD_SUBDIRECTORY(OpenGL)
|
|
||||||
ADD_SUBDIRECTORY(SmoothLOD)
|
|
||||||
ADD_SUBDIRECTORY(DecodeOnGPU)
|
|
||||||
ADD_SUBDIRECTORY(Python)
|
|
||||||
else()
|
|
||||||
SET(BUILD_EXAMPLES OFF PARENT_SCOPE)
|
|
||||||
endif()
|
|
@ -1,71 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# The MIT License (MIT)
|
|
||||||
#
|
|
||||||
# Copyright (c) 2015 Matthew Williams and David Williams
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
|
||||||
# in the Software without restriction, including without limitation the rights
|
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
|
||||||
# copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
PROJECT(DecodeOnGPUExample)
|
|
||||||
|
|
||||||
#Projects source files
|
|
||||||
SET(SRC_FILES
|
|
||||||
main.cpp
|
|
||||||
../common/PolyVoxExample.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
#Projects headers files
|
|
||||||
SET(INC_FILES
|
|
||||||
../common/OpenGLWidget.h
|
|
||||||
../common/OpenGLWidget.inl
|
|
||||||
../common/PolyVoxExample.h
|
|
||||||
)
|
|
||||||
|
|
||||||
#"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})
|
|
||||||
|
|
||||||
#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} ../common)
|
|
||||||
|
|
||||||
#This will include the shader files inside the compiled binary
|
|
||||||
QT5_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
|
||||||
QT5_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 Qt5::OpenGL)
|
|
||||||
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)
|
|
@ -1,19 +0,0 @@
|
|||||||
#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);
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
<!DOCTYPE RCC><RCC version="1.0">
|
|
||||||
<qresource>
|
|
||||||
<file>decode.vert</file>
|
|
||||||
<file>decode.frag</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
@ -1,46 +0,0 @@
|
|||||||
#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 projectionMatrix;
|
|
||||||
uniform mat4 viewMatrix;
|
|
||||||
uniform mat4 modelMatrix;
|
|
||||||
|
|
||||||
// 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 = modelMatrix * decodedPosition;
|
|
||||||
vec4 cameraPosition = viewMatrix * worldPosition;
|
|
||||||
gl_Position = projectionMatrix * cameraPosition;
|
|
||||||
}
|
|
@ -1,173 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2015 David Williams and Matthew Williams
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
#include "PolyVoxExample.h"
|
|
||||||
|
|
||||||
#include "PolyVox/CubicSurfaceExtractor.h"
|
|
||||||
#include "PolyVox/MarchingCubesSurfaceExtractor.h"
|
|
||||||
#include "PolyVox/Mesh.h"
|
|
||||||
#include "PolyVox/RawVolume.h"
|
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
|
|
||||||
//Use the PolyVox namespace
|
|
||||||
using namespace PolyVox;
|
|
||||||
|
|
||||||
void createSphereInVolume(RawVolume<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.setVoxel(x, y, z, uVoxelValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DecodeOnGPUExample : public PolyVoxExample
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DecodeOnGPUExample(QWidget *parent)
|
|
||||||
:PolyVoxExample(parent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void initializeExample() override
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
setShader(shader);
|
|
||||||
|
|
||||||
//Create an empty volume and then place a sphere in it
|
|
||||||
RawVolume<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 = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion());
|
|
||||||
|
|
||||||
//Pass the surface to the OpenGL window
|
|
||||||
OpenGLMeshData meshData = buildOpenGLMeshData(mesh);
|
|
||||||
addMeshData(meshData);
|
|
||||||
|
|
||||||
setCameraTransform(QVector3D(100.0f, 100.0f, 100.0f), -(PI / 4.0f), PI + (PI / 4.0f));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
OpenGLMeshData buildOpenGLMeshData(const PolyVox::Mesh< PolyVox::MarchingCubesVertex< uint8_t > >& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f)
|
|
||||||
{
|
|
||||||
// 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, surfaceMesh.getNoOfVertices() * sizeof(MarchingCubesVertex< uint8_t >), surfaceMesh.getRawVertexData(), 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, surfaceMesh.getNoOfIndices() * sizeof(uint32_t), surfaceMesh.getRawIndexData(), 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 = surfaceMesh.getNoOfIndices();
|
|
||||||
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);
|
|
||||||
DecodeOnGPUExample openGLWidget(0);
|
|
||||||
openGLWidget.show();
|
|
||||||
|
|
||||||
//Run the message pump.
|
|
||||||
return app.exec();
|
|
||||||
}
|
|
@ -1,26 +1,23 @@
|
|||||||
################################################################################
|
# Copyright (c) 2010-2012 David Williams
|
||||||
# The MIT License (MIT)
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2015 Matthew Williams and 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 hereby granted, free of charge, to any person obtaining a copy
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# in the Software without restriction, including without limitation the rights
|
# freely, subject to the following restrictions:
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
#
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
# 1. The origin of this software must not be misrepresented; you must not
|
||||||
# copies or substantial portions of the Software.
|
# 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.
|
||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# misrepresented as being the original software.
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
#
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# 3. This notice may not be removed or altered from any source
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# distribution.
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||||
|
|
||||||
@ -28,46 +25,46 @@ PROJECT(OpenGLExample)
|
|||||||
|
|
||||||
#Projects source files
|
#Projects source files
|
||||||
SET(SRC_FILES
|
SET(SRC_FILES
|
||||||
|
glew/glew.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
#OpenGLImmediateModeSupport.cpp
|
OpenGLImmediateModeSupport.cpp
|
||||||
#OpenGLSupport.cpp
|
OpenGLSupport.cpp
|
||||||
#OpenGLVertexBufferObjectSupport.cpp
|
OpenGLVertexBufferObjectSupport.cpp
|
||||||
../common/PolyVoxExample.cpp
|
OpenGLWidget.cpp
|
||||||
Shapes.cpp
|
Shapes.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
#Projects headers files
|
#Projects headers files
|
||||||
SET(INC_FILES
|
SET(INC_FILES
|
||||||
#OpenGLImmediateModeSupport.h
|
glew/glew.h
|
||||||
#OpenGLSupport.h
|
glew/glxew.h
|
||||||
#OpenGLVertexBufferObjectSupport.h
|
glew/wglew.h
|
||||||
../common/OpenGLWidget.h
|
OpenGLImmediateModeSupport.h
|
||||||
../common/OpenGLWidget.inl
|
OpenGLSupport.h
|
||||||
../common/PolyVoxExample.h
|
OpenGLVertexBufferObjectSupport.h
|
||||||
|
OpenGLWidget.h
|
||||||
Shapes.h
|
Shapes.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ADD_DEFINITIONS(-DGLEW_STATIC)
|
||||||
|
|
||||||
#"Sources" and "Headers" are the group names in Visual Studio.
|
#"Sources" and "Headers" are the group names in Visual Studio.
|
||||||
#They may have other uses too...
|
#They may have other uses too...
|
||||||
SOURCE_GROUP("Sources" FILES ${SRC_FILES})
|
SOURCE_GROUP("Sources" FILES ${SRC_FILES})
|
||||||
SOURCE_GROUP("Headers" FILES ${INC_FILES})
|
SOURCE_GROUP("Headers" FILES ${INC_FILES})
|
||||||
|
|
||||||
|
FIND_PACKAGE(OpenGL REQUIRED)
|
||||||
|
|
||||||
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
#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} ../common)
|
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_SOURCE_DIR}/include)
|
||||||
|
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
||||||
#This will include the shader files inside the compiled binary
|
|
||||||
QT5_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
|
||||||
QT5_ADD_RESOURCES(OPENGL_EXAMPLE_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})
|
|
||||||
|
|
||||||
#Build
|
#Build
|
||||||
ADD_EXECUTABLE(OpenGLExample ${SRC_FILES} ${COMMON_RESOURCES_RCC} ${OPENGL_EXAMPLE_RESOURCES_RCC})
|
ADD_EXECUTABLE(OpenGLExample ${SRC_FILES})
|
||||||
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 Qt5::OpenGL)
|
TARGET_LINK_LIBRARIES(OpenGLExample ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
||||||
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
|
||||||
|
63
examples/OpenGL/OpenGLImmediateModeSupport.cpp
Normal file
63
examples/OpenGL/OpenGLImmediateModeSupport.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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();
|
||||||
|
}
|
33
examples/OpenGL/OpenGLImmediateModeSupport.h
Normal file
33
examples/OpenGL/OpenGLImmediateModeSupport.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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__
|
66
examples/OpenGL/OpenGLSupport.cpp
Normal file
66
examples/OpenGL/OpenGLSupport.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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;
|
||||||
|
}
|
40
examples/OpenGL/OpenGLSupport.h
Normal file
40
examples/OpenGL/OpenGLSupport.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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__
|
124
examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp
Normal file
124
examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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);
|
||||||
|
}
|
42
examples/OpenGL/OpenGLVertexBufferObjectSupport.h
Normal file
42
examples/OpenGL/OpenGLVertexBufferObjectSupport.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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__
|
246
examples/OpenGL/OpenGLWidget.cpp
Normal file
246
examples/OpenGL/OpenGLWidget.cpp
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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);
|
||||||
|
|
||||||
|
polyvox_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())
|
||||||
|
{
|
||||||
|
polyvox_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);
|
||||||
|
}
|
83
examples/OpenGL/OpenGLWidget.h
Normal file
83
examples/OpenGL/OpenGLWidget.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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;
|
||||||
|
|
||||||
|
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> m_mapOpenGLSurfaceMeshes;
|
||||||
|
std::map<PolyVox::Vector3DUint8, polyvox_shared_ptr<PolyVox::SurfaceMesh<PolyVox::PositionMaterialNormal> > > m_mapSurfaceMeshes;
|
||||||
|
|
||||||
|
unsigned int m_uRegionSideLength;
|
||||||
|
unsigned int m_uVolumeWidthInRegions;
|
||||||
|
unsigned int m_uVolumeHeightInRegions;
|
||||||
|
unsigned int m_uVolumeDepthInRegions;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__PolyVox_OpenGLWidget_H__
|
@ -1,34 +1,33 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
The MIT License (MIT)
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
Copyright (c) 2015 David Williams and Matthew 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 hereby granted, free of charge, to any person obtaining a copy
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
including commercial applications, and to alter it and redistribute it
|
||||||
in the Software without restriction, including without limitation the rights
|
freely, subject to the following restrictions:
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
copies or substantial portions of the Software.
|
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.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
misrepresented as being the original software.
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
3. This notice may not be removed or altered from any source
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
distribution.
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "Shapes.h"
|
#include "Shapes.h"
|
||||||
|
|
||||||
#include "PolyVox/MaterialDensityPair.h"
|
#include "PolyVoxCore/MaterialDensityPair.h"
|
||||||
|
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
|
|
||||||
void createSphereInVolume(RawVolume<MaterialDensityPair88>& volData, float fRadius, uint8_t uValue)
|
void createSphereInVolume(LargeVolume<MaterialDensityPair44>& 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);
|
||||||
@ -41,33 +40,33 @@ void createSphereInVolume(RawVolume<MaterialDensityPair88>& volData, float fRadi
|
|||||||
for (int x = 0; x < volData.getWidth(); x++)
|
for (int x = 0; x < volData.getWidth(); x++)
|
||||||
{
|
{
|
||||||
//Store our current position as a vector...
|
//Store our current position as a vector...
|
||||||
Vector3DInt32 v3dCurrentPos(x, y, z);
|
Vector3DInt32 v3dCurrentPos(x,y,z);
|
||||||
//And compute how far the current position is from the center of the volume
|
//And compute how far the current position is from the center of the volume
|
||||||
double fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
double fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
||||||
|
|
||||||
//If the current voxel is less than 'radius' units from the center
|
//If the current voxel is less than 'radius' units from the center
|
||||||
//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.setVoxel(x, y, z, MaterialDensityPair88(uValue, uValue > 0 ? MaterialDensityPair88::getMaxDensity() : MaterialDensityPair88::getMinDensity()));
|
volData.setVoxelAt(x,y,z, MaterialDensityPair44(uValue, uValue > 0 ? MaterialDensityPair44::getMaxDensity() : MaterialDensityPair44::getMinDensity()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void createCubeInVolume(RawVolume<MaterialDensityPair88>& volData, Vector3DInt32 lowerCorner, Vector3DInt32 upperCorner, uint8_t uValue)
|
void createCubeInVolume(LargeVolume<MaterialDensityPair44>& volData, Vector3DInt32 lowerCorner, Vector3DInt32 upperCorner, uint8_t uValue)
|
||||||
{
|
{
|
||||||
uint8_t maxDen = static_cast<uint8_t>(MaterialDensityPair88::getMaxDensity());
|
uint8_t maxDen = MaterialDensityPair44::getMaxDensity();
|
||||||
uint8_t minDen = static_cast<uint8_t>(MaterialDensityPair88::getMinDensity());
|
uint8_t minDen = MaterialDensityPair44::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++)
|
||||||
{
|
{
|
||||||
for (int y = lowerCorner.getY(); y <= upperCorner.getY(); y++)
|
for (int y = lowerCorner.getY(); y <= upperCorner.getY(); y++)
|
||||||
{
|
{
|
||||||
for (int x = lowerCorner.getX(); x <= upperCorner.getX(); x++)
|
for (int x = lowerCorner.getX() ; x <= upperCorner.getX(); x++)
|
||||||
{
|
{
|
||||||
volData.setVoxel(x, y, z, MaterialDensityPair88(uValue, uValue > 0 ? maxDen : minDen));
|
volData.setVoxelAt(x,y,z, MaterialDensityPair44(uValue, uValue > 0 ? maxDen : minDen));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,33 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
The MIT License (MIT)
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
Copyright (c) 2015 David Williams and Matthew 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 hereby granted, free of charge, to any person obtaining a copy
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
including commercial applications, and to alter it and redistribute it
|
||||||
in the Software without restriction, including without limitation the rights
|
freely, subject to the following restrictions:
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
copies or substantial portions of the Software.
|
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.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
misrepresented as being the original software.
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
3. This notice may not be removed or altered from any source
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
distribution.
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __OpenGLExample_Shapes_H__
|
#ifndef __OpenGLExample_Shapes_H__
|
||||||
#define __OpenGLExample_Shapes_H__
|
#define __OpenGLExample_Shapes_H__
|
||||||
|
|
||||||
#include "PolyVox/RawVolume.h"
|
#include "PolyVoxCore/LargeVolume.h"
|
||||||
#include "PolyVox/MaterialDensityPair.h"
|
#include "PolyVoxCore/MaterialDensityPair.h"
|
||||||
|
|
||||||
void createSphereInVolume(PolyVox::RawVolume<PolyVox::MaterialDensityPair88>& volData, float fRadius, uint8_t uValue);
|
void createSphereInVolume(PolyVox::LargeVolume<PolyVox::MaterialDensityPair44>& volData, float fRadius, uint8_t uValue);
|
||||||
void createCubeInVolume(PolyVox::RawVolume<PolyVox::MaterialDensityPair88>& volData, PolyVox::Vector3DInt32 lowerCorner, PolyVox::Vector3DInt32 upperCorner, uint8_t uValue);
|
void createCubeInVolume(PolyVox::LargeVolume<PolyVox::MaterialDensityPair44>& volData, PolyVox::Vector3DInt32 lowerCorner, PolyVox::Vector3DInt32 upperCorner, uint8_t uValue);
|
||||||
|
|
||||||
#endif //__OpenGLExample_Shapes_H__
|
#endif //__OpenGLExample_Shapes_H__
|
73
examples/OpenGL/glew/LICENSE.txt
Normal file
73
examples/OpenGL/glew/LICENSE.txt
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
The OpenGL Extension Wrangler Library
|
||||||
|
Copyright (C) 2002-2007, Milan Ikits <milan ikits[]ieee org>
|
||||||
|
Copyright (C) 2002-2007, Marcelo E. Magallon <mmagallo[]debian org>
|
||||||
|
Copyright (C) 2002, Lev Povalahev
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
* The name of the author may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
Mesa 3-D graphics library
|
||||||
|
Version: 7.0
|
||||||
|
|
||||||
|
Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (c) 2007 The Khronos Group Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and/or associated documentation files (the
|
||||||
|
"Materials"), to deal in the Materials without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Materials, and to
|
||||||
|
permit persons to whom the Materials are furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Materials.
|
||||||
|
|
||||||
|
THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
16972
examples/OpenGL/glew/glew.cpp
Normal file
16972
examples/OpenGL/glew/glew.cpp
Normal file
File diff suppressed because it is too large
Load Diff
17132
examples/OpenGL/glew/glew.h
Normal file
17132
examples/OpenGL/glew/glew.h
Normal file
File diff suppressed because it is too large
Load Diff
1637
examples/OpenGL/glew/glxew.h
Normal file
1637
examples/OpenGL/glew/glxew.h
Normal file
File diff suppressed because it is too large
Load Diff
1397
examples/OpenGL/glew/wglew.h
Normal file
1397
examples/OpenGL/glew/wglew.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,38 +1,39 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
The MIT License (MIT)
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
Copyright (c) 2015 David Williams and Matthew 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 hereby granted, free of charge, to any person obtaining a copy
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
including commercial applications, and to alter it and redistribute it
|
||||||
in the Software without restriction, including without limitation the rights
|
freely, subject to the following restrictions:
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
copies or substantial portions of the Software.
|
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.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
misrepresented as being the original software.
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
3. This notice may not be removed or altered from any source
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
distribution.
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVox/FilePager.h"
|
#include "PolyVoxCore/Log.h"
|
||||||
#include "PolyVox/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVoxCore/MaterialDensityPair.h"
|
||||||
#include "PolyVox/MaterialDensityPair.h"
|
#include "PolyVoxCore/LargeVolume.h"
|
||||||
#include "PolyVox/LowPassFilter.h"
|
#include "PolyVoxCore/LowPassFilter.h"
|
||||||
#include "PolyVox/RawVolume.h"
|
#include "PolyVoxCore/RawVolume.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 "PolyVoxExample.h"
|
#include "OpenGLWidget.h"
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <windows.h> // Standard Header For Most Programs
|
#include <windows.h> // Standard Header For Most Programs
|
||||||
@ -46,20 +47,33 @@ using namespace std;
|
|||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
const int32_t g_uVolumeSideLength = 128;
|
void exampleLog(string message, int severity)
|
||||||
|
|
||||||
class OpenGLExample : public PolyVoxExample
|
|
||||||
{
|
{
|
||||||
public:
|
//Identify how severe the mesage is
|
||||||
OpenGLExample(QWidget *parent)
|
switch(severity)
|
||||||
:PolyVoxExample(parent)
|
|
||||||
{
|
{
|
||||||
|
case LS_DEBUG:
|
||||||
|
cout << "DEBUG: ";
|
||||||
|
break;
|
||||||
|
case LS_INFO:
|
||||||
|
cout << "INFO: ";
|
||||||
|
break;
|
||||||
|
case LS_WARN:
|
||||||
|
cout << "WARN: ";
|
||||||
|
break;
|
||||||
|
case LS_ERROR:
|
||||||
|
cout << "ERROR: ";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
//Print the message
|
||||||
void initializeExample() override
|
cout << message << endl;
|
||||||
{
|
}
|
||||||
RawVolume<MaterialDensityPair88> volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(g_uVolumeSideLength - 1, g_uVolumeSideLength - 1, g_uVolumeSideLength - 1)));
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
logHandler = &exampleLog;
|
||||||
|
LargeVolume<MaterialDensityPair44> volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(g_uVolumeSideLength-1, g_uVolumeSideLength-1, g_uVolumeSideLength-1)));
|
||||||
|
|
||||||
//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;
|
||||||
@ -78,79 +92,37 @@ protected:
|
|||||||
createSphereInVolume(volData, 20.0f, 1);
|
createSphereInVolume(volData, 20.0f, 1);
|
||||||
|
|
||||||
cout << "Creating cubes" << std::endl;
|
cout << "Creating cubes" << std::endl;
|
||||||
createCubeInVolume(volData, Vector3DInt32(minPos, minPos, midPos + 1), Vector3DInt32(midPos - 1, midPos - 1, maxPos), 0);
|
createCubeInVolume(volData, Vector3DInt32(minPos, minPos, minPos), Vector3DInt32(midPos-1, midPos-1, midPos-1), 0);
|
||||||
createCubeInVolume(volData, Vector3DInt32(midPos + 1, midPos + 1, midPos + 1), Vector3DInt32(maxPos, maxPos, maxPos), 0);
|
createCubeInVolume(volData, Vector3DInt32(midPos+1, midPos+1, minPos), Vector3DInt32(maxPos, maxPos, midPos-1), 0);
|
||||||
createCubeInVolume(volData, Vector3DInt32(minPos, midPos + 1, minPos), Vector3DInt32(midPos - 1, maxPos, midPos - 1), 0);
|
createCubeInVolume(volData, Vector3DInt32(midPos+1, minPos, midPos+1), Vector3DInt32(maxPos, midPos-1, maxPos), 0);
|
||||||
createCubeInVolume(volData, Vector3DInt32(midPos + 1, minPos, minPos), Vector3DInt32(maxPos, midPos - 1, midPos - 1), 0);
|
createCubeInVolume(volData, Vector3DInt32(minPos, midPos+1, midPos+1), Vector3DInt32(midPos-1, maxPos, maxPos), 0);
|
||||||
|
|
||||||
createCubeInVolume(volData, Vector3DInt32(1, midPos - 10, midPos - 10), Vector3DInt32(maxPos - 1, midPos + 10, midPos + 10), MaterialDensityPair44::getMaxDensity());
|
createCubeInVolume(volData, Vector3DInt32(1, midPos-10, midPos-10), Vector3DInt32(maxPos-1, midPos+10, 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, 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());
|
||||||
|
|
||||||
QSharedPointer<QGLShaderProgram> shader(new QGLShaderProgram);
|
//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();
|
||||||
|
|
||||||
if (!shader->addShaderFromSourceFile(QGLShader::Vertex, ":/openglexample.vert"))
|
QApplication app(argc, argv);
|
||||||
{
|
|
||||||
std::cerr << shader->log().toStdString() << std::endl;
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!shader->addShaderFromSourceFile(QGLShader::Fragment, ":/openglexample.frag"))
|
OpenGLWidget openGLWidget(0);
|
||||||
{
|
|
||||||
std::cerr << shader->log().toStdString() << std::endl;
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
setShader(shader);
|
|
||||||
|
openGLWidget.show();
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
const int32_t extractedRegionSize = 32;
|
//return 0;
|
||||||
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.
|
|
||||||
addMesh(decodedMesh, decodedMesh.getOffset());
|
|
||||||
|
|
||||||
meshCounter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cout << "Rendering volume as " << meshCounter << " seperate meshes" << endl;
|
|
||||||
|
|
||||||
setCameraTransform(QVector3D(150.0f, 150.0f, 150.0f), -(PI / 4.0f), PI + (PI / 4.0f));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
//Create and show the Qt OpenGL window
|
|
||||||
QApplication app(argc, argv);
|
|
||||||
OpenGLExample openGLWidget(0);
|
|
||||||
openGLWidget.show();
|
|
||||||
|
|
||||||
//Run the message pump.
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
#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
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
<!DOCTYPE RCC><RCC version="1.0">
|
|
||||||
<qresource>
|
|
||||||
<file>openglexample.vert</file>
|
|
||||||
<file>openglexample.frag</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
@ -1,26 +0,0 @@
|
|||||||
#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 projectionMatrix;
|
|
||||||
uniform mat4 viewMatrix;
|
|
||||||
uniform mat4 modelMatrix;
|
|
||||||
|
|
||||||
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 = projectionMatrix * viewMatrix * modelMatrix * 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;
|
|
||||||
}
|
|
@ -1,64 +1,66 @@
|
|||||||
################################################################################
|
# Copyright (c) 2010-2012 David Williams
|
||||||
# The MIT License (MIT)
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2015 Matthew Williams and 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 hereby granted, free of charge, to any person obtaining a copy
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# in the Software without restriction, including without limitation the rights
|
# freely, subject to the following restrictions:
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
#
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
# 1. The origin of this software must not be misrepresented; you must not
|
||||||
# copies or substantial portions of the Software.
|
# 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.
|
||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# misrepresented as being the original software.
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
#
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# 3. This notice may not be removed or altered from any source
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# distribution.
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||||
################################################################################
|
|
||||||
|
|
||||||
PROJECT(PagingExample)
|
PROJECT(PagingExample)
|
||||||
|
|
||||||
#Projects source files
|
#Projects source files
|
||||||
SET(SRC_FILES
|
SET(SRC_FILES
|
||||||
|
glew/glew.cpp
|
||||||
|
|
||||||
main.cpp
|
main.cpp
|
||||||
|
OpenGLWidget.cpp
|
||||||
Perlin.cpp
|
Perlin.cpp
|
||||||
../common/PolyVoxExample.cpp
|
)
|
||||||
)
|
|
||||||
|
|
||||||
#Projects headers files
|
#Projects headers files
|
||||||
SET(INC_FILES
|
SET(INC_FILES
|
||||||
../common/OpenGLWidget.h
|
glew/glew.h
|
||||||
../common/OpenGLWidget.inl
|
glew/glxew.h
|
||||||
|
glew/wglew.h
|
||||||
|
|
||||||
|
OpenGLWidget.h
|
||||||
Perlin.h
|
Perlin.h
|
||||||
../common/PolyVoxExample.h
|
)
|
||||||
)
|
|
||||||
|
ADD_DEFINITIONS(-DGLEW_STATIC)
|
||||||
|
|
||||||
#"Sources" and "Headers" are the group names in Visual Studio.
|
#"Sources" and "Headers" are the group names in Visual Studio.
|
||||||
#They may have other uses too...
|
#They may have other uses too...
|
||||||
SOURCE_GROUP("Sources" FILES ${SRC_FILES})
|
SOURCE_GROUP("Sources" FILES ${SRC_FILES})
|
||||||
SOURCE_GROUP("Headers" FILES ${INC_FILES})
|
SOURCE_GROUP("Headers" FILES ${INC_FILES})
|
||||||
|
|
||||||
|
FIND_PACKAGE(OpenGL REQUIRED)
|
||||||
|
|
||||||
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
#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} ../common)
|
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_SOURCE_DIR}/include)
|
||||||
|
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
||||||
#This will include the shader files inside the compiled binary
|
|
||||||
QT5_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} ${COMMON_RESOURCES_RCC})
|
ADD_EXECUTABLE(PagingExample ${SRC_FILES})
|
||||||
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 Qt5::OpenGL)
|
TARGET_LINK_LIBRARIES(PagingExample ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
||||||
SET_PROPERTY(TARGET PagingExample PROPERTY FOLDER "Examples")
|
SET_PROPERTY(TARGET PagingExample PROPERTY FOLDER "Examples")
|
||||||
|
|
||||||
#Install - Only install the example in Windows
|
#Install - Only install the example in Windows
|
||||||
|
135
examples/Paging/OpenGLWidget.cpp
Normal file
135
examples/Paging/OpenGLWidget.cpp
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#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();
|
||||||
|
}
|
67
examples/Paging/OpenGLWidget.h
Normal file
67
examples/Paging/OpenGLWidget.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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__
|
@ -42,12 +42,12 @@ float Perlin::noise1(float arg)
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
setup(0, bx0, bx1, rx0, rx1);
|
setup(0, bx0,bx1, rx0,rx1);
|
||||||
|
|
||||||
sx = s_curve(rx0);
|
sx = s_curve(rx0);
|
||||||
|
|
||||||
u = rx0 * g1[p[bx0]];
|
u = rx0 * g1[ p[ bx0 ] ];
|
||||||
v = rx1 * g1[p[bx1]];
|
v = rx1 * g1[ p[ bx1 ] ];
|
||||||
|
|
||||||
return lerp(sx, u, v);
|
return lerp(sx, u, v);
|
||||||
}
|
}
|
||||||
@ -65,8 +65,8 @@ float Perlin::noise2(float vec[2])
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
setup(0, bx0, bx1, rx0, rx1);
|
setup(0,bx0,bx1,rx0,rx1);
|
||||||
setup(1, by0, by1, ry0, ry1);
|
setup(1,by0,by1,ry0,ry1);
|
||||||
|
|
||||||
i = p[bx0];
|
i = p[bx0];
|
||||||
j = p[bx1];
|
j = p[bx1];
|
||||||
@ -79,18 +79,18 @@ float Perlin::noise2(float vec[2])
|
|||||||
sx = s_curve(rx0);
|
sx = s_curve(rx0);
|
||||||
sy = s_curve(ry0);
|
sy = s_curve(ry0);
|
||||||
|
|
||||||
#define at2(rx,ry) ( rx * q[0] + ry * q[1] )
|
#define at2(rx,ry) ( rx * q[0] + ry * q[1] )
|
||||||
|
|
||||||
q = g2[b00];
|
q = g2[b00];
|
||||||
u = at2(rx0, ry0);
|
u = at2(rx0,ry0);
|
||||||
q = g2[b10];
|
q = g2[b10];
|
||||||
v = at2(rx1, ry0);
|
v = at2(rx1,ry0);
|
||||||
a = lerp(sx, u, v);
|
a = lerp(sx, u, v);
|
||||||
|
|
||||||
q = g2[b01];
|
q = g2[b01];
|
||||||
u = at2(rx0, ry1);
|
u = at2(rx0,ry1);
|
||||||
q = g2[b11];
|
q = g2[b11];
|
||||||
v = at2(rx1, ry1);
|
v = at2(rx1,ry1);
|
||||||
b = lerp(sx, u, v);
|
b = lerp(sx, u, v);
|
||||||
|
|
||||||
return lerp(sy, a, b);
|
return lerp(sy, a, b);
|
||||||
@ -109,40 +109,40 @@ float Perlin::noise3(float vec[3])
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
setup(0, bx0, bx1, rx0, rx1);
|
setup(0, bx0,bx1, rx0,rx1);
|
||||||
setup(1, by0, by1, ry0, ry1);
|
setup(1, by0,by1, ry0,ry1);
|
||||||
setup(2, bz0, bz1, rz0, rz1);
|
setup(2, bz0,bz1, rz0,rz1);
|
||||||
|
|
||||||
i = p[bx0];
|
i = p[ bx0 ];
|
||||||
j = p[bx1];
|
j = p[ bx1 ];
|
||||||
|
|
||||||
b00 = p[i + by0];
|
b00 = p[ i + by0 ];
|
||||||
b10 = p[j + by0];
|
b10 = p[ j + by0 ];
|
||||||
b01 = p[i + by1];
|
b01 = p[ i + by1 ];
|
||||||
b11 = p[j + by1];
|
b11 = p[ j + by1 ];
|
||||||
|
|
||||||
t = s_curve(rx0);
|
t = s_curve(rx0);
|
||||||
sy = s_curve(ry0);
|
sy = s_curve(ry0);
|
||||||
sz = s_curve(rz0);
|
sz = s_curve(rz0);
|
||||||
|
|
||||||
#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
|
#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
|
||||||
|
|
||||||
q = g3[b00 + bz0]; u = at3(rx0, ry0, rz0);
|
q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0);
|
||||||
q = g3[b10 + bz0]; v = at3(rx1, ry0, rz0);
|
q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0);
|
||||||
a = lerp(t, u, v);
|
a = lerp(t, u, v);
|
||||||
|
|
||||||
q = g3[b01 + bz0]; u = at3(rx0, ry1, rz0);
|
q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0);
|
||||||
q = g3[b11 + bz0]; v = at3(rx1, ry1, rz0);
|
q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0);
|
||||||
b = lerp(t, u, v);
|
b = lerp(t, u, v);
|
||||||
|
|
||||||
c = lerp(sy, a, b);
|
c = lerp(sy, a, b);
|
||||||
|
|
||||||
q = g3[b00 + bz1]; u = at3(rx0, ry0, rz1);
|
q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1);
|
||||||
q = g3[b10 + bz1]; v = at3(rx1, ry0, rz1);
|
q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1);
|
||||||
a = lerp(t, u, v);
|
a = lerp(t, u, v);
|
||||||
|
|
||||||
q = g3[b01 + bz1]; u = at3(rx0, ry1, rz1);
|
q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1);
|
||||||
q = g3[b11 + bz1]; v = at3(rx1, ry1, rz1);
|
q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1);
|
||||||
b = lerp(t, u, v);
|
b = lerp(t, u, v);
|
||||||
|
|
||||||
d = lerp(sy, a, b);
|
d = lerp(sy, a, b);
|
||||||
@ -155,7 +155,7 @@ void Perlin::normalize2(float v[2])
|
|||||||
float s;
|
float s;
|
||||||
|
|
||||||
s = (float)sqrt(v[0] * v[0] + v[1] * v[1]);
|
s = (float)sqrt(v[0] * v[0] + v[1] * v[1]);
|
||||||
s = 1.0f / s;
|
s = 1.0f/s;
|
||||||
v[0] = v[0] * s;
|
v[0] = v[0] * s;
|
||||||
v[1] = v[1] * s;
|
v[1] = v[1] * s;
|
||||||
}
|
}
|
||||||
@ -165,7 +165,7 @@ void Perlin::normalize3(float v[3])
|
|||||||
float s;
|
float s;
|
||||||
|
|
||||||
s = (float)sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
s = (float)sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
||||||
s = 1.0f / s;
|
s = 1.0f/s;
|
||||||
|
|
||||||
v[0] = v[0] * s;
|
v[0] = v[0] * s;
|
||||||
v[1] = v[1] * s;
|
v[1] = v[1] * s;
|
||||||
@ -176,14 +176,14 @@ void Perlin::init(void)
|
|||||||
{
|
{
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
|
|
||||||
for (i = 0; i < B; i++)
|
for (i = 0 ; i < B ; i++)
|
||||||
{
|
{
|
||||||
p[i] = i;
|
p[i] = i;
|
||||||
g1[i] = (float)((rand() % (B + B)) - B) / B;
|
g1[i] = (float)((rand() % (B + B)) - B) / B;
|
||||||
for (j = 0; j < 2; j++)
|
for (j = 0 ; j < 2 ; j++)
|
||||||
g2[i][j] = (float)((rand() % (B + B)) - B) / B;
|
g2[i][j] = (float)((rand() % (B + B)) - B) / B;
|
||||||
normalize2(g2[i]);
|
normalize2(g2[i]);
|
||||||
for (j = 0; j < 3; j++)
|
for (j = 0 ; j < 3 ; j++)
|
||||||
g3[i][j] = (float)((rand() % (B + B)) - B) / B;
|
g3[i][j] = (float)((rand() % (B + B)) - B) / B;
|
||||||
normalize3(g3[i]);
|
normalize3(g3[i]);
|
||||||
}
|
}
|
||||||
@ -195,13 +195,13 @@ void Perlin::init(void)
|
|||||||
p[j] = k;
|
p[j] = k;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < B + 2; i++)
|
for (i = 0 ; i < B + 2 ; i++)
|
||||||
{
|
{
|
||||||
p[B + i] = p[i];
|
p[B + i] = p[i];
|
||||||
g1[B + i] = g1[i];
|
g1[B + i] = g1[i];
|
||||||
for (j = 0; j < 2; j++)
|
for (j = 0 ; j < 2 ; j++)
|
||||||
g2[B + i][j] = g2[i][j];
|
g2[B + i][j] = g2[i][j];
|
||||||
for (j = 0; j < 3; j++)
|
for (j = 0 ; j < 3 ; j++)
|
||||||
g3[B + i][j] = g3[i][j];
|
g3[B + i][j] = g3[i][j];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,15 +214,15 @@ float Perlin::perlin_noise_2D(float vec[2])
|
|||||||
float result = 0.0f;
|
float result = 0.0f;
|
||||||
float amp = mAmplitude;
|
float amp = mAmplitude;
|
||||||
|
|
||||||
vec[0] *= mFrequency;
|
vec[0]*=mFrequency;
|
||||||
vec[1] *= mFrequency;
|
vec[1]*=mFrequency;
|
||||||
|
|
||||||
for (int i = 0; i < terms; i++)
|
for( int i=0; i<terms; i++ )
|
||||||
{
|
{
|
||||||
result += noise2(vec)*amp;
|
result += noise2(vec)*amp;
|
||||||
vec[0] *= 2.0f;
|
vec[0] *= 2.0f;
|
||||||
vec[1] *= 2.0f;
|
vec[1] *= 2.0f;
|
||||||
amp *= 0.5f;
|
amp*=0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -235,17 +235,17 @@ float Perlin::perlin_noise_3D(float vec[3])
|
|||||||
float result = 0.0f;
|
float result = 0.0f;
|
||||||
float amp = mAmplitude;
|
float amp = mAmplitude;
|
||||||
|
|
||||||
vec[0] *= mFrequency;
|
vec[0]*=mFrequency;
|
||||||
vec[1] *= mFrequency;
|
vec[1]*=mFrequency;
|
||||||
vec[2] *= mFrequency;
|
vec[2]*=mFrequency;
|
||||||
|
|
||||||
for (int i = 0; i < terms; i++)
|
for( int i=0; i<terms; i++ )
|
||||||
{
|
{
|
||||||
result += noise3(vec)*amp;
|
result += noise3(vec)*amp;
|
||||||
vec[0] *= 2.0f;
|
vec[0] *= 2.0f;
|
||||||
vec[1] *= 2.0f;
|
vec[1] *= 2.0f;
|
||||||
vec[2] *= 2.0f;
|
vec[2] *= 2.0f;
|
||||||
amp *= 0.5f;
|
amp*=0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -254,7 +254,7 @@ float Perlin::perlin_noise_3D(float vec[3])
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Perlin::Perlin(int octaves, float freq, float amp, int seed)
|
Perlin::Perlin(int octaves,float freq,float amp,int seed)
|
||||||
{
|
{
|
||||||
mOctaves = octaves;
|
mOctaves = octaves;
|
||||||
mFrequency = freq;
|
mFrequency = freq;
|
||||||
|
73
examples/Paging/glew/LICENSE.txt
Normal file
73
examples/Paging/glew/LICENSE.txt
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
The OpenGL Extension Wrangler Library
|
||||||
|
Copyright (C) 2002-2007, Milan Ikits <milan ikits[]ieee org>
|
||||||
|
Copyright (C) 2002-2007, Marcelo E. Magallon <mmagallo[]debian org>
|
||||||
|
Copyright (C) 2002, Lev Povalahev
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
* The name of the author may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
Mesa 3-D graphics library
|
||||||
|
Version: 7.0
|
||||||
|
|
||||||
|
Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (c) 2007 The Khronos Group Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and/or associated documentation files (the
|
||||||
|
"Materials"), to deal in the Materials without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Materials, and to
|
||||||
|
permit persons to whom the Materials are furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Materials.
|
||||||
|
|
||||||
|
THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
16972
examples/Paging/glew/glew.cpp
Normal file
16972
examples/Paging/glew/glew.cpp
Normal file
File diff suppressed because it is too large
Load Diff
17132
examples/Paging/glew/glew.h
Normal file
17132
examples/Paging/glew/glew.h
Normal file
File diff suppressed because it is too large
Load Diff
1637
examples/Paging/glew/glxew.h
Normal file
1637
examples/Paging/glew/glxew.h
Normal file
File diff suppressed because it is too large
Load Diff
1397
examples/Paging/glew/wglew.h
Normal file
1397
examples/Paging/glew/wglew.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,83 +1,226 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
The MIT License (MIT)
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
Copyright (c) 2015 David Williams and Matthew 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 hereby granted, free of charge, to any person obtaining a copy
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
including commercial applications, and to alter it and redistribute it
|
||||||
in the Software without restriction, including without limitation the rights
|
freely, subject to the following restrictions:
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
copies or substantial portions of the Software.
|
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.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
misrepresented as being the original software.
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
3. This notice may not be removed or altered from any source
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
distribution.
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVoxExample.h"
|
#include "OpenGLWidget.h"
|
||||||
#include "Perlin.h"
|
#include "Perlin.h"
|
||||||
|
|
||||||
#include "PolyVox/MaterialDensityPair.h"
|
#include "PolyVoxCore/MaterialDensityPair.h"
|
||||||
#include "PolyVox/CubicSurfaceExtractor.h"
|
#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.h"
|
||||||
#include "PolyVox/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVox/Mesh.h"
|
#include "PolyVoxCore/SurfaceMesh.h"
|
||||||
#include "PolyVox/PagedVolume.h"
|
#include "PolyVoxCore/LargeVolume.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
// Use the PolyVox namespace
|
//Use the PolyVox namespace
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
|
|
||||||
/**
|
void createPerlinVolumeSlow(LargeVolume<MaterialDensityPair44>& volData)
|
||||||
* Generates data using Perlin noise.
|
|
||||||
*/
|
|
||||||
class PerlinNoisePager : public PolyVox::PagedVolume<MaterialDensityPair44>::Pager
|
|
||||||
{
|
{
|
||||||
public:
|
Perlin perlin(2,8,1,234);
|
||||||
/// Constructor
|
|
||||||
PerlinNoisePager()
|
|
||||||
:PagedVolume<MaterialDensityPair44>::Pager()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Destructor
|
for(int z = 1; z < 256-1; z++)
|
||||||
virtual ~PerlinNoisePager() {};
|
{
|
||||||
|
std::cout << z << std::endl;
|
||||||
|
for(int y = 1; y < 256-1; y++)
|
||||||
|
{
|
||||||
|
for(int x = 1; x < 256-1; x++)
|
||||||
|
{
|
||||||
|
float perlinVal = perlin.Get3D(x /static_cast<float>(256-1), (y) / static_cast<float>(256-1), z / static_cast<float>(256-1));
|
||||||
|
|
||||||
virtual void pageIn(const PolyVox::Region& region, PagedVolume<MaterialDensityPair44>::Chunk* pChunk)
|
|
||||||
{
|
|
||||||
Perlin perlin(2, 2, 1, 234);
|
|
||||||
|
|
||||||
for (int x = region.getLowerX(); x <= region.getUpperX(); x++)
|
|
||||||
{
|
|
||||||
for (int y = region.getLowerY(); y <= region.getUpperY(); y++)
|
|
||||||
{
|
|
||||||
float perlinVal = perlin.Get(x / static_cast<float>(255 - 1), y / static_cast<float>(255 - 1));
|
|
||||||
perlinVal += 1.0f;
|
perlinVal += 1.0f;
|
||||||
perlinVal *= 0.5f;
|
perlinVal *= 0.5f;
|
||||||
perlinVal *= 255;
|
perlinVal *= MaterialDensityPair44::getMaxDensity();
|
||||||
for (int z = region.getLowerZ(); z <= region.getUpperZ(); z++)
|
|
||||||
{
|
|
||||||
MaterialDensityPair44 voxel;
|
MaterialDensityPair44 voxel;
|
||||||
if (z < perlinVal)
|
|
||||||
|
voxel.setMaterial(245);
|
||||||
|
voxel.setDensity(perlinVal);
|
||||||
|
|
||||||
|
/*if(perlinVal < 0.0f)
|
||||||
{
|
{
|
||||||
const int xpos = 50;
|
voxel.setMaterial(245);
|
||||||
const int zpos = 100;
|
voxel.setDensity(MaterialDensityPair44::getMaxDensity());
|
||||||
if ((x - xpos)*(x - xpos) + (z - zpos)*(z - zpos) < 200)
|
|
||||||
{
|
|
||||||
// tunnel
|
|
||||||
voxel.setMaterial(0);
|
|
||||||
voxel.setDensity(MaterialDensityPair44::getMinDensity());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
voxel.setMaterial(0);
|
||||||
|
voxel.setDensity(MaterialDensityPair44::getMinDensity());
|
||||||
|
}*/
|
||||||
|
|
||||||
|
volData.setVoxelAt(x, y, z, voxel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*void createPerlinVolumeFast(LargeVolume<MaterialDensityPair44>& volData)
|
||||||
|
{
|
||||||
|
Perlin perlin(2,8,1,234);
|
||||||
|
|
||||||
|
for(int blockZ = 0; blockZ < volData.m_uDepthInBlocks; blockZ++)
|
||||||
|
{
|
||||||
|
std::cout << blockZ << std::endl;
|
||||||
|
for(int blockY = 0; blockY < volData.m_uHeightInBlocks; blockY++)
|
||||||
|
{
|
||||||
|
for(int blockX = 0; blockX < volData.m_uWidthInBlocks; blockX++)
|
||||||
|
{
|
||||||
|
for(int offsetz = 0; offsetz < volData.m_uBlockSideLength; offsetz++)
|
||||||
|
{
|
||||||
|
for(int offsety = 0; offsety < volData.m_uBlockSideLength; offsety++)
|
||||||
|
{
|
||||||
|
for(int offsetx = 0; offsetx < volData.m_uBlockSideLength; offsetx++)
|
||||||
|
{
|
||||||
|
int x = blockX * volData.m_uBlockSideLength + offsetx;
|
||||||
|
int y = blockY * volData.m_uBlockSideLength + offsety;
|
||||||
|
int z = blockZ * volData.m_uBlockSideLength + offsetz;
|
||||||
|
|
||||||
|
if((x == 0) || (x == volData.getWidth()-1)) continue;
|
||||||
|
if((y == 0) || (y == volData.getHeight()-1)) continue;
|
||||||
|
if((z == 0) || (z == volData.getDepth()-1)) continue;
|
||||||
|
|
||||||
|
float perlinVal = perlin.Get3D(x /static_cast<float>(volData.getWidth()-1), (y) / static_cast<float>(volData.getHeight()-1), z / static_cast<float>(volData.getDepth()-1));
|
||||||
|
|
||||||
|
MaterialDensityPair44 voxel;
|
||||||
|
if(perlinVal < 0.0f)
|
||||||
|
{
|
||||||
|
voxel.setMaterial(245);
|
||||||
|
voxel.setDensity(MaterialDensityPair44::getMaxDensity());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
voxel.setMaterial(0);
|
||||||
|
voxel.setDensity(MaterialDensityPair44::getMinDensity());
|
||||||
|
}
|
||||||
|
|
||||||
|
volData.setVoxelAt(x, y, z, voxel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
void createPerlinTerrain(LargeVolume<MaterialDensityPair44>& volData)
|
||||||
|
{
|
||||||
|
Perlin perlin(2,2,1,234);
|
||||||
|
|
||||||
|
for(int x = 1; x < 255-1; x++)
|
||||||
|
{
|
||||||
|
if(x%(255/100) == 0) {
|
||||||
|
std::cout << "." << std::flush;
|
||||||
|
}
|
||||||
|
for(int y = 1; y < 255-1; y++)
|
||||||
|
{
|
||||||
|
float perlinVal = perlin.Get(x / static_cast<float>(255-1), y / static_cast<float>(255-1));
|
||||||
|
perlinVal += 1.0f;
|
||||||
|
perlinVal *= 0.5f;
|
||||||
|
perlinVal *= 255;
|
||||||
|
for(int z = 1; z < 255-1; z++)
|
||||||
|
{
|
||||||
|
MaterialDensityPair44 voxel;
|
||||||
|
if(z < perlinVal)
|
||||||
|
{
|
||||||
|
voxel.setMaterial(245);
|
||||||
|
voxel.setDensity(MaterialDensityPair44::getMaxDensity());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
voxel.setMaterial(0);
|
||||||
|
voxel.setDensity(MaterialDensityPair44::getMinDensity());
|
||||||
|
}
|
||||||
|
|
||||||
|
volData.setVoxelAt(x, y, z, voxel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void createSphereInVolume(LargeVolume<MaterialDensityPair44>& volData, Vector3DFloat v3dVolCenter, float fRadius)
|
||||||
|
{
|
||||||
|
//This vector hold the position of the center of the volume
|
||||||
|
//Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
||||||
|
|
||||||
|
int iRadius = fRadius;
|
||||||
|
|
||||||
|
//This three-level for loop iterates over every voxel in the volume
|
||||||
|
for (int z = v3dVolCenter.getZ() - iRadius; z <= v3dVolCenter.getZ() + iRadius; z++)
|
||||||
|
{
|
||||||
|
for (int y = v3dVolCenter.getY() - iRadius; y <= v3dVolCenter.getY() + iRadius; y++)
|
||||||
|
{
|
||||||
|
for (int x = v3dVolCenter.getX() - iRadius; x <= v3dVolCenter.getX() + iRadius; 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();
|
||||||
|
|
||||||
|
//If the current voxel is less than 'radius' units from the center then we make it solid.
|
||||||
|
if(fDistToCenter <= fRadius)
|
||||||
|
{
|
||||||
|
//Our new density value
|
||||||
|
uint8_t uDensity = MaterialDensityPair44::getMaxDensity();
|
||||||
|
|
||||||
|
//Get the old voxel
|
||||||
|
MaterialDensityPair44 voxel = volData.getVoxelAt(x,y,z);
|
||||||
|
|
||||||
|
//Modify the density
|
||||||
|
voxel.setDensity(uDensity);
|
||||||
|
|
||||||
|
//Wrte the voxel value into the volume
|
||||||
|
volData.setVoxelAt(x, y, z, voxel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void load(const ConstVolumeProxy<MaterialDensityPair44>& volume, const PolyVox::Region& reg)
|
||||||
|
{
|
||||||
|
Perlin perlin(2,2,1,234);
|
||||||
|
|
||||||
|
for(int x = reg.getLowerCorner().getX(); x <= reg.getUpperCorner().getX(); x++)
|
||||||
|
{
|
||||||
|
for(int y = reg.getLowerCorner().getY(); y <= reg.getUpperCorner().getY(); y++)
|
||||||
|
{
|
||||||
|
float perlinVal = perlin.Get(x / static_cast<float>(255-1), y / static_cast<float>(255-1));
|
||||||
|
perlinVal += 1.0f;
|
||||||
|
perlinVal *= 0.5f;
|
||||||
|
perlinVal *= 255;
|
||||||
|
for(int z = reg.getLowerCorner().getZ(); z <= reg.getUpperCorner().getZ(); z++)
|
||||||
|
{
|
||||||
|
MaterialDensityPair44 voxel;
|
||||||
|
if(z < perlinVal)
|
||||||
|
{
|
||||||
|
const int xpos = 50;
|
||||||
|
const int zpos = 100;
|
||||||
|
if((x-xpos)*(x-xpos) + (z-zpos)*(z-zpos) < 200) {
|
||||||
|
// tunnel
|
||||||
|
voxel.setMaterial(0);
|
||||||
|
voxel.setDensity(MaterialDensityPair44::getMinDensity());
|
||||||
|
} else {
|
||||||
// solid
|
// solid
|
||||||
voxel.setMaterial(245);
|
voxel.setMaterial(245);
|
||||||
voxel.setDensity(MaterialDensityPair44::getMaxDensity());
|
voxel.setDensity(MaterialDensityPair44::getMaxDensity());
|
||||||
@ -89,66 +232,69 @@ public:
|
|||||||
voxel.setDensity(MaterialDensityPair44::getMinDensity());
|
voxel.setDensity(MaterialDensityPair44::getMinDensity());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Voxel position within a chunk always start from zero. So if a chunk represents region (4, 8, 12) to (11, 19, 15)
|
volume.setVoxelAt(x, y, z, voxel);
|
||||||
// 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 chunk space position.
|
|
||||||
pChunk->setVoxel(x - region.getLowerX(), y - region.getLowerY(), z - region.getLowerZ(), voxel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual void pageOut(const PolyVox::Region& region, PagedVolume<MaterialDensityPair44>::Chunk* /*pChunk*/)
|
void unload(const ConstVolumeProxy<MaterialDensityPair44>& /*vol*/, const PolyVox::Region& reg)
|
||||||
{
|
|
||||||
std::cout << "warning unloading region: " << region.getLowerCorner() << " -> " << region.getUpperCorner() << std::endl;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class PagingExample : public PolyVoxExample
|
|
||||||
{
|
{
|
||||||
public:
|
std::cout << "warning unloading region: " << reg.getLowerCorner() << " -> " << reg.getUpperCorner() << std::endl;
|
||||||
PagingExample(QWidget *parent)
|
}
|
||||||
:PolyVoxExample(parent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void initializeExample() override
|
|
||||||
{
|
|
||||||
PerlinNoisePager* pager = new PerlinNoisePager();
|
|
||||||
PagedVolume<MaterialDensityPair44> volData(pager, 8 * 1024 * 1024, 64);
|
|
||||||
|
|
||||||
// Just some tests of memory usage, etc.
|
|
||||||
std::cout << "Memory usage: " << (volData.calculateSizeInBytes() / 1024.0 / 1024.0) << "MB" << std::endl;
|
|
||||||
PolyVox::Region reg(Vector3DInt32(-255, 0, 0), Vector3DInt32(255, 255, 255));
|
|
||||||
std::cout << "Prefetching region: " << reg.getLowerCorner() << " -> " << reg.getUpperCorner() << std::endl;
|
|
||||||
volData.prefetch(reg);
|
|
||||||
std::cout << "Memory usage: " << (volData.calculateSizeInBytes() / 1024.0 / 1024.0) << "MB" << std::endl;
|
|
||||||
std::cout << "Flushing entire volume" << std::endl;
|
|
||||||
volData.flushAll();
|
|
||||||
std::cout << "Memory usage: " << (volData.calculateSizeInBytes() / 1024.0 / 1024.0) << "MB" << std::endl;
|
|
||||||
|
|
||||||
// Extract the surface
|
|
||||||
PolyVox::Region reg2(Vector3DInt32(0, 0, 0), Vector3DInt32(254, 254, 254));
|
|
||||||
auto mesh = extractCubicMesh(&volData, reg2);
|
|
||||||
std::cout << "#vertices: " << mesh.getNoOfVertices() << std::endl;
|
|
||||||
|
|
||||||
auto decodedMesh = decodeMesh(mesh);
|
|
||||||
|
|
||||||
// Pass the surface to the OpenGL window
|
|
||||||
addMesh(decodedMesh);
|
|
||||||
|
|
||||||
setCameraTransform(QVector3D(300.0f, 300.0f, 300.0f), -(PI / 4.0f), PI + (PI / 4.0f));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
// Create and show the Qt OpenGL window
|
//Create and show the Qt OpenGL window
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
PagingExample openGLWidget(0);
|
OpenGLWidget openGLWidget(0);
|
||||||
openGLWidget.show();
|
openGLWidget.show();
|
||||||
|
|
||||||
// Run the message pump.
|
//If these lines don't compile, please try commenting them out and using the two lines after
|
||||||
|
//(you will need Boost for this). If you have to do this then please let us know in the forums as
|
||||||
|
//we rely on community feedback to keep the Boost version running.
|
||||||
|
LargeVolume<MaterialDensityPair44> volData(&load, &unload, 256);
|
||||||
|
//LargeVolume<MaterialDensityPair44> volData(polyvox_bind(&load, polyvox_placeholder_1, polyvox_placeholder_2),
|
||||||
|
// polyvox_bind(&unload, polyvox_placeholder_1, polyvox_placeholder_2), 256);
|
||||||
|
volData.setMaxNumberOfBlocksInMemory(4096);
|
||||||
|
volData.setMaxNumberOfUncompressedBlocks(64);
|
||||||
|
|
||||||
|
//volData.dataRequiredHandler = &load;
|
||||||
|
//volData.dataOverflowHandler = &unload;
|
||||||
|
|
||||||
|
//volData.setMaxNumberOfUncompressedBlocks(4096);
|
||||||
|
//createSphereInVolume(volData, 30);
|
||||||
|
//createPerlinTerrain(volData);
|
||||||
|
//createPerlinVolumeSlow(volData);
|
||||||
|
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;
|
||||||
|
//volData.setBlockCacheSize(64);
|
||||||
|
PolyVox::Region reg(Vector3DInt32(-255,0,0), Vector3DInt32(255,255,255));
|
||||||
|
std::cout << "Prefetching region: " << reg.getLowerCorner() << " -> " << reg.getUpperCorner() << std::endl;
|
||||||
|
volData.prefetch(reg);
|
||||||
|
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;
|
||||||
|
PolyVox::Region reg2(Vector3DInt32(0,0,0), Vector3DInt32(255,255,255));
|
||||||
|
std::cout << "Flushing region: " << reg2.getLowerCorner() << " -> " << reg2.getUpperCorner() << std::endl;
|
||||||
|
volData.flush(reg2);
|
||||||
|
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 << "Flushing entire volume" << std::endl;
|
||||||
|
volData.flushAll();
|
||||||
|
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
||||||
|
std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
||||||
|
|
||||||
|
//Extract the surface
|
||||||
|
SurfaceMesh<PositionMaterialNormal> mesh;
|
||||||
|
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;
|
||||||
|
|
||||||
|
//Pass the surface to the OpenGL window
|
||||||
|
openGLWidget.setSurfaceMeshToRender(mesh);
|
||||||
|
|
||||||
|
//Run the message pump.
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# The MIT License (MIT)
|
|
||||||
#
|
|
||||||
# Copyright (c) 2015 Matthew Williams and David Williams
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
|
||||||
# in the Software without restriction, including without limitation the rights
|
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
|
||||||
# copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
PROJECT(PythonExample)
|
|
||||||
|
|
||||||
configure_file(PythonExample.py PythonExample.py COPYONLY)
|
|
@ -1,257 +0,0 @@
|
|||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# The MIT License (MIT)
|
|
||||||
#
|
|
||||||
# Copyright (c) 2015 Matthew Williams and David Williams
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
|
||||||
# in the Software without restriction, including without limitation the rights
|
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
|
||||||
# copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
import sys
|
|
||||||
sys.path.append("../../library/bindings/") #This is just to point to the generated bindings
|
|
||||||
|
|
||||||
import PolyVoxCore as pv
|
|
||||||
|
|
||||||
#Create a 64x64x64 volume of integers
|
|
||||||
r = pv.Region(pv.Vector3Dint32_t(0,0,0), pv.Vector3Dint32_t(63,63,63))
|
|
||||||
vol = pv.SimpleVolumeuint8(r)
|
|
||||||
|
|
||||||
#Now fill the volume with our data (a sphere)
|
|
||||||
v3dVolCenter = pv.Vector3Dint32_t(vol.getWidth() // 2, vol.getHeight() // 2, vol.getDepth() // 2)
|
|
||||||
sphereRadius = 30
|
|
||||||
#This three-level for loop iterates over every voxel in the volume
|
|
||||||
for z in range(vol.getDepth()):
|
|
||||||
for y in range(vol.getHeight()):
|
|
||||||
for x in range(vol.getWidth()):
|
|
||||||
#Compute how far the current position is from the center of the volume
|
|
||||||
fDistToCenter = (pv.Vector3Dint32_t(x,y,z) - v3dVolCenter).length()
|
|
||||||
|
|
||||||
#If the current voxel is less than 'radius' units from the center then we make it solid.
|
|
||||||
if(fDistToCenter <= sphereRadius):
|
|
||||||
#Our new voxel value
|
|
||||||
uVoxelValue = 255
|
|
||||||
else:
|
|
||||||
uVoxelValue = 0
|
|
||||||
|
|
||||||
#Write the voxel value into the volume
|
|
||||||
vol.setVoxelAt(x, y, z, uVoxelValue);
|
|
||||||
|
|
||||||
#Create a mesh, pass it to the extractor and generate the mesh
|
|
||||||
mesh = pv.SurfaceMeshPositionMaterialNormal()
|
|
||||||
extractor = pv.CubicSurfaceExtractorWithNormalsSimpleVolumeuint8(vol, r, mesh)
|
|
||||||
extractor.execute()
|
|
||||||
|
|
||||||
#That's all of the PolyVox generation done, now to convert the output to something OpenGL can read efficiently
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
indices = np.array(mesh.getIndices(), dtype='uint32') #Throw in the vertex indices into an array
|
|
||||||
#The vertices and normals are placed in an interpolated array like [vvvnnn,vvvnnn,vvvnnn]
|
|
||||||
vertices = np.array([[vertex.getPosition().getX(), vertex.getPosition().getY(), vertex.getPosition().getZ(),
|
|
||||||
vertex.getNormal().getX(), vertex.getNormal().getY(), vertex.getNormal().getZ()]
|
|
||||||
for vertex in mesh.getVertices()],
|
|
||||||
dtype='f')
|
|
||||||
|
|
||||||
#Now that we have our data, everything else here is just OpenGL
|
|
||||||
|
|
||||||
import OpenGL
|
|
||||||
|
|
||||||
from OpenGL.GL import shaders
|
|
||||||
from OpenGL.arrays import vbo
|
|
||||||
from OpenGL.GL import glClear, glEnable, glDepthFunc, GLuint, glEnableVertexAttribArray, glVertexAttribPointer, glDisableVertexAttribArray, \
|
|
||||||
glDrawElements, glGetUniformLocation, glUniformMatrix4fv, glDepthMask, glDepthRange, glGetString, glBindAttribLocation, \
|
|
||||||
GL_COLOR_BUFFER_BIT, GL_TRIANGLES, GL_DEPTH_TEST, GL_LEQUAL, GL_FLOAT, \
|
|
||||||
GL_DEPTH_BUFFER_BIT, GL_ELEMENT_ARRAY_BUFFER, GL_UNSIGNED_INT, GL_STATIC_DRAW, \
|
|
||||||
GL_FALSE, GL_TRUE, GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, GL_CULL_FACE, \
|
|
||||||
GL_VENDOR, GL_RENDERER, GL_VERSION, GL_SHADING_LANGUAGE_VERSION
|
|
||||||
from OpenGL.raw.GL.ARB.vertex_array_object import glGenVertexArrays, glBindVertexArray
|
|
||||||
|
|
||||||
import pygame
|
|
||||||
|
|
||||||
from math import sin, cos, tan, radians
|
|
||||||
|
|
||||||
SCREEN_SIZE = (800, 800)
|
|
||||||
|
|
||||||
def run():
|
|
||||||
#Start OpenGL and ask it for an OpenGL context
|
|
||||||
pygame.init()
|
|
||||||
clock = pygame.time.Clock()
|
|
||||||
screen = pygame.display.set_mode(SCREEN_SIZE, pygame.HWSURFACE|pygame.OPENGL|pygame.DOUBLEBUF)
|
|
||||||
|
|
||||||
#The first thing we do is print some OpenGL details and check that we have a good enough version
|
|
||||||
print("OpenGL Implementation Details:")
|
|
||||||
if glGetString(GL_VENDOR):
|
|
||||||
print("\tGL_VENDOR: {}".format(glGetString(GL_VENDOR).decode()))
|
|
||||||
if glGetString(GL_RENDERER):
|
|
||||||
print("\tGL_RENDERER: {}".format(glGetString(GL_RENDERER).decode()))
|
|
||||||
if glGetString(GL_VERSION):
|
|
||||||
print("\tGL_VERSION: {}".format(glGetString(GL_VERSION).decode()))
|
|
||||||
if glGetString(GL_SHADING_LANGUAGE_VERSION):
|
|
||||||
print("\tGL_SHADING_LANGUAGE_VERSION: {}".format(glGetString(GL_SHADING_LANGUAGE_VERSION).decode()))
|
|
||||||
|
|
||||||
major_version = int(glGetString(GL_VERSION).decode().split()[0].split('.')[0])
|
|
||||||
minor_version = int(glGetString(GL_VERSION).decode().split()[0].split('.')[1])
|
|
||||||
if major_version < 3 or (major_version < 3 and minor_version < 0):
|
|
||||||
print("OpenGL version must be at least 3.0 (found {0})".format(glGetString(GL_VERSION).decode().split()[0]))
|
|
||||||
|
|
||||||
#Now onto the OpenGL initialisation
|
|
||||||
|
|
||||||
#Set up depth culling
|
|
||||||
glEnable(GL_CULL_FACE)
|
|
||||||
glEnable(GL_DEPTH_TEST)
|
|
||||||
glDepthMask(GL_TRUE)
|
|
||||||
glDepthFunc(GL_LEQUAL)
|
|
||||||
glDepthRange(0.0, 1.0)
|
|
||||||
|
|
||||||
#We create out shaders which do little more than set a flat colour for each face
|
|
||||||
|
|
||||||
VERTEX_SHADER = shaders.compileShader(b"""
|
|
||||||
#version 130
|
|
||||||
|
|
||||||
in vec4 position;
|
|
||||||
in vec4 normal;
|
|
||||||
|
|
||||||
uniform mat4 projectionMatrix;
|
|
||||||
uniform mat4 viewMatrix;
|
|
||||||
uniform mat4 modelMatrix;
|
|
||||||
|
|
||||||
flat out float theColor;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
vec4 temp = modelMatrix * position;
|
|
||||||
temp = viewMatrix * temp;
|
|
||||||
gl_Position = projectionMatrix * temp;
|
|
||||||
|
|
||||||
theColor = clamp(abs(dot(normalize(normal.xyz), normalize(vec3(0.9,0.1,0.5)))), 0, 1);
|
|
||||||
}
|
|
||||||
""", GL_VERTEX_SHADER)
|
|
||||||
|
|
||||||
|
|
||||||
FRAGMENT_SHADER = shaders.compileShader(b"""
|
|
||||||
#version 130
|
|
||||||
|
|
||||||
flat in float theColor;
|
|
||||||
|
|
||||||
out vec4 outputColor;
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
outputColor = vec4(1.0, 0.5, theColor, 1.0);
|
|
||||||
}
|
|
||||||
""", GL_FRAGMENT_SHADER)
|
|
||||||
|
|
||||||
shader = shaders.compileProgram(VERTEX_SHADER, FRAGMENT_SHADER)
|
|
||||||
|
|
||||||
#And then grab our attribute locations from it
|
|
||||||
glBindAttribLocation(shader, 0, b"position")
|
|
||||||
glBindAttribLocation(shader, 1, b"normal")
|
|
||||||
|
|
||||||
#Create the Vertex Array Object to hold our volume mesh
|
|
||||||
vertexArrayObject = GLuint(0)
|
|
||||||
glGenVertexArrays(1, vertexArrayObject)
|
|
||||||
glBindVertexArray(vertexArrayObject)
|
|
||||||
|
|
||||||
#Create the index buffer object
|
|
||||||
indexPositions = vbo.VBO(indices, target=GL_ELEMENT_ARRAY_BUFFER, usage=GL_STATIC_DRAW)
|
|
||||||
#Create the VBO
|
|
||||||
vertexPositions = vbo.VBO(vertices, usage=GL_STATIC_DRAW)
|
|
||||||
|
|
||||||
#Bind our VBOs and set up our data layout specifications
|
|
||||||
with indexPositions, vertexPositions:
|
|
||||||
glEnableVertexAttribArray(0)
|
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, False, 6*vertices.dtype.itemsize, vertexPositions+(0*vertices.dtype.itemsize))
|
|
||||||
glEnableVertexAttribArray(1)
|
|
||||||
glVertexAttribPointer(1, 3, GL_FLOAT, False, 6*vertices.dtype.itemsize, vertexPositions+(3*vertices.dtype.itemsize))
|
|
||||||
|
|
||||||
glBindVertexArray(0)
|
|
||||||
glDisableVertexAttribArray(0)
|
|
||||||
|
|
||||||
#Now grab out transformation martix locations
|
|
||||||
modelMatrixUnif = glGetUniformLocation(shader, b"modelMatrix")
|
|
||||||
viewMatrixUnif = glGetUniformLocation(shader, b"viewMatrix")
|
|
||||||
projectionMatrixUnif = glGetUniformLocation(shader, b"projectionMatrix")
|
|
||||||
|
|
||||||
modelMatrix = np.array([[1.0,0.0,0.0,-32.0],[0.0,1.0,0.0,-32.0],[0.0,0.0,1.0,-32.0],[0.0,0.0,0.0,1.0]], dtype='f')
|
|
||||||
viewMatrix = np.array([[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,-50.0],[0.0,0.0,0.0,1.0]], dtype='f')
|
|
||||||
projectionMatrix = np.array([[0.0,0.0,0.0,0.0],[0.0,0.0,0.0,0.0],[0.0,0.0,0.0,0.0],[0.0,0.0,0.0,0.0]], dtype='f')
|
|
||||||
|
|
||||||
#These next few lines just set up our camera frustum
|
|
||||||
fovDeg = 45.0
|
|
||||||
frustumScale = 1.0 / tan(radians(fovDeg) / 2.0)
|
|
||||||
|
|
||||||
zNear = 1.0
|
|
||||||
zFar = 1000.0
|
|
||||||
|
|
||||||
projectionMatrix[0][0] = frustumScale
|
|
||||||
projectionMatrix[1][1] = frustumScale
|
|
||||||
projectionMatrix[2][2] = (zFar + zNear) / (zNear - zFar)
|
|
||||||
projectionMatrix[2][3] = -1.0
|
|
||||||
projectionMatrix[3][2] = (2 * zFar * zNear) / (zNear - zFar)
|
|
||||||
|
|
||||||
#viewMatrix and projectionMatrix don't change ever so just set them once here
|
|
||||||
with shader:
|
|
||||||
glUniformMatrix4fv(projectionMatrixUnif, 1, GL_TRUE, projectionMatrix)
|
|
||||||
glUniformMatrix4fv(viewMatrixUnif, 1, GL_TRUE, viewMatrix)
|
|
||||||
|
|
||||||
#These are used to track the rotation of the volume
|
|
||||||
LastFrameMousePos = (0,0)
|
|
||||||
CurrentMousePos = (0,0)
|
|
||||||
xRotation = 0
|
|
||||||
yRotation = 0
|
|
||||||
|
|
||||||
while True:
|
|
||||||
clock.tick()
|
|
||||||
|
|
||||||
for event in pygame.event.get():
|
|
||||||
if event.type == pygame.QUIT:
|
|
||||||
return
|
|
||||||
if event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE:
|
|
||||||
return
|
|
||||||
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
|
|
||||||
CurrentMousePos = event.pos
|
|
||||||
LastFrameMousePos = CurrentMousePos
|
|
||||||
if event.type == pygame.MOUSEMOTION and 1 in event.buttons:
|
|
||||||
CurrentMousePos = event.pos
|
|
||||||
diff = (CurrentMousePos[0] - LastFrameMousePos[0], CurrentMousePos[1] - LastFrameMousePos[1])
|
|
||||||
xRotation += event.rel[0]
|
|
||||||
yRotation += event.rel[1]
|
|
||||||
LastFrameMousePos = CurrentMousePos
|
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
|
||||||
|
|
||||||
#Perform the rotation of the mesh
|
|
||||||
moveToOrigin = np.array([[1.0,0.0,0.0,-32.0],[0.0,1.0,0.0,-32.0],[0.0,0.0,1.0,-32.0],[0.0,0.0,0.0,1.0]], dtype='f')
|
|
||||||
rotateAroundX = np.array([[1.0,0.0,0.0,0.0],[0.0,cos(radians(yRotation)),-sin(radians(yRotation)),0.0],[0.0,sin(radians(yRotation)),cos(radians(yRotation)),0.0],[0.0,0.0,0.0,1.0]], dtype='f')
|
|
||||||
rotateAroundY = np.array([[cos(radians(xRotation)),0.0,sin(radians(xRotation)),0.0],[0.0,1.0,0.0,0.0],[-sin(radians(xRotation)),0.0,cos(radians(xRotation)),0.0],[0.0,0.0,0.0,1.0]], dtype='f')
|
|
||||||
|
|
||||||
modelMatrix = rotateAroundY.dot(rotateAroundX.dot(moveToOrigin))
|
|
||||||
|
|
||||||
with shader:
|
|
||||||
glUniformMatrix4fv(modelMatrixUnif, 1, GL_TRUE, modelMatrix)
|
|
||||||
glBindVertexArray(vertexArrayObject)
|
|
||||||
|
|
||||||
glDrawElements(GL_TRIANGLES, len(indices), GL_UNSIGNED_INT, None)
|
|
||||||
|
|
||||||
glBindVertexArray(0)
|
|
||||||
|
|
||||||
# Show the screen
|
|
||||||
pygame.display.flip()
|
|
||||||
|
|
||||||
run()
|
|
@ -1,62 +1,64 @@
|
|||||||
################################################################################
|
# Copyright (c) 2010-2012 David Williams
|
||||||
# The MIT License (MIT)
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2015 Matthew Williams and 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 hereby granted, free of charge, to any person obtaining a copy
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# in the Software without restriction, including without limitation the rights
|
# freely, subject to the following restrictions:
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
#
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
# 1. The origin of this software must not be misrepresented; you must not
|
||||||
# copies or substantial portions of the Software.
|
# 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.
|
||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# misrepresented as being the original software.
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
#
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# 3. This notice may not be removed or altered from any source
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# distribution.
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||||
################################################################################
|
|
||||||
|
|
||||||
PROJECT(SmoothLODExample)
|
PROJECT(SmoothLODExample)
|
||||||
|
|
||||||
#Projects source files
|
#Projects source files
|
||||||
SET(SRC_FILES
|
SET(SRC_FILES
|
||||||
|
glew/glew.cpp
|
||||||
|
|
||||||
main.cpp
|
main.cpp
|
||||||
../common/PolyVoxExample.cpp
|
OpenGLWidget.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
#Projects headers files
|
#Projects headers files
|
||||||
SET(INC_FILES
|
SET(INC_FILES
|
||||||
../common/OpenGLWidget.h
|
glew/glew.h
|
||||||
../common/OpenGLWidget.inl
|
glew/glxew.h
|
||||||
../common/PolyVoxExample.h
|
glew/wglew.h
|
||||||
)
|
|
||||||
|
OpenGLWidget.h
|
||||||
|
)
|
||||||
|
|
||||||
|
ADD_DEFINITIONS(-DGLEW_STATIC)
|
||||||
|
|
||||||
#"Sources" and "Headers" are the group names in Visual Studio.
|
#"Sources" and "Headers" are the group names in Visual Studio.
|
||||||
#They may have other uses too...
|
#They may have other uses too...
|
||||||
SOURCE_GROUP("Sources" FILES ${SRC_FILES})
|
SOURCE_GROUP("Sources" FILES ${SRC_FILES})
|
||||||
SOURCE_GROUP("Headers" FILES ${INC_FILES})
|
SOURCE_GROUP("Headers" FILES ${INC_FILES})
|
||||||
|
|
||||||
|
FIND_PACKAGE(OpenGL REQUIRED)
|
||||||
|
|
||||||
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
#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} ../common)
|
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_SOURCE_DIR}/include)
|
||||||
|
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
||||||
#This will include the shader files inside the compiled binary
|
|
||||||
QT5_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} ${COMMON_RESOURCES_RCC})
|
ADD_EXECUTABLE(SmoothLODExample ${SRC_FILES})
|
||||||
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 Qt5::OpenGL)
|
TARGET_LINK_LIBRARIES(SmoothLODExample ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
||||||
SET_PROPERTY(TARGET SmoothLODExample PROPERTY FOLDER "Examples")
|
SET_PROPERTY(TARGET SmoothLODExample PROPERTY FOLDER "Examples")
|
||||||
|
|
||||||
#Install - Only install the example in Windows
|
#Install - Only install the example in Windows
|
||||||
|
186
examples/SmoothLOD/OpenGLWidget.cpp
Normal file
186
examples/SmoothLOD/OpenGLWidget.cpp
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
#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();
|
||||||
|
}
|
74
examples/SmoothLOD/OpenGLWidget.h
Normal file
74
examples/SmoothLOD/OpenGLWidget.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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__
|
73
examples/SmoothLOD/glew/LICENSE.txt
Normal file
73
examples/SmoothLOD/glew/LICENSE.txt
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
The OpenGL Extension Wrangler Library
|
||||||
|
Copyright (C) 2002-2007, Milan Ikits <milan ikits[]ieee org>
|
||||||
|
Copyright (C) 2002-2007, Marcelo E. Magallon <mmagallo[]debian org>
|
||||||
|
Copyright (C) 2002, Lev Povalahev
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
* The name of the author may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
Mesa 3-D graphics library
|
||||||
|
Version: 7.0
|
||||||
|
|
||||||
|
Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (c) 2007 The Khronos Group Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and/or associated documentation files (the
|
||||||
|
"Materials"), to deal in the Materials without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Materials, and to
|
||||||
|
permit persons to whom the Materials are furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Materials.
|
||||||
|
|
||||||
|
THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
16972
examples/SmoothLOD/glew/glew.cpp
Normal file
16972
examples/SmoothLOD/glew/glew.cpp
Normal file
File diff suppressed because it is too large
Load Diff
17132
examples/SmoothLOD/glew/glew.h
Normal file
17132
examples/SmoothLOD/glew/glew.h
Normal file
File diff suppressed because it is too large
Load Diff
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