3rdparty/polyvox
This commit is contained in:
parent
82f2a6abbd
commit
263906be8f
57
3rdparty/polyvox/CHANGELOG.txt
vendored
Normal file
57
3rdparty/polyvox/CHANGELOG.txt
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
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.
|
||||
|
||||
Deprecated functionality
|
||||
------------------------
|
||||
The following functionality is considered deprecated in this release of PolyVox and will probably be removed in future versions.
|
||||
|
||||
MeshDecimator: The mesh decimator was intended to reduce the amount of triangles in generated meshes but it has always had problems. It's far too slow and not very robust. For cubic meshes it is no longer needed anyway as the CubicSurfaceExtractor has built in decimation which is much more effective. For smooth (marching cubes) meshes there is no single alternative. You can consider downsampling the volume before you run the surface extractor (see the SmoothLODExample), and in the future we may add support for an external mesh processing library.
|
||||
|
||||
SimpleInterface: This was added so that people could create volumes without knowing about templates, and also to provide a target which was easier to wrap with SWIG. But overall we'd rather focus on getting the real SWIG bindings to work. The SimpleInterface is also extremely limited in the functionality it provides.
|
||||
|
||||
Serialisation: This is a difficult one. The current serialisation is rather old and only deals with loading/saving a whole volume at a time. It would make much more sense if it could serialise regions instead of whole volumes, and if it could handle compression. It would then be useful for serialising the data which is paged into and out of the LargeVolume, as well as other uses. Both these changes would likely require breaking the current format and interface. It is likely that serialisation will return to PolyVox in the future, but for now we would suggest just implementing your own.
|
||||
|
||||
VolumeChangeTracker: The idea behind this was was to provide a utility class to help the user keep track of which regions have been modified so they know when they need the surface extractor to be run again. But overall we'd rather keep such higher level functionality in user code as there are multiple ways it can be implemented. The current implementation is also old and does not support very large/infinite volumes, for example.
|
||||
|
||||
Refactor of basic voxel types
|
||||
-----------------------------
|
||||
Previous versions of PolyVox provided classes representing voxel data, such as MaterialDensityPair88. These classes were required to expose certain functions such as getDensity() and getMaterial(). This is no longer the case as now even primitive data types such as floats and ints can be used as voxels. You can also create new classes to represent voxel data and it is entirely up to you what kind of properties they have.
|
||||
|
||||
As an example, imagine you might want to store lighting values in a volume and propagate them according to some algorithm you devise. In this case the voxel data has no concept of densities or materials and there is no need to provide them. Algorithms which conceptually operate on densities (such as the MarchingCubesSurfaceExtractor) will not be able to operate on your lighting data but this would not make sense anyway.
|
||||
|
||||
Because algorithms now know nothing about the structure of the underlying voxels, some utility functions/classes are required. The principle is similar to the std::sort algorithm, which knows nothing about the type of data it is operating on but is told how to compare any two values via a comparator function object. In this sense, it will be useful to have an understanding of how algorithms such as std::sort are used.
|
||||
|
||||
We have continued to provide the Density, Material, and MaterialDensityPair classes to ease the transition into the new system, but really they should just be considered as examples of how you might create your own voxel types.
|
||||
|
||||
Some algorithms assume that basic mathematical operations can be applied to voxel types. For example, the LowPassFilter needs to compute the average of a set of voxels, and to do this it needs to be possible to add voxels together and divide by an integer. Obviously these operations are provided by primitive types, but it means that if you want to use the LowPassfilter on custom voxel types then these types need to provide operator+=, operator/=, etc. These have been added to the Density and MaterialDensityPair classes, but not to the Material class. This reflects the fact that applying a low pass filter to a material volume does not make conceptual sense.
|
||||
|
||||
Changes to build system
|
||||
-----------------------
|
||||
In order to make the build system easier to use, a number of CMake variables were changed to be more consistent. See :doc:`install` for details on the new variable naming.
|
||||
|
||||
Changes to CubicSurfaceExtractor
|
||||
--------------------------------
|
||||
The behaviour of the CubicSurfaceExtractor has been changed such that it no longer handles some edge cases. Because each generated quad lies between two voxels it can be unclear which region should 'own' a quad when the two voxels are from different regions. The previous version of the CubicSurfaceExtractor would attempt to handle this automatically, but as a result it was possible to get two quads existing at the same position in space. This can cause problems with transparency and with physics, as well as making it harder to decide which regions need to be updated when a voxel is changed.
|
||||
|
||||
The new system simplifies the behaviour of this surface extractor but does require a bit of care on the part of the user. You should be clear on the rules controlling when quads are generated and to which regions they will belong. To aid with this we have significantly improved the API documentation for the CubicSurfaceExtractor so be sure to have a look.
|
||||
|
||||
Changes to Raycast
|
||||
------------------
|
||||
The raycasting functionality was previously in a class (Raycast) but now it is provided by standalone functions. This is basically because there is no need for it to be a class, and it complicated usage. The new functions are called 'raycastWithDirection' and 'raycastWithEndpoints' which helps remove the previous ambiguity regarding the meaning of the two vectors which are passed as parameters.
|
||||
|
||||
The callback functionality (called for each processed voxel to determine whether to continue and also perform additional processing) is no longer implemented as an std::function. Instead the standard STL approach is used, in which a function or function object is used a a template parameter. This is faster than the std::function solution and should also be easier to integrate with other languages.
|
||||
|
||||
Usage of the new raycasting is demonstrated by a unit test.
|
||||
|
||||
Changes to AmbientOcclusionCalculator
|
||||
-------------------------------------
|
||||
The AmbientOcclusionCalculator has also been unclassed and is now called calculateAmbientOcclusion. The unit test has been updated to demonstrate the new usage.
|
||||
|
||||
Changes to A* pathfinder
|
||||
------------------------
|
||||
The A* pathfinder has always had different (but equally valid) results when building in Visual Studio vs. GCC. This is now fixed and results are consistent between platforms.
|
||||
|
||||
Copy and move semantics
|
||||
-----------------------
|
||||
All volume classes now have protected copy constructors and assignment operators to prevent you from accidentally copying them (which is expensive). Look at the VolumeResampler if you really do want to copy some volume data.
|
64
3rdparty/polyvox/CMakeLists.txt
vendored
Normal file
64
3rdparty/polyvox/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
# Copyright (c) 2007-2012 Matt Williams
|
||||
# Copyright (c) 2007-2012 David Williams
|
||||
#
|
||||
# This software is provided 'as-is', without any express or implied
|
||||
# warranty. In no event will the authors be held liable for any damages
|
||||
# arising from the use of this software.
|
||||
#
|
||||
# Permission is granted to anyone to use this software for any purpose,
|
||||
# including commercial applications, and to alter it and redistribute it
|
||||
# freely, subject to the following restrictions:
|
||||
#
|
||||
# 1. The origin of this software must not be misrepresented; you must not
|
||||
# claim that you wrote the original software. If you use this software
|
||||
# in a product, an acknowledgment in the product documentation would be
|
||||
# appreciated but is not required.
|
||||
#
|
||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||
# misrepresented as being the original software.
|
||||
#
|
||||
# 3. This notice may not be removed or altered from any source
|
||||
# distribution.
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3)
|
||||
|
||||
PROJECT(PolyVox)
|
||||
|
||||
SET(POLYVOX_VERSION_MAJOR "0")
|
||||
SET(POLYVOX_VERSION_MINOR "2")
|
||||
SET(POLYVOX_VERSION_PATCH "1")
|
||||
SET(POLYVOX_VERSION "${POLYVOX_VERSION_MAJOR}.${POLYVOX_VERSION_MINOR}.${POLYVOX_VERSION_PATCH}" CACHE STRING "PolyVox version")
|
||||
MARK_AS_ADVANCED(FORCE POLYVOX_VERSION)
|
||||
|
||||
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
include(FeatureSummary)
|
||||
|
||||
FIND_PACKAGE(Doxygen)
|
||||
OPTION(ENABLE_EXAMPLES "Should the examples be built" ON)
|
||||
|
||||
#SET(LIBRARY_TYPE "DYNAMIC" CACHE STRING "Should the library be STATIC or DYNAMIC")
|
||||
#SET_PROPERTY(CACHE LIBRARY_TYPE PROPERTY STRINGS DYNAMIC STATIC)
|
||||
#IF(WIN32)
|
||||
# SET(LIBRARY_TYPE "STATIC")
|
||||
#ENDIF()
|
||||
|
||||
SET(LIBRARY_TYPE "STATIC")
|
||||
|
||||
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
|
||||
ENDIF()
|
||||
if(CMAKE_CXX_COMPILER MATCHES "clang")
|
||||
ADD_DEFINITIONS(-std=c++0x) #Enable C++0x mode
|
||||
endif()
|
||||
|
||||
ADD_SUBDIRECTORY(library)
|
||||
|
||||
INCLUDE(Packaging.cmake)
|
||||
|
3
3rdparty/polyvox/CREDITS.txt
vendored
Normal file
3
3rdparty/polyvox/CREDITS.txt
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
David Williams - Lead programmer.
|
||||
Matthew Williams - Linux port, build system, support and maintenance.
|
||||
Oliver Schneider - Very large Volumes
|
28
3rdparty/polyvox/CTestConfig.cmake
vendored
Normal file
28
3rdparty/polyvox/CTestConfig.cmake
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
# Copyright (c) 2010-2012 Matt 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.
|
||||
|
||||
set(CTEST_PROJECT_NAME "PolyVox")
|
||||
set(CTEST_NIGHTLY_START_TIME "00:00:00 GMT")
|
||||
|
||||
set(CTEST_DROP_METHOD "http")
|
||||
set(CTEST_DROP_SITE "my.cdash.org")
|
||||
set(CTEST_DROP_LOCATION "/submit.php?project=PolyVox")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
20
3rdparty/polyvox/LICENSE.TXT
vendored
Normal file
20
3rdparty/polyvox/LICENSE.TXT
vendored
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.
|
55
3rdparty/polyvox/Packaging.cmake
vendored
Normal file
55
3rdparty/polyvox/Packaging.cmake
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
# Copyright (c) 2009-2012 Matt 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(InstallRequiredSystemLibraries)
|
||||
|
||||
SET(CPACK_PACKAGE_NAME "PolyVox SDK")
|
||||
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "PolyVox SDK")
|
||||
SET(CPACK_PACKAGE_VENDOR "Thermite 3D Team")
|
||||
#SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ReadMe.txt")
|
||||
#SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt")
|
||||
SET(CPACK_PACKAGE_VERSION_MAJOR ${POLYVOX_VERSION_MAJOR})
|
||||
SET(CPACK_PACKAGE_VERSION_MINOR ${POLYVOX_VERSION_MINOR})
|
||||
SET(CPACK_PACKAGE_VERSION_PATCH ${POLYVOX_VERSION_PATCH})
|
||||
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "PolyVox SDK ${POLYVOX_VERSION}")
|
||||
IF(WIN32 AND NOT UNIX)
|
||||
# There is a bug in NSIS that does not handle full unix paths properly.
|
||||
# Make sure there is at least one set of four backslashes.
|
||||
#SET(CPACK_PACKAGE_ICON "${CMake_SOURCE_DIR}/Utilities/Release\\\\InstallIcon.bmp")
|
||||
#SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\MyExecutable.exe")
|
||||
SET(CPACK_NSIS_DISPLAY_NAME "PolyVox SDK ${POLYVOX_VERSION}")
|
||||
SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\thermite3d.org/phpBB/")
|
||||
SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\thermite3d.org")
|
||||
SET(CPACK_NSIS_CONTACT "matt@milliams.com")
|
||||
SET(CPACK_NSIS_MODIFY_PATH ON)
|
||||
ELSE(WIN32 AND NOT UNIX)
|
||||
#SET(CPACK_STRIP_FILES "bin/MyExecutable")
|
||||
#SET(CPACK_SOURCE_STRIP_FILES "")
|
||||
ENDIF(WIN32 AND NOT UNIX)
|
||||
#SET(CPACK_PACKAGE_EXECUTABLES "MyExecutable" "My Executable")
|
||||
|
||||
INCLUDE(CPack)
|
||||
|
||||
CPACK_ADD_COMPONENT(library DISPLAY_NAME "Library" DESCRIPTION "The runtime libraries" REQUIRED)
|
||||
CPACK_ADD_COMPONENT(development DISPLAY_NAME "Development" DESCRIPTION "Files required for developing with PolyVox" DEPENDS library)
|
||||
CPACK_ADD_COMPONENT(example DISPLAY_NAME "OpenGL Example" DESCRIPTION "A PolyVox example application using OpenGL" DEPENDS library)
|
||||
cpack_add_component_group(bindings DISPLAY_NAME "Bindings" DESCRIPTION "Language bindings")
|
||||
CPACK_ADD_COMPONENT(python DISPLAY_NAME "Python Bindings" DESCRIPTION "PolyVox bindings for the Python language" DISABLED GROUP bindings DEPENDS library)
|
5
3rdparty/polyvox/README.rst
vendored
Normal file
5
3rdparty/polyvox/README.rst
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
PolyVox - The voxel management and manipulation library
|
||||
=======================================================
|
||||
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>`_.
|
||||
|
||||
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.
|
33
3rdparty/polyvox/library/CMakeLists.txt
vendored
Normal file
33
3rdparty/polyvox/library/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
# Copyright (c) 2008-2012 Matt Williams
|
||||
# Copyright (c) 2008-2012 David Williams
|
||||
#
|
||||
# This software is provided 'as-is', without any express or implied
|
||||
# warranty. In no event will the authors be held liable for any damages
|
||||
# arising from the use of this software.
|
||||
#
|
||||
# Permission is granted to anyone to use this software for any purpose,
|
||||
# including commercial applications, and to alter it and redistribute it
|
||||
# freely, subject to the following restrictions:
|
||||
#
|
||||
# 1. The origin of this software must not be misrepresented; you must not
|
||||
# claim that you wrote the original software. If you use this software
|
||||
# in a product, an acknowledgment in the product documentation would be
|
||||
# appreciated but is not required.
|
||||
#
|
||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||
# misrepresented as being the original software.
|
||||
#
|
||||
# 3. This notice may not be removed or altered from any source
|
||||
# distribution.
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
|
||||
PROJECT(PolyVox)
|
||||
|
||||
add_subdirectory(PolyVoxCore)
|
||||
|
||||
# Not useful; the serialization is platform-dependent
|
||||
#add_subdirectory(PolyVoxUtil)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/PolyVoxConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/PolyVoxConfig.cmake @ONLY)
|
||||
|
1876
3rdparty/polyvox/library/Doxyfile.in
vendored
Normal file
1876
3rdparty/polyvox/library/Doxyfile.in
vendored
Normal file
File diff suppressed because it is too large
Load Diff
59
3rdparty/polyvox/library/Mainpage.dox
vendored
Normal file
59
3rdparty/polyvox/library/Mainpage.dox
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
\mainpage PolyVox Framework
|
||||
|
||||
The PolyVox documentation.\n
|
||||
|
||||
See the <a href="../manual/index.html">manual</a> for help and tutorials.
|
||||
|
||||
|
||||
\author David Williams
|
||||
|
||||
\namespace PolyVox
|
||||
\brief Main namespace
|
||||
*/
|
||||
|
||||
/**
|
||||
\page tutorial Tutorial
|
||||
|
||||
This is a basic tutorial covering the essentials of using %PolyVox.
|
||||
|
||||
\note This is a work in progress. For now, the best example is the OpenGL example distributed with %PolyVox in the example/OpenGL/ folder.
|
||||
|
||||
\code
|
||||
#include <Block.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
//blah blah
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
|
||||
/**
|
||||
\page cmake Finding %PolyVox with CMake
|
||||
|
||||
CMakeLists.txt:
|
||||
\verbatim
|
||||
# Tell CMake the name of you project
|
||||
project(MyApp)
|
||||
|
||||
# Ask CMake to find PolyVox for you
|
||||
find_package(PolyVox REQUIRED)
|
||||
|
||||
# Tell your compiler where to look for the PolyVox headers
|
||||
include_directories(${PolyVox_INCLUDE_DIRS})
|
||||
|
||||
# Create your executable
|
||||
add_executable(myapp main.cpp)
|
||||
|
||||
# Link it to PolyVox
|
||||
target_link_libraries(myapp ${PolyVox_LIBRARIES})
|
||||
\endverbatim
|
||||
|
||||
Then call cmake with
|
||||
\verbatim
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
\endverbatim
|
||||
You may also need to pass an argument to cmake if it can't find %PolyVox. Pass <tt>-DCMAKE_PREFIX_PATH=/path/to/polyvox/root/</tt>.
|
||||
*/
|
39
3rdparty/polyvox/library/PolyVoxConfig.cmake.in
vendored
Normal file
39
3rdparty/polyvox/library/PolyVoxConfig.cmake.in
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
# Find PolyVox includes and library
|
||||
#
|
||||
# This module defines
|
||||
# PolyVox_INCLUDE_DIRS
|
||||
# PolyVox_LIBRARIES, the libraries to link against to use OGRE.
|
||||
# PolyVox_LIBRARY_DIRS, the location of the libraries
|
||||
# PolyVox_FOUND, If false, do not try to use OGRE
|
||||
#
|
||||
# Copyright © 2008, Matt Williams
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
include(FindPackageMessage)
|
||||
|
||||
get_filename_component(THIS_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
if(WIN32)
|
||||
set(PREFIX ${THIS_DIR}/..)
|
||||
else()
|
||||
set(PREFIX ${THIS_DIR}/../../..)
|
||||
endif()
|
||||
|
||||
|
||||
set(PolyVoxCore_LIBRARY_DIRS "${PREFIX}/@PolyVoxCore_LIBRARY_INSTALL_DIRS@")
|
||||
set(PolyVoxUtil_LIBRARY_DIRS "${PREFIX}/@PolyVoxUtil_LIBRARY_INSTALL_DIRS@")
|
||||
set(PolyVox_LIBRARY_DIRS "${PolyVoxCore_LIBRARY_DIRS}" "${PolyVoxUtil_LIBRARY_DIRS}")
|
||||
|
||||
set(PolyVoxCore_INCLUDE_DIRS "${PREFIX}/@PolyVoxCore_INCLUDE_INSTALL_DIRS@")
|
||||
set(PolyVoxUtil_INCLUDE_DIRS "${PREFIX}/@PolyVoxUtil_INCLUDE_INSTALL_DIRS@")
|
||||
set(PolyVox_INCLUDE_DIRS "${PolyVoxCore_INCLUDE_DIRS}" "${PolyVoxUtil_INCLUDE_DIRS}" "${PREFIX}/include")
|
||||
|
||||
set(PolyVoxCore_LIBRARIES "PolyVoxCore")
|
||||
set(PolyVoxUtil_LIBRARIES "PolyVoxUtil")
|
||||
set(PolyVox_LIBRARIES "${PolyVoxCore_LIBRARIES};${PolyVoxUtil_LIBRARIES}")
|
||||
|
||||
message(STATUS "Found PolyVox")
|
||||
message(STATUS " libraries : '${PolyVoxCore_LIBRARIES}' from ${PolyVoxCore_LIBRARY_DIRS}")
|
||||
message(STATUS " : '${PolyVoxUtil_LIBRARIES}' from ${PolyVoxUtil_LIBRARY_DIRS}")
|
||||
message(STATUS " includes : ${PolyVox_INCLUDE_DIRS}")
|
151
3rdparty/polyvox/library/PolyVoxCore/CMakeLists.txt
vendored
Normal file
151
3rdparty/polyvox/library/PolyVoxCore/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
# Copyright (c) 2008-2012 Matt Williams
|
||||
# Copyright (c) 2008-2012 David Williams
|
||||
#
|
||||
# This software is provided 'as-is', without any express or implied
|
||||
# warranty. In no event will the authors be held liable for any damages
|
||||
# arising from the use of this software.
|
||||
#
|
||||
# Permission is granted to anyone to use this software for any purpose,
|
||||
# including commercial applications, and to alter it and redistribute it
|
||||
# freely, subject to the following restrictions:
|
||||
#
|
||||
# 1. The origin of this software must not be misrepresented; you must not
|
||||
# claim that you wrote the original software. If you use this software
|
||||
# in a product, an acknowledgment in the product documentation would be
|
||||
# appreciated but is not required.
|
||||
#
|
||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||
# misrepresented as being the original software.
|
||||
#
|
||||
# 3. This notice may not be removed or altered from any source
|
||||
# distribution.
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
|
||||
PROJECT(PolyVoxCore)
|
||||
|
||||
#Projects source files
|
||||
SET(CORE_SRC_FILES
|
||||
source/ArraySizes.cpp
|
||||
source/AStarPathfinder.cpp
|
||||
source/Log.cpp
|
||||
source/MeshDecimator.cpp
|
||||
source/Region.cpp
|
||||
source/SimpleInterface.cpp
|
||||
source/VertexTypes.cpp
|
||||
)
|
||||
|
||||
#Projects headers files
|
||||
SET(CORE_INC_FILES
|
||||
include/PolyVoxCore/AmbientOcclusionCalculator.h
|
||||
include/PolyVoxCore/AmbientOcclusionCalculator.inl
|
||||
include/PolyVoxCore/Array.h
|
||||
include/PolyVoxCore/Array.inl
|
||||
include/PolyVoxCore/ArraySizes.h
|
||||
include/PolyVoxCore/AStarPathfinder.h
|
||||
include/PolyVoxCore/AStarPathfinder.inl
|
||||
include/PolyVoxCore/BaseVolume.h
|
||||
include/PolyVoxCore/BaseVolume.inl
|
||||
include/PolyVoxCore/BaseVolumeSampler.inl
|
||||
include/PolyVoxCore/ConstVolumeProxy.h
|
||||
include/PolyVoxCore/CubicSurfaceExtractor.h
|
||||
include/PolyVoxCore/CubicSurfaceExtractor.inl
|
||||
include/PolyVoxCore/CubicSurfaceExtractorWithNormals.h
|
||||
include/PolyVoxCore/CubicSurfaceExtractorWithNormals.inl
|
||||
include/PolyVoxCore/DefaultIsQuadNeeded.h
|
||||
include/PolyVoxCore/DefaultMarchingCubesController.h
|
||||
include/PolyVoxCore/Density.h
|
||||
include/PolyVoxCore/GradientEstimators.h
|
||||
include/PolyVoxCore/GradientEstimators.inl
|
||||
include/PolyVoxCore/Interpolation.h
|
||||
include/PolyVoxCore/IteratorController.h
|
||||
include/PolyVoxCore/IteratorController.inl
|
||||
include/PolyVoxCore/LargeVolume.h
|
||||
include/PolyVoxCore/LargeVolume.inl
|
||||
include/PolyVoxCore/LargeVolumeSampler.inl
|
||||
include/PolyVoxCore/Log.h
|
||||
include/PolyVoxCore/LowPassFilter.h
|
||||
include/PolyVoxCore/LowPassFilter.inl
|
||||
include/PolyVoxCore/MarchingCubesSurfaceExtractor.h
|
||||
include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl
|
||||
include/PolyVoxCore/Material.h
|
||||
include/PolyVoxCore/MaterialDensityPair.h
|
||||
include/PolyVoxCore/MeshDecimator.h
|
||||
include/PolyVoxCore/MeshDecimator.inl
|
||||
include/PolyVoxCore/PolyVoxForwardDeclarations.h
|
||||
include/PolyVoxCore/RawVolume.h
|
||||
include/PolyVoxCore/RawVolume.inl
|
||||
include/PolyVoxCore/RawVolumeSampler.inl
|
||||
include/PolyVoxCore/Raycast.h
|
||||
include/PolyVoxCore/Raycast.inl
|
||||
include/PolyVoxCore/Region.h
|
||||
include/PolyVoxCore/SimpleInterface.h
|
||||
include/PolyVoxCore/SimpleVolume.h
|
||||
include/PolyVoxCore/SimpleVolume.inl
|
||||
include/PolyVoxCore/SimpleVolumeBlock.inl
|
||||
include/PolyVoxCore/SimpleVolumeSampler.inl
|
||||
include/PolyVoxCore/SurfaceMesh.h
|
||||
include/PolyVoxCore/SurfaceMesh.inl
|
||||
include/PolyVoxCore/Vector.h
|
||||
include/PolyVoxCore/Vector.inl
|
||||
include/PolyVoxCore/VertexTypes.h
|
||||
include/PolyVoxCore/VolumeResampler.h
|
||||
include/PolyVoxCore/VolumeResampler.inl
|
||||
include/PolyVoxCore/VoxelFilters.h
|
||||
include/PolyVoxCore/VoxelFilters.inl
|
||||
)
|
||||
|
||||
SET(IMPL_SRC_FILES
|
||||
source/Impl/MarchingCubesTables.cpp
|
||||
source/Impl/RandomUnitVectors.cpp
|
||||
source/Impl/RandomVectors.cpp
|
||||
source/Impl/Utility.cpp
|
||||
)
|
||||
|
||||
SET(IMPL_INC_FILES
|
||||
include/PolyVoxCore/Impl/ArraySizesImpl.h
|
||||
include/PolyVoxCore/Impl/ArraySizesImpl.inl
|
||||
include/PolyVoxCore/Impl/AStarPathfinderImpl.h
|
||||
include/PolyVoxCore/Impl/Block.h
|
||||
include/PolyVoxCore/Impl/Block.inl
|
||||
include/PolyVoxCore/Impl/MarchingCubesTables.h
|
||||
include/PolyVoxCore/Impl/RandomUnitVectors.h
|
||||
include/PolyVoxCore/Impl/RandomVectors.h
|
||||
include/PolyVoxCore/Impl/SubArray.h
|
||||
include/PolyVoxCore/Impl/SubArray.inl
|
||||
include/PolyVoxCore/Impl/TypeDef.h
|
||||
include/PolyVoxCore/Impl/Utility.h
|
||||
)
|
||||
|
||||
#NOTE: The following line should be uncommented when building shared libs.
|
||||
|
||||
#"Sources" and "Headers" are the group names in Visual Studio.
|
||||
#They may have other uses too...
|
||||
SOURCE_GROUP("Sources" FILES ${CORE_SRC_FILES})
|
||||
SOURCE_GROUP("Headers" FILES ${CORE_INC_FILES})
|
||||
|
||||
SOURCE_GROUP("Sources\\Impl" FILES ${IMPL_SRC_FILES})
|
||||
SOURCE_GROUP("Headers\\Impl" FILES ${IMPL_INC_FILES})
|
||||
|
||||
#Tell CMake the paths
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
#Core
|
||||
#Build
|
||||
IF(LIBRARY_TYPE STREQUAL "STATIC")
|
||||
ADD_LIBRARY(PolyVoxCore STATIC ${CORE_SRC_FILES} ${CORE_INC_FILES} ${IMPL_SRC_FILES} ${IMPL_INC_FILES})
|
||||
IF(UNIX)
|
||||
SET_TARGET_PROPERTIES(PolyVoxCore PROPERTIES COMPILE_FLAGS -fPIC)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(LIBRARY_TYPE STREQUAL "DYNAMIC")
|
||||
ADD_LIBRARY(PolyVoxCore SHARED ${CORE_SRC_FILES} ${CORE_INC_FILES} ${IMPL_SRC_FILES} ${IMPL_INC_FILES})
|
||||
SET_TARGET_PROPERTIES(PolyVoxCore PROPERTIES COMPILE_FLAGS "-DPOLYVOX_SHARED_EXPORTS")
|
||||
ENDIF()
|
||||
SET_PROPERTY(TARGET PolyVoxCore PROPERTY FOLDER "Library")
|
||||
|
||||
SET_TARGET_PROPERTIES(PolyVoxCore PROPERTIES VERSION ${POLYVOX_VERSION} SOVERSION ${POLYVOX_VERSION_MAJOR})
|
||||
IF(MSVC)
|
||||
SET_TARGET_PROPERTIES(PolyVoxCore PROPERTIES COMPILE_FLAGS "/W4 /wd4251 /wd4127") #Disable warning on STL exports
|
||||
ENDIF(MSVC)
|
||||
|
196
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/AStarPathfinder.h
vendored
Normal file
196
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/AStarPathfinder.h
vendored
Normal file
@ -0,0 +1,196 @@
|
||||
/*******************************************************************************
|
||||
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_AStarPathfinder_H__
|
||||
#define __PolyVox_AStarPathfinder_H__
|
||||
|
||||
#include "Impl/AStarPathfinderImpl.h"
|
||||
#include "Impl/TypeDef.h"
|
||||
|
||||
#include "PolyVoxCore/Array.h"
|
||||
|
||||
#include <list>
|
||||
#include <stdexcept> //For runtime_error
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
const float sqrt_1 = 1.0f;
|
||||
const float sqrt_2 = 1.4143f;
|
||||
const float sqrt_3 = 1.7321f;
|
||||
|
||||
extern const POLYVOX_API Vector3DInt32 arrayPathfinderFaces[6];
|
||||
extern const POLYVOX_API Vector3DInt32 arrayPathfinderEdges[12];
|
||||
extern const POLYVOX_API Vector3DInt32 arrayPathfinderCorners[8];
|
||||
|
||||
/// This function provides the default method for checking whether a given voxel
|
||||
/// is valid for the path computed by the AStarPathfinder.
|
||||
template<typename VolumeType>
|
||||
bool aStarDefaultVoxelValidator(const VolumeType* volData, const Vector3DInt32& v3dPos);
|
||||
|
||||
/// Provides a configuration for the AStarPathfinder.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This structure stores the AStarPathfinder%s configuration options, because this
|
||||
/// is simpler than providing a large number of get/set properties within the
|
||||
/// AStarPathfinder itself. In order to create an instance of this structure you
|
||||
/// must provide at least a volume, a start and end point, and a list to store
|
||||
/// the result. All the other option have sensible default values which can
|
||||
/// optionally be changed for more precise control over the pathfinder's behaviour.
|
||||
///
|
||||
/// \sa AStarPathfinder
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template<typename VolumeType>
|
||||
struct AStarPathfinderParams
|
||||
{
|
||||
public:
|
||||
AStarPathfinderParams
|
||||
(
|
||||
VolumeType* volData,
|
||||
const Vector3DInt32& v3dStart,
|
||||
const Vector3DInt32& v3dEnd,
|
||||
std::list<Vector3DInt32>* listResult,
|
||||
float fHBias = 1.0,
|
||||
uint32_t uMaxNoOfNodes = 10000,
|
||||
Connectivity requiredConnectivity = TwentySixConnected,
|
||||
polyvox_function<bool (const VolumeType*, const Vector3DInt32&)> funcIsVoxelValidForPath = &aStarDefaultVoxelValidator,
|
||||
polyvox_function<void (float)> funcProgressCallback = 0
|
||||
)
|
||||
:volume(volData)
|
||||
,start(v3dStart)
|
||||
,end(v3dEnd)
|
||||
,result(listResult)
|
||||
,connectivity(requiredConnectivity)
|
||||
,hBias(fHBias)
|
||||
,maxNumberOfNodes(uMaxNoOfNodes)
|
||||
,isVoxelValidForPath(funcIsVoxelValidForPath)
|
||||
,progressCallback(funcProgressCallback)
|
||||
{
|
||||
}
|
||||
|
||||
/// This is the volume through which the AStarPathfinder must find a path.
|
||||
VolumeType* volume;
|
||||
|
||||
/// The start point for the pathfinding algorithm.
|
||||
Vector3DInt32 start;
|
||||
|
||||
/// The end point for the pathfinding algorithm.
|
||||
Vector3DInt32 end;
|
||||
|
||||
/// The resulting path will be stored as a series of points in
|
||||
/// this list. Any existing contents will be cleared.
|
||||
std::list<Vector3DInt32>* result;
|
||||
|
||||
/// The AStarPathfinder performs its search by examining the neighbours
|
||||
/// of each voxel it encounters. This property controls the meaning of
|
||||
/// neighbour - e.g. whether two voxels must share a face, edge, or corner.
|
||||
Connectivity connectivity;
|
||||
|
||||
/// For each voxel the pathfinder tracks its distance to the start (known as g())
|
||||
/// and estimates its distance to the end (known as h()). Increasing or decreasing
|
||||
/// h() has an effect on the way the pathfinder behaves. If h() is an underestimate
|
||||
/// of the true distance then the pathfinder will act more like a greedy search -
|
||||
/// always finding the shortest path but taking longer to do so. If h() is an over
|
||||
/// estimate then the pathfinder will behave more like a best-first search - returning
|
||||
/// a potentially suboptimal path but finding it more quickly. The hBias is multiplied
|
||||
/// by the estimated h() value to control this behaviour.
|
||||
float hBias;
|
||||
|
||||
/// Volumes can be pretty huge (millions of voxels) and processing each one of these
|
||||
/// can take a long time. In A* terminology each voxel is a node, and this property
|
||||
/// controls the maximum number of nodes that will be considered when finding the path,
|
||||
/// before giving up and throwing an exception because a path can't be found.
|
||||
uint32_t maxNumberOfNodes;
|
||||
|
||||
/// This function is called to determine whether the path can pass though a given voxel. The
|
||||
/// default behaviour is specified by aStarDefaultVoxelValidator(), but users can specify thier
|
||||
/// own criteria if desired. For example, if you always want a path to follow a surface then
|
||||
/// you could check to ensure that the voxel above is empty and the voxel below is solid.
|
||||
///
|
||||
/// \sa aStarDefaultVoxelValidator
|
||||
polyvox_function<bool (const VolumeType*, const Vector3DInt32&)> isVoxelValidForPath;
|
||||
|
||||
/// This function is called by the AStarPathfinder to report on its progress in getting to
|
||||
/// the goal. The progress is reported by computing the distance from the closest node found
|
||||
/// so far to the end node, and comparing this with the distance from the start node to the
|
||||
/// end node. This progress value is guarenteed to never decrease, but it may stop increasing
|
||||
///for short periods of time. It may even stop increasing altogether if a path cannot be found.
|
||||
polyvox_function<void (float)> progressCallback;
|
||||
};
|
||||
|
||||
/// The AStarPathfinder compute a path from one point in the volume to another.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// A* is a well known pathfinding algorithm commonly used in computer games. It
|
||||
/// takes as input a pair of points in the world, and works out a path between
|
||||
/// them which avoids obstacles and adheres to other user defined criteria. The
|
||||
/// resulting path is usually the shortest possible, but a less optimal path can
|
||||
/// be exchanged for reduced computation time.
|
||||
///
|
||||
/// For an excellent overview of the A* algorithm please see Amit Patel's Game
|
||||
/// Programming page here: http://theory.stanford.edu/~amitp/GameProgramming/
|
||||
/// Much of this class is based on the principles described in those pages.
|
||||
///
|
||||
/// Usage of this class if very strightforward. You create an instance of it
|
||||
/// by passing an instance of the AStarPathfinderParams structure to the constructor.
|
||||
/// The details of the AStarPathfinderParams and the options it provides are described
|
||||
/// in the documentation for that class.
|
||||
///
|
||||
/// Next you call the execute() function and wait for it to return. If a path is
|
||||
/// found then this is stored in the list which was set as the 'result' field of
|
||||
/// the AStarPathfinderParams. If a path cannot be found then an exception of type
|
||||
/// std::runtime_error is thrown.
|
||||
///
|
||||
/// \sa AStarPathfinderParams
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template<typename VolumeType>
|
||||
class AStarPathfinder
|
||||
{
|
||||
public:
|
||||
AStarPathfinder(const AStarPathfinderParams<VolumeType>& params);
|
||||
|
||||
void execute();
|
||||
|
||||
private:
|
||||
void processNeighbour(const Vector3DInt32& neighbourPos, float neighbourGVal);
|
||||
|
||||
float SixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b);
|
||||
float EighteenConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b);
|
||||
float TwentySixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b);
|
||||
float computeH(const Vector3DInt32& a, const Vector3DInt32& b);
|
||||
uint32_t hash(uint32_t a);
|
||||
|
||||
//Node containers
|
||||
AllNodesContainer allNodes;
|
||||
OpenNodesContainer openNodes;
|
||||
ClosedNodesContainer closedNodes;
|
||||
|
||||
//The current node
|
||||
AllNodesContainer::iterator current;
|
||||
|
||||
float m_fProgress;
|
||||
|
||||
AStarPathfinderParams<VolumeType> m_params;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/AStarPathfinder.inl"
|
||||
|
||||
#endif //__PolyVox_AStarPathfinder_H__
|
349
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/AStarPathfinder.inl
vendored
Normal file
349
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/AStarPathfinder.inl
vendored
Normal file
@ -0,0 +1,349 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Using this function, a voxel is considered valid for the path if it is inside the
|
||||
/// volume and if its density is below that returned by the voxel's getDensity() function.
|
||||
/// \return true is the voxel is valid for the path
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template<typename VolumeType>
|
||||
bool aStarDefaultVoxelValidator(const VolumeType* volData, const Vector3DInt32& v3dPos)
|
||||
{
|
||||
//Voxels are considered valid candidates for the path if they are inside the volume...
|
||||
if(volData->getEnclosingRegion().containsPoint(v3dPos) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AStarPathfinder Class
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template<typename VolumeType>
|
||||
AStarPathfinder<VolumeType>::AStarPathfinder(const AStarPathfinderParams<VolumeType>& params)
|
||||
:m_params(params)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename VolumeType>
|
||||
void AStarPathfinder<VolumeType>::execute()
|
||||
{
|
||||
//Clear any existing nodes
|
||||
allNodes.clear();
|
||||
openNodes.clear();
|
||||
closedNodes.clear();
|
||||
|
||||
//Clear the result
|
||||
m_params.result->clear();
|
||||
|
||||
//Iterators to start and end node.
|
||||
AllNodesContainer::iterator startNode = allNodes.insert(Node(m_params.start.getX(), m_params.start.getY(), m_params.start.getZ())).first;
|
||||
AllNodesContainer::iterator endNode = allNodes.insert(Node(m_params.end.getX(), m_params.end.getY(), m_params.end.getZ())).first;
|
||||
|
||||
//Regarding the const_cast - normally you should not modify an object which is in an sdt::set.
|
||||
//The reason is that objects in a set are stored sorted in a tree so they can be accessed quickly,
|
||||
//and changing the object directly can break the sorting. However, in our case we have provided a
|
||||
//custom sort operator for the set which we know only uses the position to sort. Hence we can safely
|
||||
//modify other properties of the object while it is in the set.
|
||||
Node* tempStart = const_cast<Node*>(&(*startNode));
|
||||
tempStart->gVal = 0;
|
||||
tempStart->hVal = computeH(startNode->position, endNode->position);
|
||||
|
||||
Node* tempEnd = const_cast<Node*>(&(*endNode));
|
||||
tempEnd->hVal = 0.0f;
|
||||
|
||||
openNodes.insert(startNode);
|
||||
|
||||
float fDistStartToEnd = (endNode->position - startNode->position).length();
|
||||
m_fProgress = 0.0f;
|
||||
if(m_params.progressCallback)
|
||||
{
|
||||
m_params.progressCallback(m_fProgress);
|
||||
}
|
||||
|
||||
while((openNodes.empty() == false) && (openNodes.getFirst() != endNode))
|
||||
{
|
||||
//Move the first node from open to closed.
|
||||
current = openNodes.getFirst();
|
||||
openNodes.removeFirst();
|
||||
closedNodes.insert(current);
|
||||
|
||||
//Update the user on our progress
|
||||
if(m_params.progressCallback)
|
||||
{
|
||||
const float fMinProgresIncreament = 0.001f;
|
||||
float fDistCurrentToEnd = (endNode->position - current->position).length();
|
||||
float fDistNormalised = fDistCurrentToEnd / fDistStartToEnd;
|
||||
float fProgress = 1.0f - fDistNormalised;
|
||||
if(fProgress >= m_fProgress + fMinProgresIncreament)
|
||||
{
|
||||
m_fProgress = fProgress;
|
||||
m_params.progressCallback(m_fProgress);
|
||||
}
|
||||
}
|
||||
|
||||
//The distance from one cell to another connected by face, edge, or corner.
|
||||
const float fFaceCost = sqrt_1;
|
||||
const float fEdgeCost = sqrt_2;
|
||||
const float fCornerCost = sqrt_3;
|
||||
|
||||
//Process the neighbours. Note the deliberate lack of 'break'
|
||||
//statements, larger connectivities include smaller ones.
|
||||
switch(m_params.connectivity)
|
||||
{
|
||||
case TwentySixConnected:
|
||||
processNeighbour(current->position + arrayPathfinderCorners[0], current->gVal + fCornerCost);
|
||||
processNeighbour(current->position + arrayPathfinderCorners[1], current->gVal + fCornerCost);
|
||||
processNeighbour(current->position + arrayPathfinderCorners[2], current->gVal + fCornerCost);
|
||||
processNeighbour(current->position + arrayPathfinderCorners[3], current->gVal + fCornerCost);
|
||||
processNeighbour(current->position + arrayPathfinderCorners[4], current->gVal + fCornerCost);
|
||||
processNeighbour(current->position + arrayPathfinderCorners[5], current->gVal + fCornerCost);
|
||||
processNeighbour(current->position + arrayPathfinderCorners[6], current->gVal + fCornerCost);
|
||||
processNeighbour(current->position + arrayPathfinderCorners[7], current->gVal + fCornerCost);
|
||||
|
||||
case EighteenConnected:
|
||||
processNeighbour(current->position + arrayPathfinderEdges[ 0], current->gVal + fEdgeCost);
|
||||
processNeighbour(current->position + arrayPathfinderEdges[ 1], current->gVal + fEdgeCost);
|
||||
processNeighbour(current->position + arrayPathfinderEdges[ 2], current->gVal + fEdgeCost);
|
||||
processNeighbour(current->position + arrayPathfinderEdges[ 3], current->gVal + fEdgeCost);
|
||||
processNeighbour(current->position + arrayPathfinderEdges[ 4], current->gVal + fEdgeCost);
|
||||
processNeighbour(current->position + arrayPathfinderEdges[ 5], current->gVal + fEdgeCost);
|
||||
processNeighbour(current->position + arrayPathfinderEdges[ 6], current->gVal + fEdgeCost);
|
||||
processNeighbour(current->position + arrayPathfinderEdges[ 7], current->gVal + fEdgeCost);
|
||||
processNeighbour(current->position + arrayPathfinderEdges[ 8], current->gVal + fEdgeCost);
|
||||
processNeighbour(current->position + arrayPathfinderEdges[ 9], current->gVal + fEdgeCost);
|
||||
processNeighbour(current->position + arrayPathfinderEdges[10], current->gVal + fEdgeCost);
|
||||
processNeighbour(current->position + arrayPathfinderEdges[11], current->gVal + fEdgeCost);
|
||||
|
||||
case SixConnected:
|
||||
processNeighbour(current->position + arrayPathfinderFaces[0], current->gVal + fFaceCost);
|
||||
processNeighbour(current->position + arrayPathfinderFaces[1], current->gVal + fFaceCost);
|
||||
processNeighbour(current->position + arrayPathfinderFaces[2], current->gVal + fFaceCost);
|
||||
processNeighbour(current->position + arrayPathfinderFaces[3], current->gVal + fFaceCost);
|
||||
processNeighbour(current->position + arrayPathfinderFaces[4], current->gVal + fFaceCost);
|
||||
processNeighbour(current->position + arrayPathfinderFaces[5], current->gVal + fFaceCost);
|
||||
}
|
||||
|
||||
if(allNodes.size() > m_params.maxNumberOfNodes)
|
||||
{
|
||||
//We've reached the specified maximum number
|
||||
//of nodes. Just give up on the search.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if((openNodes.empty()) || (openNodes.getFirst() != endNode))
|
||||
{
|
||||
//In this case we failed to find a valid path.
|
||||
throw std::runtime_error("No path found");
|
||||
}
|
||||
else
|
||||
{
|
||||
//Regarding the const_cast - normally you should not modify an object which is in an sdt::set.
|
||||
//The reason is that objects in a set are stored sorted in a tree so they can be accessed quickly,
|
||||
//and changing the object directly can break the sorting. However, in our case we have provided a
|
||||
//custom sort operator for the set which we know only uses the position to sort. Hence we can safely
|
||||
//modify other properties of the object while it is in the set.
|
||||
Node* n = const_cast<Node*>(&(*endNode));
|
||||
while(n != 0)
|
||||
{
|
||||
m_params.result->push_front(n->position);
|
||||
n = n->parent;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_params.progressCallback)
|
||||
{
|
||||
m_params.progressCallback(1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename VolumeType>
|
||||
void AStarPathfinder<VolumeType>::processNeighbour(const Vector3DInt32& neighbourPos, float neighbourGVal)
|
||||
{
|
||||
bool bIsVoxelValidForPath = m_params.isVoxelValidForPath(m_params.volume, neighbourPos);
|
||||
if(!bIsVoxelValidForPath)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float cost = neighbourGVal;
|
||||
|
||||
std::pair<AllNodesContainer::iterator, bool> insertResult = allNodes.insert(Node(neighbourPos.getX(), neighbourPos.getY(), neighbourPos.getZ()));
|
||||
AllNodesContainer::iterator neighbour = insertResult.first;
|
||||
|
||||
if(insertResult.second == true) //New node, compute h.
|
||||
{
|
||||
Node* tempNeighbour = const_cast<Node*>(&(*neighbour));
|
||||
tempNeighbour -> hVal = computeH(neighbour->position, m_params.end);
|
||||
}
|
||||
|
||||
OpenNodesContainer::iterator openIter = openNodes.find(neighbour);
|
||||
if(openIter != openNodes.end())
|
||||
{
|
||||
if(cost < neighbour->gVal)
|
||||
{
|
||||
openNodes.remove(openIter);
|
||||
openIter = openNodes.end();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO - Nodes could keep track of if they are in open or closed? And a pointer to where they are?
|
||||
ClosedNodesContainer::iterator closedIter = closedNodes.find(neighbour);
|
||||
if(closedIter != closedNodes.end())
|
||||
{
|
||||
if(cost < neighbour->gVal)
|
||||
{
|
||||
//Probably shouldn't happen?
|
||||
closedNodes.remove(closedIter);
|
||||
closedIter = closedNodes.end();
|
||||
}
|
||||
}
|
||||
|
||||
if((openIter == openNodes.end()) && (closedIter == closedNodes.end()))
|
||||
{
|
||||
//Regarding the const_cast - normally you should not modify an object which is in an sdt::set.
|
||||
//The reason is that objects in a set are stored sorted in a tree so they can be accessed quickly,
|
||||
//and changing the object directly can break the sorting. However, in our case we have provided a
|
||||
//custom sort operator for the set which we know only uses the position to sort. Hence we can safely
|
||||
//modify other properties of the object while it is in the set.
|
||||
Node* temp = const_cast<Node*>(&(*neighbour));
|
||||
temp->gVal = cost;
|
||||
openNodes.insert(neighbour);
|
||||
temp->parent = const_cast<Node*>(&(*current));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename VolumeType>
|
||||
float AStarPathfinder<VolumeType>::SixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b)
|
||||
{
|
||||
//This is the only heuristic I'm sure of - just use the manhatten distance for the 6-connected case.
|
||||
uint32_t faceSteps = std::abs(a.getX()-b.getX()) + std::abs(a.getY()-b.getY()) + std::abs(a.getZ()-b.getZ());
|
||||
|
||||
return faceSteps * 1.0f;
|
||||
}
|
||||
|
||||
template<typename VolumeType>
|
||||
float AStarPathfinder<VolumeType>::EighteenConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b)
|
||||
{
|
||||
//I'm not sure of the correct heuristic for the 18-connected case, so I'm just letting it fall through to the
|
||||
//6-connected case. This means 'h' will be bigger than it should be, resulting in a faster path which may not
|
||||
//actually be the shortest one. If you have a correct heuristic for the 18-connected case then please let me know.
|
||||
|
||||
return SixConnectedCost(a,b);
|
||||
}
|
||||
|
||||
template<typename VolumeType>
|
||||
float AStarPathfinder<VolumeType>::TwentySixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b)
|
||||
{
|
||||
//Can't say I'm certain about this heuristic - if anyone has
|
||||
//a better idea of what it should be then please let me know.
|
||||
uint32_t array[3];
|
||||
array[0] = std::abs(a.getX() - b.getX());
|
||||
array[1] = std::abs(a.getY() - b.getY());
|
||||
array[2] = std::abs(a.getZ() - b.getZ());
|
||||
|
||||
//Maybe this is better implemented directly
|
||||
//using three compares and two swaps... but not
|
||||
//until the profiler says so.
|
||||
std::sort(&array[0], &array[3]);
|
||||
|
||||
uint32_t cornerSteps = array[0];
|
||||
uint32_t edgeSteps = array[1] - array[0];
|
||||
uint32_t faceSteps = array[2] - array[1];
|
||||
|
||||
return cornerSteps * sqrt_3 + edgeSteps * sqrt_2 + faceSteps * sqrt_1;
|
||||
}
|
||||
|
||||
template<typename VolumeType>
|
||||
float AStarPathfinder<VolumeType>::computeH(const Vector3DInt32& a, const Vector3DInt32& b)
|
||||
{
|
||||
float hVal;
|
||||
|
||||
switch(m_params.connectivity)
|
||||
{
|
||||
case TwentySixConnected:
|
||||
hVal = TwentySixConnectedCost(a, b);
|
||||
break;
|
||||
case EighteenConnected:
|
||||
hVal = EighteenConnectedCost(a, b);
|
||||
break;
|
||||
case SixConnected:
|
||||
hVal = SixConnectedCost(a, b);
|
||||
break;
|
||||
default:
|
||||
assert(false); //Invalid case.
|
||||
}
|
||||
|
||||
//Sanity checks in debug mode. These can come out eventually, but I
|
||||
//want to make sure that the heuristics I've come up with make sense.
|
||||
assert((a-b).length() <= TwentySixConnectedCost(a,b));
|
||||
assert(TwentySixConnectedCost(a,b) <= EighteenConnectedCost(a,b));
|
||||
assert(EighteenConnectedCost(a,b) <= SixConnectedCost(a,b));
|
||||
|
||||
//Apply the bias to the computed h value;
|
||||
hVal *= m_params.hBias;
|
||||
|
||||
//Having computed hVal, we now apply some random bias to break ties.
|
||||
//This needs to be deterministic on the input position. This random
|
||||
//bias means it is much les likely that two paths are exactly the same
|
||||
//length, and so far fewer nodes must be expanded to find the shortest path.
|
||||
//See http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html#S12
|
||||
|
||||
//Note that if the hash is zero we can have differences between the Linux vs. Windows
|
||||
//(or perhaps GCC vs. VS) versions of the code. This is probably because of the way
|
||||
//sorting inside the std::set works (i.e. one system swaps values which are identical
|
||||
//while the other one doesn't - both approaches are valid). For the same reason we want
|
||||
//to make sure that position (x,y,z) has a differnt hash from e.g. position (x,z,y).
|
||||
uint32_t aX = (a.getX() << 16) & 0x00FF0000;
|
||||
uint32_t aY = (a.getY() << 8) & 0x0000FF00;
|
||||
uint32_t aZ = (a.getZ() ) & 0x000000FF;
|
||||
uint32_t hashVal = hash(aX | aY | aZ);
|
||||
|
||||
//Stop hashVal going over 65535, and divide by 1000000 to make sure it is small.
|
||||
hashVal &= 0x0000FFFF;
|
||||
float fHash = hashVal / 1000000.0f;
|
||||
|
||||
//Apply the hash and return
|
||||
hVal += fHash;
|
||||
return hVal;
|
||||
}
|
||||
|
||||
// Robert Jenkins' 32 bit integer hash function
|
||||
// http://www.concentric.net/~ttwang/tech/inthash.htm
|
||||
template<typename VolumeType>
|
||||
uint32_t AStarPathfinder<VolumeType>::hash( uint32_t a)
|
||||
{
|
||||
a = (a+0x7ed55d16) + (a<<12);
|
||||
a = (a^0xc761c23c) ^ (a>>19);
|
||||
a = (a+0x165667b1) + (a<<5);
|
||||
a = (a+0xd3a2646c) ^ (a<<9);
|
||||
a = (a+0xfd7046c5) + (a<<3);
|
||||
a = (a^0xb55a4f09) ^ (a>>16);
|
||||
return a;
|
||||
}
|
||||
}
|
82
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/AmbientOcclusionCalculator.h
vendored
Normal file
82
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/AmbientOcclusionCalculator.h
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
/*******************************************************************************
|
||||
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 __AmbientOcclusionCalculator_H__
|
||||
#define __AmbientOcclusionCalculator_H__
|
||||
|
||||
#include "Impl/RandomUnitVectors.h"
|
||||
#include "Impl/RandomVectors.h"
|
||||
|
||||
#include "PolyVoxCore/Array.h"
|
||||
#include "PolyVoxCore/Region.h"
|
||||
#include "PolyVoxCore/Raycast.h"
|
||||
|
||||
//These two should not be here!
|
||||
#include "PolyVoxCore/Material.h"
|
||||
#include "PolyVoxCore/SimpleVolume.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Ambient occlusion
|
||||
*/
|
||||
|
||||
template<typename IsVoxelTransparentCallback>
|
||||
class AmbientOcclusionCalculatorRaycastCallback
|
||||
{
|
||||
public:
|
||||
AmbientOcclusionCalculatorRaycastCallback(IsVoxelTransparentCallback isVoxelTransparentCallback) : mIsVoxelTransparentCallback(isVoxelTransparentCallback)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(const SimpleVolume<uint8_t>::Sampler& sampler)
|
||||
{
|
||||
uint8_t sample = sampler.getVoxel();
|
||||
bool func = mIsVoxelTransparentCallback(sample);
|
||||
return func;
|
||||
}
|
||||
|
||||
IsVoxelTransparentCallback mIsVoxelTransparentCallback;
|
||||
};
|
||||
|
||||
// NOTE: The callback needs to be a functor not a function. I haven't been
|
||||
// able to work the required template magic to get functions working as well.
|
||||
//
|
||||
// Matt: If you make the function take a "IsVoxelTransparentCallback&&" then
|
||||
// it will forward it on. Works for functors, functions and lambdas.
|
||||
// This will be 'perfect forwarding' using 'universal references'
|
||||
// This will require C++11 rvalue references which is why I haven't made the
|
||||
// change yet.
|
||||
|
||||
/// Calculate the ambient occlusion for the volume
|
||||
template<typename VolumeType, typename IsVoxelTransparentCallback>
|
||||
void calculateAmbientOcclusion(VolumeType* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement, IsVoxelTransparentCallback isVoxelTransparentCallback);
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/AmbientOcclusionCalculator.inl"
|
||||
|
||||
#endif //__AmbientOcclusionCalculator_H__
|
127
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/AmbientOcclusionCalculator.inl
vendored
Normal file
127
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/AmbientOcclusionCalculator.inl
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/**
|
||||
* \param volInput The volume to calculate the ambient occlusion for
|
||||
* \param[out] arrayResult The output of the calculator
|
||||
* \param region The region of the volume for which the occlusion should be calculated
|
||||
* \param fRayLength The length for each test ray
|
||||
* \param uNoOfSamplesPerOutputElement The number of samples to calculate the occlusion
|
||||
* \param isVoxelTransparentCallback A callback which takes a \a VoxelType and returns a \a bool whether the voxel is transparent
|
||||
*/
|
||||
template<typename VolumeType, typename IsVoxelTransparentCallback>
|
||||
void calculateAmbientOcclusion(VolumeType* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement, IsVoxelTransparentCallback isVoxelTransparentCallback)
|
||||
{
|
||||
typename VolumeType::Sampler m_sampVolume(volInput);
|
||||
|
||||
uint16_t uRandomUnitVectorIndex = 0;
|
||||
uint16_t uRandomVectorIndex = 0;
|
||||
uint16_t uIndexIncreament;
|
||||
|
||||
//Make sure that the size of the volume is an exact multiple of the size of the array.
|
||||
assert(volInput->getWidth() % arrayResult->getDimension(0) == 0);
|
||||
assert(volInput->getHeight() % arrayResult->getDimension(1) == 0);
|
||||
assert(volInput->getDepth() % arrayResult->getDimension(2) == 0);
|
||||
|
||||
//Our initial indices. It doesn't matter exactly what we set here, but the code below makes
|
||||
//sure they are different for different regions which helps reduce tiling patterns in the results.
|
||||
uRandomUnitVectorIndex += region.getLowerCorner().getX() + region.getLowerCorner().getY() + region.getLowerCorner().getZ();
|
||||
uRandomVectorIndex += region.getLowerCorner().getX() + region.getLowerCorner().getY() + region.getLowerCorner().getZ();
|
||||
|
||||
//This value helps us jump around in the array a bit more, so the
|
||||
//nth 'random' value isn't always followed by the n+1th 'random' value.
|
||||
uIndexIncreament = 1;
|
||||
|
||||
const int iRatioX = volInput->getWidth() / arrayResult->getDimension(0);
|
||||
const int iRatioY = volInput->getHeight() / arrayResult->getDimension(1);
|
||||
const int iRatioZ = volInput->getDepth() / arrayResult->getDimension(2);
|
||||
|
||||
const float fRatioX = iRatioX;
|
||||
const float fRatioY = iRatioY;
|
||||
const float fRatioZ = iRatioZ;
|
||||
const Vector3DFloat v3dRatio(fRatioX, fRatioY, fRatioZ);
|
||||
|
||||
const float fHalfRatioX = fRatioX * 0.5f;
|
||||
const float fHalfRatioY = fRatioY * 0.5f;
|
||||
const float fHalfRatioZ = fRatioZ * 0.5f;
|
||||
const Vector3DFloat v3dHalfRatio(fHalfRatioX, fHalfRatioY, fHalfRatioZ);
|
||||
|
||||
const Vector3DFloat v3dOffset(0.5f,0.5f,0.5f);
|
||||
|
||||
//This loop iterates over the bottom-lower-left voxel in each of the cells in the output array
|
||||
for(uint16_t z = region.getLowerCorner().getZ(); z <= region.getUpperCorner().getZ(); z += iRatioZ)
|
||||
{
|
||||
for(uint16_t y = region.getLowerCorner().getY(); y <= region.getUpperCorner().getY(); y += iRatioY)
|
||||
{
|
||||
for(uint16_t x = region.getLowerCorner().getX(); x <= region.getUpperCorner().getX(); x += iRatioX)
|
||||
{
|
||||
//Compute a start position corresponding to
|
||||
//the centre of the cell in the output array.
|
||||
Vector3DFloat v3dStart(x, y, z);
|
||||
v3dStart -= v3dOffset;
|
||||
v3dStart += v3dHalfRatio;
|
||||
|
||||
//Keep track of how many rays did not hit anything
|
||||
uint8_t uVisibleDirections = 0;
|
||||
|
||||
for(int ct = 0; ct < uNoOfSamplesPerOutputElement; ct++)
|
||||
{
|
||||
//We take a random vector with components going from -1 to 1 and scale it to go from -halfRatio to +halfRatio.
|
||||
//This jitter value moves our sample point from the centre of the array cell to somewhere else in the array cell
|
||||
Vector3DFloat v3dJitter = randomVectors[(uRandomVectorIndex += (++uIndexIncreament)) % 1019]; //Prime number helps avoid repetition on successive loops.
|
||||
v3dJitter *= v3dHalfRatio;
|
||||
const Vector3DFloat v3dRayStart = v3dStart + v3dJitter;
|
||||
|
||||
Vector3DFloat v3dRayDirection = randomUnitVectors[(uRandomUnitVectorIndex += (++uIndexIncreament)) % 1021]; //Different prime number.
|
||||
v3dRayDirection *= fRayLength;
|
||||
|
||||
AmbientOcclusionCalculatorRaycastCallback<IsVoxelTransparentCallback> ambientOcclusionCalculatorRaycastCallback(isVoxelTransparentCallback);
|
||||
RaycastResult result = raycastWithDirection(volInput, v3dRayStart, v3dRayDirection, ambientOcclusionCalculatorRaycastCallback);
|
||||
|
||||
if(result == RaycastResults::Completed)
|
||||
{
|
||||
++uVisibleDirections;
|
||||
}
|
||||
}
|
||||
|
||||
float fVisibility;
|
||||
if(uNoOfSamplesPerOutputElement == 0)
|
||||
{
|
||||
//The user might request zero samples (I've done this in the past while debugging - I don't want to
|
||||
//wait for ambient occlusion but I do want as valid result for rendering). Avoid the divide by zero.
|
||||
fVisibility = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
fVisibility = static_cast<float>(uVisibleDirections) / static_cast<float>(uNoOfSamplesPerOutputElement);
|
||||
assert((fVisibility >= 0.0f) && (fVisibility <= 1.0f));
|
||||
}
|
||||
|
||||
(*arrayResult)[z / iRatioZ][y / iRatioY][x / iRatioX] = static_cast<uint8_t>(255.0f * fVisibility);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
210
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Array.h
vendored
Normal file
210
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Array.h
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
/*******************************************************************************
|
||||
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_Array_H__
|
||||
#define __PolyVox_Array_H__
|
||||
|
||||
#include "Impl/SubArray.h"
|
||||
|
||||
#include "PolyVoxCore/ArraySizes.h" //Not strictly required, but convienient
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
///Provides an efficient implementation of a multidimensional array.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// While C++ provides one-dimensional arrays as a language feature, it does not
|
||||
/// provide a simple and intuitive way of working with multidimensional arrays
|
||||
/// whose sizes are specified at runtime. Such a construct is very useful within
|
||||
/// the context of PolyVox, and this Array class provides such functionality
|
||||
/// implemented via templates and partial specialisation.
|
||||
///
|
||||
/// The following code snippet illustrates the basic usage of the class by writing
|
||||
/// a different value into each element:
|
||||
///
|
||||
/// \code
|
||||
/// int width = 5;
|
||||
/// int height = 10;
|
||||
/// int depth = 20;
|
||||
///
|
||||
/// //Creates a 3D array of integers with dimensions 5x10x20
|
||||
/// Array<3, int> myArray(ArraySizes(width)(height)(depth));
|
||||
///
|
||||
/// int ct = 1;
|
||||
/// for(int z = 0; z < depth; z++)
|
||||
/// {
|
||||
/// for(int y = 0; y < height; y++)
|
||||
/// {
|
||||
/// for(int x = 0; x < width; x++)
|
||||
/// {
|
||||
/// myArray[x][y][z] = ct;
|
||||
/// ct++;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// Although the constructor and resize() functions both take the required dimensions
|
||||
/// as an array of ints, note that the ArraySizes class can be used to build this
|
||||
/// inline. This is a more convienient way of specifying these dimensions.
|
||||
///
|
||||
/// Note also that this class has a private assignment operator and copy constructor
|
||||
/// in order to prevent copying. This is because a deep copy is a potentially slow
|
||||
/// operation and can often be performed inadvertently by functions such as std::swap,
|
||||
/// while a shallow copy introduces confusion over memory ownership.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
class Array
|
||||
{
|
||||
public:
|
||||
///Constructor
|
||||
Array<noOfDims, ElementType>();
|
||||
///Constructor
|
||||
Array<noOfDims, ElementType>(const uint32_t (&pDimensions)[noOfDims]);
|
||||
///Destructor
|
||||
~Array<noOfDims, ElementType>();
|
||||
|
||||
///Subarray access
|
||||
SubArray<noOfDims-1, ElementType> operator[](uint32_t uIndex);
|
||||
///Subarray access
|
||||
const SubArray<noOfDims-1, ElementType> operator[](uint32_t uIndex) const;
|
||||
|
||||
///Gets the total number of elements in this array
|
||||
uint32_t getNoOfElements(void) const;
|
||||
///Gets a pointer to the first element of the array
|
||||
ElementType* getRawData(void) const;
|
||||
|
||||
///Resize the array to the specified dimensions
|
||||
void resize(const uint32_t (&pDimensions)[noOfDims]);
|
||||
///Swaps the contents of this array with the one specified
|
||||
void swap(Array<noOfDims, ElementType>& rhs);
|
||||
///Get the size of the Array along the specified dimension
|
||||
uint32_t getDimension(uint32_t uDimension);
|
||||
|
||||
private:
|
||||
Array<noOfDims, ElementType>(const Array<noOfDims, ElementType>& rhs);
|
||||
|
||||
Array<noOfDims, ElementType>& operator=(const Array<noOfDims, ElementType>& rhs);
|
||||
|
||||
void deallocate(void);
|
||||
|
||||
uint32_t * m_pDimensions;
|
||||
uint32_t * m_pOffsets;
|
||||
uint32_t m_uNoOfElements;
|
||||
ElementType * m_pElements;
|
||||
};
|
||||
|
||||
template <typename ElementType>
|
||||
class Array<1, ElementType>
|
||||
{
|
||||
public:
|
||||
Array<1, ElementType>();
|
||||
|
||||
Array<1, ElementType>(const uint32_t (&pDimensions)[1]);
|
||||
|
||||
~Array<1, ElementType>();
|
||||
|
||||
ElementType& operator[] (uint32_t uIndex);
|
||||
|
||||
const ElementType& operator[] (uint32_t uIndex) const;
|
||||
|
||||
uint32_t getNoOfElements(void) const;
|
||||
|
||||
ElementType* getRawData(void) const;
|
||||
|
||||
void resize(const uint32_t (&pDimensions)[1]);
|
||||
|
||||
void swap(Array<1, ElementType>& rhs);
|
||||
|
||||
private:
|
||||
Array<1, ElementType>(const Array<1, ElementType>& rhs);
|
||||
|
||||
Array<1, ElementType>& operator=(const Array<1, ElementType>& rhs);
|
||||
|
||||
void deallocate(void);
|
||||
|
||||
uint32_t * m_pDimensions;
|
||||
ElementType * m_pElements;
|
||||
};
|
||||
|
||||
template <typename ElementType>
|
||||
class Array<0, ElementType>
|
||||
{
|
||||
//Zero dimensional array is meaningless.
|
||||
};
|
||||
|
||||
//Some handy typedefs
|
||||
///A 1D Array of floats.
|
||||
typedef Array<1,float> Array1DFloat;
|
||||
///A 1D Array of doubles.
|
||||
typedef Array<1,double> Array1DDouble;
|
||||
///A 1D Array of signed 8-bit values.
|
||||
typedef Array<1,int8_t> Array1DInt8;
|
||||
///A 1D Array of unsigned 8-bit values.
|
||||
typedef Array<1,uint8_t> Array1DUint8;
|
||||
///A 1D Array of signed 16-bit values.
|
||||
typedef Array<1,int16_t> Array1DInt16;
|
||||
///A 1D Array of unsigned 16-bit values.
|
||||
typedef Array<1,uint16_t> Array1DUint16;
|
||||
///A 1D Array of signed 32-bit values.
|
||||
typedef Array<1,int32_t> Array1DInt32;
|
||||
///A 1D Array of unsigned 32-bit values.
|
||||
typedef Array<1,uint32_t> Array1DUint32;
|
||||
|
||||
///A 2D Array of floats.
|
||||
typedef Array<2,float> Array2DFloat;
|
||||
///A 2D Array of doubles.
|
||||
typedef Array<2,double> Array2DDouble;
|
||||
///A 2D Array of signed 8-bit values.
|
||||
typedef Array<2,int8_t> Array2DInt8;
|
||||
///A 2D Array of unsigned 8-bit values.
|
||||
typedef Array<2,uint8_t> Array2DUint8;
|
||||
///A 2D Array of signed 16-bit values.
|
||||
typedef Array<2,int16_t> Array2DInt16;
|
||||
///A 2D Array of unsigned 16-bit values.
|
||||
typedef Array<2,uint16_t> Array2DUint16;
|
||||
///A 2D Array of signed 32-bit values.
|
||||
typedef Array<2,int32_t> Array2DInt32;
|
||||
///A 2D Array of unsigned 32-bit values.
|
||||
typedef Array<2,uint32_t> Array2DUint32;
|
||||
|
||||
///A 3D Array of floats.
|
||||
typedef Array<3,float> Array3DFloat;
|
||||
///A 3D Array of doubles.
|
||||
typedef Array<3,double> Array3DDouble;
|
||||
///A 3D Array of signed 8-bit values.
|
||||
typedef Array<3,int8_t> Array3DInt8;
|
||||
///A 3D Array of unsigned 8-bit values.
|
||||
typedef Array<3,uint8_t> Array3DUint8;
|
||||
///A 3D Array of signed 16-bit values.
|
||||
typedef Array<3,int16_t> Array3DInt16;
|
||||
///A 3D Array of unsigned 16-bit values.
|
||||
typedef Array<3,uint16_t> Array3DUint16;
|
||||
///A 3D Array of signed 32-bit values.
|
||||
typedef Array<3,int32_t> Array3DInt32;
|
||||
///A 3D Array of unsigned 32-bit values.
|
||||
typedef Array<3,uint32_t> Array3DUint32;
|
||||
}//namespace PolyVox
|
||||
|
||||
#include "PolyVoxCore/Array.inl"
|
||||
|
||||
#endif
|
330
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Array.inl
vendored
Normal file
330
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Array.inl
vendored
Normal file
@ -0,0 +1,330 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Creates an empty array with no elements. You will have to call resize() on this
|
||||
/// array before it can be used.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
Array<noOfDims, ElementType>::Array()
|
||||
:m_pDimensions(0)
|
||||
,m_pOffsets(0)
|
||||
,m_uNoOfElements(0)
|
||||
,m_pElements(0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Creates an array with the specified dimensions.
|
||||
/// \param pDimensions The dimensions of the array. You can also use the ArraySizes
|
||||
/// class to construct this more easily.
|
||||
/// \sa ArraySizes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
Array<noOfDims, ElementType>::Array(const uint32_t (&pDimensions)[noOfDims])
|
||||
:m_pDimensions(0)
|
||||
,m_pOffsets(0)
|
||||
,m_uNoOfElements(0)
|
||||
,m_pElements(0)
|
||||
{
|
||||
resize(pDimensions);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Destroys the array and releases all owned memory.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
Array<noOfDims, ElementType>::~Array()
|
||||
{
|
||||
deallocate();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// An N-dimensional array can be conceptually consists of N subarrays each of which
|
||||
/// has N-1 dimensions. For example, a 3D array conceptually consists of three 2D
|
||||
/// arrays. This operator is used to access the subarray at the specified index.
|
||||
/// Crucially, the subarray defines a similar operator allowing them to be chained
|
||||
/// together to convieniently access a particular element.
|
||||
/// \param uIndex The zero-based index of the subarray to retrieve.
|
||||
/// \return The requested SubArray
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
SubArray<noOfDims-1, ElementType> Array<noOfDims, ElementType>::operator[](uint32_t uIndex)
|
||||
{
|
||||
assert(uIndex<m_pDimensions[0]);
|
||||
return
|
||||
SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]],
|
||||
m_pDimensions+1, m_pOffsets+1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// An N-dimensional array can be conceptually consists of N subarrays each of which
|
||||
/// has N-1 dimensions. For example, a 3D array conceptually consists of three 2D
|
||||
/// arrays. This operator is used to access the subarray at the specified index.
|
||||
/// Crucially, the subarray defines a similar operator allowing them to be chained
|
||||
/// together to convieniently access a particular element.
|
||||
/// \param uIndex The zero-based index of the subarray to retrieve.
|
||||
/// \return The requested SubArray
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
const SubArray<noOfDims-1, ElementType> Array<noOfDims, ElementType>::operator[](uint32_t uIndex) const
|
||||
{
|
||||
assert(uIndex<m_pDimensions[0]);
|
||||
return
|
||||
SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]],
|
||||
m_pDimensions+1, m_pOffsets+1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \return The number of elements in the array.
|
||||
/// \sa getRawData()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
uint32_t Array<noOfDims, ElementType>::getNoOfElements(void) const
|
||||
{
|
||||
return m_uNoOfElements;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sometimes it is useful to directly manipulate the underlying array without
|
||||
/// going through this classes interface. Although this does not honour the principle
|
||||
/// of encapsulation it can be done safely if you are careful and can sometimes be
|
||||
/// useful. Use getNoOfElements() to determine how far you can safely write.
|
||||
/// \return A pointer to the first element of the array
|
||||
/// \sa getNoOfElements()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
ElementType* Array<noOfDims, ElementType>::getRawData(void) const
|
||||
{
|
||||
return m_pElements;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Please note that the existing contents of the array will be lost.
|
||||
/// \param pDimensions The new dimensions of the array. You can also use the
|
||||
/// ArraySizes class to specify this more easily.
|
||||
/// \sa ArraySizes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
void Array<noOfDims, ElementType>::resize(const uint32_t (&pDimensions)[noOfDims])
|
||||
{
|
||||
deallocate();
|
||||
|
||||
m_pDimensions = new uint32_t[noOfDims];
|
||||
m_pOffsets = new uint32_t[noOfDims];
|
||||
|
||||
// Calculate all the information you need to use the array
|
||||
m_uNoOfElements = 1;
|
||||
for (uint32_t i = 0; i<noOfDims; i++)
|
||||
{
|
||||
assert(pDimensions[i] != 0);
|
||||
|
||||
m_uNoOfElements *= pDimensions[i];
|
||||
m_pDimensions[i] = pDimensions[i];
|
||||
m_pOffsets[i] = 1;
|
||||
for (uint32_t k=noOfDims-1; k>i; k--)
|
||||
{
|
||||
m_pOffsets[i] *= pDimensions[k];
|
||||
}
|
||||
}
|
||||
// Allocate new elements, let exception propagate
|
||||
m_pElements = new ElementType[m_uNoOfElements];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Because this class does not have a public assignment operator or copy constructor
|
||||
/// it cannot be used with the STL swap() function. This function provides an efficient
|
||||
/// implementation of that feature.
|
||||
/// \param rhs The array to swap this object with.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
void Array<noOfDims, ElementType>::swap(Array<noOfDims, ElementType>& rhs)
|
||||
{
|
||||
//Implement this function without temporary 'Array'
|
||||
//objects, as the destructors will free the memory...
|
||||
uint32_t* m_pTempDimensions = m_pDimensions;
|
||||
uint32_t* m_pTempOffsets = m_pOffsets;
|
||||
uint32_t m_uTempNoOfElements = m_uNoOfElements;
|
||||
ElementType* m_pTempElements = m_pElements;
|
||||
|
||||
m_pDimensions = rhs.m_pDimensions;
|
||||
m_pOffsets = rhs.m_pOffsets;
|
||||
m_uNoOfElements = rhs.m_uNoOfElements;
|
||||
m_pElements = rhs.m_pElements;
|
||||
|
||||
rhs.m_pDimensions = m_pTempDimensions;
|
||||
rhs.m_pOffsets = m_pTempOffsets;
|
||||
rhs.m_uNoOfElements = m_uTempNoOfElements;
|
||||
rhs.m_pElements = m_pTempElements;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param uDimension The dimension to get the size of.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
uint32_t Array<noOfDims, ElementType>::getDimension(uint32_t uDimension)
|
||||
{
|
||||
assert(uDimension < noOfDims);
|
||||
return m_pDimensions[uDimension];
|
||||
}
|
||||
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
Array<noOfDims, ElementType>::Array(const Array<noOfDims, ElementType>& rhs)
|
||||
:m_pElements(0)
|
||||
,m_pDimensions(0)
|
||||
,m_pOffsets(0)
|
||||
,m_uNoOfElements(0)
|
||||
{
|
||||
//Not implemented
|
||||
assert(false);
|
||||
}
|
||||
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
Array<noOfDims, ElementType>& Array<noOfDims, ElementType>::operator=(const Array<noOfDims, ElementType>& rhs)
|
||||
{
|
||||
//Not implemented
|
||||
assert(false);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
void Array<noOfDims, ElementType>::deallocate(void)
|
||||
{
|
||||
delete[] m_pDimensions;
|
||||
m_pDimensions = 0;
|
||||
delete[] m_pOffsets;
|
||||
m_pOffsets = 0;
|
||||
delete[] m_pElements;
|
||||
m_pElements = 0;
|
||||
|
||||
m_uNoOfElements = 0;
|
||||
}
|
||||
|
||||
//****************************************************************************//
|
||||
// One dimensional specialisation begins here //
|
||||
//****************************************************************************//
|
||||
|
||||
template <typename ElementType>
|
||||
Array<1, ElementType>::Array()
|
||||
: m_pElements(0)
|
||||
,m_pDimensions(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
Array<1, ElementType>::Array(const uint32_t (&pDimensions)[1])
|
||||
: m_pElements(0)
|
||||
,m_pDimensions(0)
|
||||
{
|
||||
resize(pDimensions);
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
Array<1, ElementType>::~Array()
|
||||
{
|
||||
deallocate();
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
ElementType& Array<1, ElementType>::operator[] (uint32_t uIndex)
|
||||
{
|
||||
assert(uIndex<m_pDimensions[0]);
|
||||
return m_pElements[uIndex];
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
const ElementType& Array<1, ElementType>::operator[] (uint32_t uIndex) const
|
||||
{
|
||||
assert(uIndex<m_pDimensions[0]);
|
||||
return m_pElements[uIndex];
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
uint32_t Array<1, ElementType>::getNoOfElements(void) const
|
||||
{
|
||||
return m_pDimensions[0];
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
ElementType* Array<1, ElementType>::getRawData(void) const
|
||||
{
|
||||
return m_pElements;
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
void Array<1, ElementType>::resize(const uint32_t (&pDimensions)[1])
|
||||
{
|
||||
deallocate();
|
||||
|
||||
m_pDimensions = new uint32_t[1];
|
||||
m_pDimensions[0] = pDimensions[0];
|
||||
|
||||
// Allocate new elements, let exception propagate
|
||||
m_pElements = new ElementType[m_pDimensions[0]];
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
void Array<1, ElementType>::swap(Array<1, ElementType>& rhs)
|
||||
{
|
||||
//Implement this function without temporary 'Array'
|
||||
//objects, as the destructors will free the memory...
|
||||
uint32_t* m_pTempDimensions = m_pDimensions;
|
||||
ElementType* m_pTempElements = m_pElements;
|
||||
|
||||
m_pDimensions = rhs.m_pDimensions;
|
||||
m_pElements = rhs.m_pElements;
|
||||
|
||||
rhs.m_pDimensions = m_pTempDimensions;
|
||||
rhs.m_pElements = m_pTempElements;
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
Array<1, ElementType>::Array(const Array<1, ElementType>& rhs)
|
||||
: m_pElements(0)
|
||||
,m_pDimensions(0)
|
||||
{
|
||||
//Not implemented
|
||||
assert(false);
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
Array<1, ElementType>& Array<1, ElementType>::operator=(const Array<1, ElementType>& rhs)
|
||||
{
|
||||
//Not implemented
|
||||
assert(false);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
void Array<1, ElementType>::deallocate(void)
|
||||
{
|
||||
delete[] m_pDimensions;
|
||||
m_pDimensions = 0;
|
||||
delete[] m_pElements;
|
||||
m_pElements = 0;
|
||||
}
|
||||
}//namespace PolyVox
|
77
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/ArraySizes.h
vendored
Normal file
77
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/ArraySizes.h
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
/*******************************************************************************
|
||||
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_ArraySizes_H__
|
||||
#define __PolyVox_ArraySizes_H__
|
||||
|
||||
#include "Impl/ArraySizesImpl.h"
|
||||
#include "Impl/TypeDef.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
///The ArraySizes class provide a convienient way to specify the dimensions of an Array.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// The Array class requires an array of integers to be passed to the constructor
|
||||
/// to specify the dimensions of the Array to be built. C++ does not allow this to
|
||||
/// be done in place, and so it typically requires an extra line of code - something
|
||||
/// like this:
|
||||
///
|
||||
/// \code
|
||||
/// uint32_t dimensions[3] = {10, 20, 30}; // Array dimensions
|
||||
/// Array<3,float> array(dimensions);
|
||||
/// \endcode
|
||||
///
|
||||
/// The ArraySizes class can be constructed in place, and also provides implicit
|
||||
/// conversion to an array of integers. Hence it is now possible to declare the
|
||||
/// above Array as follows:
|
||||
///
|
||||
/// \code
|
||||
/// Array<3,float> array(ArraySizes(10)(20)(30));
|
||||
/// \endcode
|
||||
///
|
||||
/// Usage of this class is therefore very simple, although the template code
|
||||
/// behind it may appear complex. For reference, it is based upon the article here:
|
||||
/// http://www.drdobbs.com/cpp/184401319/
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class POLYVOX_API ArraySizes
|
||||
{
|
||||
typedef const uint32_t (&UIntArray1)[1];
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
explicit ArraySizes(uint32_t uSize);
|
||||
|
||||
/// Duplicates this object but with an extra dimension
|
||||
ArraySizesImpl<2> operator () (uint32_t uSize);
|
||||
|
||||
/// Converts this object to an array of integers
|
||||
operator UIntArray1 () const;
|
||||
|
||||
private:
|
||||
// This class is only one dimensional. Higher dimensions
|
||||
// are implemented via the ArraySizesImpl class.
|
||||
uint32_t m_pSizes[1];
|
||||
};
|
||||
}//namespace PolyVox
|
||||
|
||||
#endif //__PolyVox_ArraySizes_H__
|
168
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/BaseVolume.h
vendored
Normal file
168
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/BaseVolume.h
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
/*******************************************************************************
|
||||
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_BaseVolume_H__
|
||||
#define __PolyVox_BaseVolume_H__
|
||||
|
||||
#include "PolyVoxCore/Log.h"
|
||||
#include "PolyVoxCore/Region.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/// The BaseVolume class provides common functionality and an interface for other volume classes to implement. You should not try to create an instance of this
|
||||
/// class directly. Instead you should use RawVolume, SimpleVolume, or LargeVolume.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// More details to come...
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename _VoxelType>
|
||||
class BaseVolume
|
||||
{
|
||||
public:
|
||||
typedef _VoxelType VoxelType;
|
||||
|
||||
#ifndef SWIG
|
||||
template <typename DerivedVolumeType>
|
||||
class Sampler
|
||||
{
|
||||
public:
|
||||
Sampler(DerivedVolumeType* volume);
|
||||
~Sampler();
|
||||
|
||||
Vector3DInt32 getPosition(void) const;
|
||||
inline VoxelType getVoxel(void) const;
|
||||
|
||||
void setPosition(const Vector3DInt32& v3dNewPos);
|
||||
void setPosition(int32_t xPos, int32_t yPos, int32_t zPos);
|
||||
inline bool setVoxel(VoxelType tValue);
|
||||
|
||||
void movePositiveX(void);
|
||||
void movePositiveY(void);
|
||||
void movePositiveZ(void);
|
||||
|
||||
void moveNegativeX(void);
|
||||
void moveNegativeY(void);
|
||||
void moveNegativeZ(void);
|
||||
|
||||
inline VoxelType peekVoxel1nx1ny1nz(void) const;
|
||||
inline VoxelType peekVoxel1nx1ny0pz(void) const;
|
||||
inline VoxelType peekVoxel1nx1ny1pz(void) const;
|
||||
inline VoxelType peekVoxel1nx0py1nz(void) const;
|
||||
inline VoxelType peekVoxel1nx0py0pz(void) const;
|
||||
inline VoxelType peekVoxel1nx0py1pz(void) const;
|
||||
inline VoxelType peekVoxel1nx1py1nz(void) const;
|
||||
inline VoxelType peekVoxel1nx1py0pz(void) const;
|
||||
inline VoxelType peekVoxel1nx1py1pz(void) const;
|
||||
|
||||
inline VoxelType peekVoxel0px1ny1nz(void) const;
|
||||
inline VoxelType peekVoxel0px1ny0pz(void) const;
|
||||
inline VoxelType peekVoxel0px1ny1pz(void) const;
|
||||
inline VoxelType peekVoxel0px0py1nz(void) const;
|
||||
inline VoxelType peekVoxel0px0py0pz(void) const;
|
||||
inline VoxelType peekVoxel0px0py1pz(void) const;
|
||||
inline VoxelType peekVoxel0px1py1nz(void) const;
|
||||
inline VoxelType peekVoxel0px1py0pz(void) const;
|
||||
inline VoxelType peekVoxel0px1py1pz(void) const;
|
||||
|
||||
inline VoxelType peekVoxel1px1ny1nz(void) const;
|
||||
inline VoxelType peekVoxel1px1ny0pz(void) const;
|
||||
inline VoxelType peekVoxel1px1ny1pz(void) const;
|
||||
inline VoxelType peekVoxel1px0py1nz(void) const;
|
||||
inline VoxelType peekVoxel1px0py0pz(void) const;
|
||||
inline VoxelType peekVoxel1px0py1pz(void) const;
|
||||
inline VoxelType peekVoxel1px1py1nz(void) const;
|
||||
inline VoxelType peekVoxel1px1py0pz(void) const;
|
||||
inline VoxelType peekVoxel1px1py1pz(void) const;
|
||||
|
||||
protected:
|
||||
DerivedVolumeType* mVolume;
|
||||
|
||||
//The current position in the volume
|
||||
int32_t mXPosInVolume;
|
||||
int32_t mYPosInVolume;
|
||||
int32_t mZPosInVolume;
|
||||
};
|
||||
#endif
|
||||
|
||||
public:
|
||||
/// Gets the value used for voxels which are outside the volume
|
||||
VoxelType getBorderValue(void) const;
|
||||
/// Gets a Region representing the extents of the Volume.
|
||||
Region getEnclosingRegion(void) const;
|
||||
/// Gets the width of the volume in voxels.
|
||||
int32_t getWidth(void) const;
|
||||
/// Gets the height of the volume in voxels.
|
||||
int32_t getHeight(void) const;
|
||||
/// Gets the depth of the volume in voxels.
|
||||
int32_t getDepth(void) const;
|
||||
/// Gets the length of the longest side in voxels
|
||||
int32_t getLongestSideLength(void) const;
|
||||
/// Gets the length of the shortest side in voxels
|
||||
int32_t getShortestSideLength(void) const;
|
||||
/// Gets the length of the diagonal in voxels
|
||||
float getDiagonalLength(void) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
|
||||
|
||||
/// Sets the value used for voxels which are outside the volume
|
||||
void setBorderValue(const VoxelType& tBorder);
|
||||
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue);
|
||||
/// Sets the voxel at the position given by a 3D vector
|
||||
bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue);
|
||||
|
||||
/// Calculates approximatly how many bytes of memory the volume is currently using.
|
||||
uint32_t calculateSizeInBytes(void);
|
||||
|
||||
protected:
|
||||
/// Constructor for creating a fixed size volume.
|
||||
BaseVolume(const Region& regValid);
|
||||
|
||||
/// Copy constructor
|
||||
BaseVolume(const BaseVolume& rhs);
|
||||
|
||||
/// Destructor
|
||||
~BaseVolume();
|
||||
|
||||
/// Assignment operator
|
||||
BaseVolume& operator=(const BaseVolume& rhs);
|
||||
|
||||
//The size of the volume
|
||||
Region m_regValidRegion;
|
||||
|
||||
//Some useful sizes
|
||||
int32_t m_uLongestSideLength;
|
||||
int32_t m_uShortestSideLength;
|
||||
float m_fDiagonalLength;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/BaseVolume.inl"
|
||||
#include "PolyVoxCore/BaseVolumeSampler.inl"
|
||||
|
||||
#endif //__PolyVox_BaseVolume_H__
|
224
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/BaseVolume.inl
vendored
Normal file
224
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/BaseVolume.inl
vendored
Normal file
@ -0,0 +1,224 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This is protected because you should never create a BaseVolume directly, you should instead use one of the derived classes.
|
||||
///
|
||||
/// \sa RawVolume, SimpleVolume, LargeVolume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
BaseVolume<VoxelType>::BaseVolume(const Region& regValid)
|
||||
:m_regValidRegion(regValid)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This function should never be called. Copying volumes by value would be expensive, and we want to prevent users from doing
|
||||
/// it by accident (such as when passing them as paramenters to functions). That said, there are times when you really do want to
|
||||
/// make a copy of a volume and in this case you should look at the Volumeresampler.
|
||||
///
|
||||
/// \sa VolumeResampler
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
BaseVolume<VoxelType>::BaseVolume(const BaseVolume<VoxelType>& /*rhs*/)
|
||||
{
|
||||
assert(false); // See function comment above.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Destroys the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
BaseVolume<VoxelType>::~BaseVolume()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This function should never be called. Copying volumes by value would be expensive, and we want to prevent users from doing
|
||||
/// it by accident (such as when passing them as paramenters to functions). That said, there are times when you really do want to
|
||||
/// make a copy of a volume and in this case you should look at the Volumeresampler.
|
||||
///
|
||||
/// \sa VolumeResampler
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
BaseVolume<VoxelType>& BaseVolume<VoxelType>::operator=(const BaseVolume<VoxelType>& /*rhs*/)
|
||||
{
|
||||
assert(false); // See function comment above.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// The border value is returned whenever an attempt is made to read a voxel which
|
||||
/// is outside the extents of the volume.
|
||||
/// \return The value used for voxels outside of the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType BaseVolume<VoxelType>::getBorderValue(void) const
|
||||
{
|
||||
assert(false);
|
||||
return VoxelType();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \return A Region representing the extent of the volume.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
Region BaseVolume<VoxelType>::getEnclosingRegion(void) const
|
||||
{
|
||||
return m_regValidRegion;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \return The width of the volume in voxels. Note that this value is inclusive, so that if the valid range is e.g. 0 to 63 then the width is 64.
|
||||
/// \sa getHeight(), getDepth()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
int32_t BaseVolume<VoxelType>::getWidth(void) const
|
||||
{
|
||||
return m_regValidRegion.getUpperCorner().getX() - m_regValidRegion.getLowerCorner().getX() + 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \return The height of the volume in voxels. Note that this value is inclusive, so that if the valid range is e.g. 0 to 63 then the height is 64.
|
||||
/// \sa getWidth(), getDepth()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
int32_t BaseVolume<VoxelType>::getHeight(void) const
|
||||
{
|
||||
return m_regValidRegion.getUpperCorner().getY() - m_regValidRegion.getLowerCorner().getY() + 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \return The depth of the volume in voxels. Note that this value is inclusive, so that if the valid range is e.g. 0 to 63 then the depth is 64.
|
||||
/// \sa getWidth(), getHeight()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
int32_t BaseVolume<VoxelType>::getDepth(void) const
|
||||
{
|
||||
return m_regValidRegion.getUpperCorner().getZ() - m_regValidRegion.getLowerCorner().getZ() + 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \return The length of the shortest side in voxels. For example, if a volume has
|
||||
/// dimensions 256x512x1024 this function will return 256.
|
||||
/// \sa getLongestSideLength(), getDiagonalLength()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
int32_t BaseVolume<VoxelType>::getShortestSideLength(void) const
|
||||
{
|
||||
return m_uShortestSideLength;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \return The length of the longest side in voxels. For example, if a volume has
|
||||
/// dimensions 256x512x1024 this function will return 1024.
|
||||
/// \sa getShortestSideLength(), getDiagonalLength()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
int32_t BaseVolume<VoxelType>::getLongestSideLength(void) const
|
||||
{
|
||||
return m_uLongestSideLength;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \return The length of the diagonal in voxels. For example, if a volume has
|
||||
/// dimensions 256x512x1024 this function will return sqrt(256*256+512*512+1024*1024)
|
||||
/// = 1173.139. This value is computed on volume creation so retrieving it is fast.
|
||||
/// \sa getShortestSideLength(), getLongestSideLength()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
float BaseVolume<VoxelType>::getDiagonalLength(void) const
|
||||
{
|
||||
return m_fDiagonalLength;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param uXPos The \c x position of the voxel
|
||||
/// \param uYPos The \c y position of the voxel
|
||||
/// \param uZPos The \c z position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType BaseVolume<VoxelType>::getVoxelAt(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/) const
|
||||
{
|
||||
assert(false);
|
||||
return VoxelType();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos The 3D position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType BaseVolume<VoxelType>::getVoxelAt(const Vector3DInt32& /*v3dPos*/) const
|
||||
{
|
||||
assert(false);
|
||||
return VoxelType();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param tBorder The value to use for voxels outside the volume.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void BaseVolume<VoxelType>::setBorderValue(const VoxelType& /*tBorder*/)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param uXPos the \c x position of the voxel
|
||||
/// \param uYPos the \c y position of the voxel
|
||||
/// \param uZPos the \c z position of the voxel
|
||||
/// \param tValue the value to which the voxel will be set
|
||||
/// \return whether the requested position is inside the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
bool BaseVolume<VoxelType>::setVoxelAt(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, VoxelType /*tValue*/)
|
||||
{
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos the 3D position of the voxel
|
||||
/// \param tValue the value to which the voxel will be set
|
||||
/// \return whether the requested position is inside the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
bool BaseVolume<VoxelType>::setVoxelAt(const Vector3DInt32& /*v3dPos*/, VoxelType /*tValue*/)
|
||||
{
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Note: This function needs reviewing for accuracy...
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
uint32_t BaseVolume<VoxelType>::calculateSizeInBytes(void)
|
||||
{
|
||||
return getWidth() * getHeight() * getDepth() * sizeof(VoxelType);
|
||||
}
|
||||
}
|
||||
|
315
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/BaseVolumeSampler.inl
vendored
Normal file
315
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/BaseVolumeSampler.inl
vendored
Normal file
@ -0,0 +1,315 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::Sampler(DerivedVolumeType* volume)
|
||||
:mVolume(volume)
|
||||
,mXPosInVolume(0)
|
||||
,mYPosInVolume(0)
|
||||
,mZPosInVolume(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::~Sampler()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
Vector3DInt32 BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::getPosition(void) const
|
||||
{
|
||||
return Vector3DInt32(mXPosInVolume, mYPosInVolume, mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::getVoxel(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume, mYPosInVolume, mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::setPosition(const Vector3DInt32& v3dNewPos)
|
||||
{
|
||||
mXPosInVolume = v3dNewPos.getX();
|
||||
mYPosInVolume = v3dNewPos.getY();
|
||||
mZPosInVolume = v3dNewPos.getZ();
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::setPosition(int32_t xPos, int32_t yPos, int32_t zPos)
|
||||
{
|
||||
mXPosInVolume = xPos;
|
||||
mYPosInVolume = yPos;
|
||||
mZPosInVolume = zPos;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
bool BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::setVoxel(VoxelType tValue)
|
||||
{
|
||||
return mVolume->setVoxelAt(mXPosInVolume, mYPosInVolume, mZPosInVolume, tValue);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::movePositiveX(void)
|
||||
{
|
||||
mXPosInVolume++;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::movePositiveY(void)
|
||||
{
|
||||
mYPosInVolume++;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::movePositiveZ(void)
|
||||
{
|
||||
mZPosInVolume++;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::moveNegativeX(void)
|
||||
{
|
||||
mXPosInVolume--;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::moveNegativeY(void)
|
||||
{
|
||||
mYPosInVolume--;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::moveNegativeZ(void)
|
||||
{
|
||||
mZPosInVolume--;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1ny1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1ny0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1ny1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx0py1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx0py0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx0py1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1py1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1py0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1py1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1ny1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1ny0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1ny1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px0py1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume , mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px0py0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume , mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px0py1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume , mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1py1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1py0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1py1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1ny1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1ny0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1ny1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px0py1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px0py0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px0py1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume + 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1py1nz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume - 1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1py0pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume );
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
template <typename DerivedVolumeType>
|
||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1py1pz(void) const
|
||||
{
|
||||
return mVolume->getVoxelAt(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume + 1);
|
||||
}
|
||||
}
|
79
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/ConstVolumeProxy.h
vendored
Normal file
79
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/ConstVolumeProxy.h
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
/*******************************************************************************
|
||||
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_ConstVolumeProxy_H__
|
||||
#define __PolyVox_ConstVolumeProxy_H__
|
||||
|
||||
#include "PolyVoxCore/Region.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
class ConstVolumeProxy
|
||||
{
|
||||
//LargeVolume is a friend so it can call the constructor.
|
||||
friend class LargeVolume<VoxelType>;
|
||||
public:
|
||||
VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
|
||||
{
|
||||
assert(m_regValid.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
|
||||
return m_pVolume.getVoxelAt(uXPos, uYPos, uZPos);
|
||||
}
|
||||
|
||||
VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const
|
||||
{
|
||||
assert(m_regValid.containsPoint(v3dPos));
|
||||
return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
void setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const
|
||||
{
|
||||
assert(m_regValid.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
|
||||
m_pVolume.setVoxelAtConst(uXPos, uYPos, uZPos, tValue);
|
||||
}
|
||||
|
||||
void setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue) const
|
||||
{
|
||||
assert(m_regValid.containsPoint(v3dPos));
|
||||
setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
|
||||
}
|
||||
private:
|
||||
//Private constructor, so client code can't abuse this class.
|
||||
ConstVolumeProxy(const LargeVolume<VoxelType>& pVolume, const Region& regValid)
|
||||
:m_pVolume(pVolume)
|
||||
,m_regValid(regValid)
|
||||
{
|
||||
}
|
||||
|
||||
//Private assignment operator, so client code can't abuse this class.
|
||||
ConstVolumeProxy& operator=(const ConstVolumeProxy& rhs)
|
||||
{
|
||||
}
|
||||
|
||||
const LargeVolume<VoxelType>& m_pVolume;
|
||||
const Region& m_regValid;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //__PolyVox_ConstVolumeProxy_H__
|
151
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h
vendored
Normal file
151
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
/*******************************************************************************
|
||||
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_CubicSurfaceExtractor_H__
|
||||
#define __PolyVox_CubicSurfaceExtractor_H__
|
||||
|
||||
#include "Impl/TypeDef.h"
|
||||
|
||||
#include "PolyVoxCore/Array.h"
|
||||
#include "PolyVoxCore/DefaultIsQuadNeeded.h"
|
||||
#include "PolyVoxCore/SurfaceMesh.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/// The CubicSurfaceExtractor creates a mesh in which each voxel appears to be rendered as a cube
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Introduction
|
||||
/// ------------
|
||||
/// Games such as Minecraft and Voxatron have a unique graphical style in which each voxel in the world appears to be rendered as a single cube. Actually rendering a cube for each voxel would be very expensive, but in practice the only faces which need to be drawn are those which lie on the boundary between solid and empty voxels. The CubicSurfaceExtractor can be used to create such a mesh from PolyVox volume data. As an example, images from Minecraft and Voxatron are shown below:
|
||||
///
|
||||
/// \image html MinecraftAndVoxatron.jpg
|
||||
///
|
||||
/// Before we get into the specifics of the CubicSurfaceExtractor, it is useful to understand the principles which apply to *all* PolyVox surface extractors and which are described in the Surface Extraction document (ADD LINK). From here on, it is assumed that you are familier with PolyVox regions and how they are used to limit surface extraction to a particular part of the volume. The principles of allowing dynamic terrain are also common to all surface extractors and are described here (ADD LINK).
|
||||
///
|
||||
/// Basic Operation
|
||||
/// ---------------
|
||||
/// At its core, the CubicSurfaceExtractor works by by looking at pairs of adjacent voxels and determining whether a quad should be placed between then. The most simple situation to imagine is a binary volume where every voxel is either solid or empty. In this case a quad should be generated whenever a solid voxel is next to an empty voxel as this represents part of the surface of the solid object. There is no need to generate a quad between two solid voxels (this quad would never be seen as it is inside the object) and there is no need to generate a quad between two empty voxels (there is no object here). PolyVox allows the principle to be extended far beyond such simple binary volumes but they provide a useful starting point for understanding how the algorithm works.
|
||||
///
|
||||
/// As an example, lets consider the part of a volume shown below. We are going to explain the principles in only two dimensions as this makes it much simpler to illustrate, so you will need to mentally extend the process into the third dimension. Hopefully you will find this intuitive. The diagram below shows a small part of a larger volume (as indicated by the voxel coordinates on the axes) which contains only solid and empty voxels represented by solid and hollow circles respectively. The region on which we are running the surface extractor is marked in pink, and for the purpose of this example it corresponds to the whole of the diagram.
|
||||
///
|
||||
/// \image html CubicSurfaceExtractor1.png
|
||||
///
|
||||
/// The output of the surface extractor is the mesh marked in red. As you can see, this forms a closed object which corrsponds to the shape of the underlying voxel data. We won't describe the rendering of such meshes here - for details of this please see (SOME LINK HERE).
|
||||
///
|
||||
/// Working with Regions
|
||||
/// --------------------
|
||||
/// So far the behaviour is easy to understand, but let's look at what happens when the extraction is limited to a particular region of the volume. The figure below shows the same data set as the previous figure, but the extraction region (still marked in pink) has been limited to 13 to 16 in x and 47 to 51 in y:
|
||||
///
|
||||
/// \image html CubicSurfaceExtractor2.png
|
||||
///
|
||||
/// As you can see, the extractor continues to generate a number of quads as indicated by the solid red lines. However, you can also see that the shape is no longer closed. This is because the solid voxels actually extend outside the region which is being processed, and so the extractor does not encounter a boundary between solid and empty voxels. Although this may initially appear problematic, the hole in the mesh does not actually matter because it will be hidden by the mesh corresponding to the region adjacent to it (see next diagram).
|
||||
///
|
||||
/// More interestingly, the diagram also contains a couple of dotted red lines lying on the bottom and right hand side of the extracted region. These are present to illustrate a common point of confusion, which is that *no quads are generated at this position even though it is a boundary between solid and empty voxels*. This is indeed somewhat counter intuitive but there is a rational reasaoning behind it.
|
||||
/// If you consider the dashed line on the righthand side of the extracted region, then it is clear that this lies on a boundary between solid and empty voxels and so we do need to create quads here. But what is not so clear is whether these quads should be assigned to the mesh which corresponds to the region in pink, or whether they should be assigned to the region to the right of it which is marked in blue in the diagram below:
|
||||
///
|
||||
/// \image html CubicSurfaceExtractor3.png
|
||||
///
|
||||
/// We could choose to add the quads to *both* regions, but this can cause confusion when one of the region is modified (causing the face to disappear or a new one to be created) as *both* regions need to have their mesh regenerated to correctly represent the new state of the volume data. Such pairs of coplanar quads can also cause problems with physics engines, and may prevent transparent block from rendering correctly. Therefore we choose to instead only add the quad to one of the the regions and we always choose the one with the greater coordinate value in the direction in which they differ. In the above example the regions differ by the 'x' component of their position, and so the quad is added to the region with the greater 'x' value (the one marked in blue).
|
||||
///
|
||||
/// **Note:** *This behaviour has changed recently (September 2012). Earlier versions of PolyVox tried to be smart about this problem by looking beyond the region which was being processed, but this complicated the code and didn't work very well. Ultimatly we decided to simply stick with the convention outlined above.*
|
||||
///
|
||||
/// One of the practical implications of this is that when you modify a voxel *you may have to re-extract the mesh for regions other than region which actually contains the voxel you modified.* This happens when the voxel lies on the upper x,y or z face of a region. Assuming that you have some management code which can mark a region as needing re-extraction when a voxel changes, you should probably extend this to mark the regions of neighbouring voxels as invalid (this will have no effect when the voxel is well within a region, but will mark the neighbouring region as needing an update if the voxel lies on a region face).
|
||||
///
|
||||
/// Another scenario which sometimes results in confusion is when you wish to extract a region which corresponds to the whole volume, partcularly when solid voxels extend right to the edge of the volume.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<typename VolumeType, typename IsQuadNeeded = DefaultIsQuadNeeded<typename VolumeType::VoxelType> >
|
||||
class CubicSurfaceExtractor
|
||||
{
|
||||
struct IndexAndMaterial
|
||||
{
|
||||
int32_t iIndex;
|
||||
int32_t uMaterial; //Should actually use the material type here, but this is ok for now.
|
||||
};
|
||||
|
||||
enum FaceNames
|
||||
{
|
||||
PositiveX,
|
||||
PositiveY,
|
||||
PositiveZ,
|
||||
NegativeX,
|
||||
NegativeY,
|
||||
NegativeZ,
|
||||
NoOfFaces
|
||||
};
|
||||
|
||||
struct Quad
|
||||
{
|
||||
Quad(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3)
|
||||
{
|
||||
vertices[0] = v0;
|
||||
vertices[1] = v1;
|
||||
vertices[2] = v2;
|
||||
vertices[3] = v3;
|
||||
}
|
||||
|
||||
uint32_t vertices[4];
|
||||
};
|
||||
|
||||
public:
|
||||
CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterial>* result, bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded());
|
||||
|
||||
|
||||
void execute();
|
||||
|
||||
private:
|
||||
int32_t addVertex(float fX, float fY, float fZ, uint32_t uMaterial, Array<3, IndexAndMaterial>& existingVertices);
|
||||
bool performQuadMerging(std::list<Quad>& quads);
|
||||
bool mergeQuads(Quad& q1, Quad& q2);
|
||||
|
||||
IsQuadNeeded m_funcIsQuadNeededCallback;
|
||||
|
||||
//The volume data and a sampler to access it.
|
||||
VolumeType* m_volData;
|
||||
|
||||
//Information about the region we are currently processing
|
||||
Region m_regSizeInVoxels;
|
||||
|
||||
//The surface patch we are currently filling.
|
||||
SurfaceMesh<PositionMaterial>* m_meshCurrent;
|
||||
|
||||
//Used to avoid creating duplicate vertices.
|
||||
Array<3, IndexAndMaterial> m_previousSliceVertices;
|
||||
Array<3, IndexAndMaterial> m_currentSliceVertices;
|
||||
|
||||
//During extraction we create a number of different lists of quads. All the
|
||||
//quads in a given list are in the same plane and facing in the same direction.
|
||||
std::vector< std::list<Quad> > m_vecQuads[NoOfFaces];
|
||||
|
||||
//Controls whether quad merging should be performed. This might be undesirable
|
||||
//is the user needs per-vertex attributes, or to perform per vertex lighting.
|
||||
bool m_bMergeQuads;
|
||||
|
||||
//This constant defines the maximum number of quads which can share a
|
||||
//vertex in a cubic style mesh. See the initialisation for more details.
|
||||
static const uint32_t MaxVerticesPerPosition;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/CubicSurfaceExtractor.inl"
|
||||
|
||||
#endif
|
297
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl
vendored
Normal file
297
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl
vendored
Normal file
@ -0,0 +1,297 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
// We try to avoid duplicate vertices by checking whether a vertex has already been added at a given position.
|
||||
// However, it is possible that vertices have the same position but different materials. In this case, the
|
||||
// vertices are not true duplicates and both must be added to the mesh. As far as I can tell, it is possible to have
|
||||
// at most six vertices with the same position but different materials. This worst-case scenario happens when we
|
||||
// have a 2x2x2 group of voxels (all with different materials) and then we delete two voxels from opposing corners.
|
||||
// The vertex position at the center of this group is then going to be used by six quads all with different materials.
|
||||
// One futher note - we can actually have eight quads sharing a vertex position (imagine two 1x1x10 rows of voxels
|
||||
// sharing a common edge) but in this case all eight quads will not have different materials.
|
||||
template<typename VolumeType, typename IsQuadNeeded>
|
||||
const uint32_t CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::MaxVerticesPerPosition = 6;
|
||||
|
||||
template<typename VolumeType, typename IsQuadNeeded>
|
||||
CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterial>* result, bool bMergeQuads, IsQuadNeeded isQuadNeeded)
|
||||
:m_volData(volData)
|
||||
,m_regSizeInVoxels(region)
|
||||
,m_meshCurrent(result)
|
||||
,m_bMergeQuads(bMergeQuads)
|
||||
{
|
||||
m_funcIsQuadNeededCallback = isQuadNeeded;
|
||||
}
|
||||
|
||||
template<typename VolumeType, typename IsQuadNeeded>
|
||||
void CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::execute()
|
||||
{
|
||||
m_meshCurrent->clear();
|
||||
|
||||
uint32_t uArrayWidth = m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 2;
|
||||
uint32_t uArrayHeight = m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 2;
|
||||
|
||||
uint32_t arraySize[3]= {uArrayWidth, uArrayHeight, MaxVerticesPerPosition};
|
||||
m_previousSliceVertices.resize(arraySize);
|
||||
m_currentSliceVertices.resize(arraySize);
|
||||
memset(m_previousSliceVertices.getRawData(), 0xff, m_previousSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
||||
memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
||||
|
||||
m_vecQuads[NegativeX].resize(m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 2);
|
||||
m_vecQuads[PositiveX].resize(m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 2);
|
||||
|
||||
m_vecQuads[NegativeY].resize(m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 2);
|
||||
m_vecQuads[PositiveY].resize(m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 2);
|
||||
|
||||
m_vecQuads[NegativeZ].resize(m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ() + 2);
|
||||
m_vecQuads[PositiveZ].resize(m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ() + 2);
|
||||
|
||||
typename VolumeType::Sampler volumeSampler(m_volData);
|
||||
|
||||
for(int32_t z = m_regSizeInVoxels.getLowerCorner().getZ(); z <= m_regSizeInVoxels.getUpperCorner().getZ(); z++)
|
||||
{
|
||||
uint32_t regZ = z - m_regSizeInVoxels.getLowerCorner().getZ();
|
||||
|
||||
for(int32_t y = m_regSizeInVoxels.getLowerCorner().getY(); y <= m_regSizeInVoxels.getUpperCorner().getY(); y++)
|
||||
{
|
||||
uint32_t regY = y - m_regSizeInVoxels.getLowerCorner().getY();
|
||||
|
||||
for(int32_t x = m_regSizeInVoxels.getLowerCorner().getX(); x <= m_regSizeInVoxels.getUpperCorner().getX(); x++)
|
||||
{
|
||||
uint32_t regX = x - m_regSizeInVoxels.getLowerCorner().getX();
|
||||
|
||||
volumeSampler.setPosition(x,y,z);
|
||||
|
||||
uint32_t material; //Filled in by callback
|
||||
typename VolumeType::VoxelType currentVoxel = volumeSampler.getVoxel();
|
||||
typename VolumeType::VoxelType negXVoxel = volumeSampler.peekVoxel1nx0py0pz();
|
||||
typename VolumeType::VoxelType negYVoxel = volumeSampler.peekVoxel0px1ny0pz();
|
||||
typename VolumeType::VoxelType negZVoxel = volumeSampler.peekVoxel0px0py1nz();
|
||||
|
||||
// X
|
||||
if(m_funcIsQuadNeededCallback(currentVoxel, negXVoxel, material))
|
||||
{
|
||||
uint32_t v0 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
uint32_t v1 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices);
|
||||
uint32_t v2 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices);
|
||||
uint32_t v3 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
|
||||
m_vecQuads[NegativeX][regX].push_back(Quad(v0, v1, v2, v3));
|
||||
}
|
||||
|
||||
if(m_funcIsQuadNeededCallback(negXVoxel, currentVoxel, material))
|
||||
{
|
||||
uint32_t v0 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
uint32_t v1 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices);
|
||||
uint32_t v2 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices);
|
||||
uint32_t v3 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
|
||||
m_vecQuads[PositiveX][regX].push_back(Quad(v0, v3, v2, v1));
|
||||
}
|
||||
|
||||
// Y
|
||||
if(m_funcIsQuadNeededCallback(currentVoxel, negYVoxel, material))
|
||||
{
|
||||
uint32_t v0 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
uint32_t v1 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
uint32_t v2 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices);
|
||||
uint32_t v3 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices);
|
||||
|
||||
m_vecQuads[NegativeY][regY].push_back(Quad(v0, v1, v2, v3));
|
||||
}
|
||||
|
||||
if(m_funcIsQuadNeededCallback(negYVoxel, currentVoxel, material))
|
||||
{
|
||||
uint32_t v0 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
uint32_t v1 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
uint32_t v2 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices);
|
||||
uint32_t v3 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices);
|
||||
|
||||
m_vecQuads[PositiveY][regY].push_back(Quad(v0, v3, v2, v1));
|
||||
}
|
||||
|
||||
// Z
|
||||
if(m_funcIsQuadNeededCallback(currentVoxel, negZVoxel, material))
|
||||
{
|
||||
uint32_t v0 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
uint32_t v1 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
uint32_t v2 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
uint32_t v3 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
|
||||
m_vecQuads[NegativeZ][regZ].push_back(Quad(v0, v1, v2, v3));
|
||||
}
|
||||
|
||||
if(m_funcIsQuadNeededCallback(negZVoxel, currentVoxel, material))
|
||||
{
|
||||
uint32_t v0 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
uint32_t v1 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
uint32_t v2 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
uint32_t v3 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices);
|
||||
|
||||
m_vecQuads[PositiveZ][regZ].push_back(Quad(v0, v3, v2, v1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_previousSliceVertices.swap(m_currentSliceVertices);
|
||||
memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
||||
}
|
||||
|
||||
for(uint32_t uFace = 0; uFace < NoOfFaces; uFace++)
|
||||
{
|
||||
std::vector< std::list<Quad> >& vecListQuads = m_vecQuads[uFace];
|
||||
|
||||
for(uint32_t slice = 0; slice < vecListQuads.size(); slice++)
|
||||
{
|
||||
std::list<Quad>& listQuads = vecListQuads[slice];
|
||||
|
||||
if(m_bMergeQuads)
|
||||
{
|
||||
//Repeatedly call this function until it returns
|
||||
//false to indicate nothing more can be done.
|
||||
while(performQuadMerging(listQuads)){}
|
||||
}
|
||||
|
||||
typename std::list<Quad>::iterator iterEnd = listQuads.end();
|
||||
for(typename std::list<Quad>::iterator quadIter = listQuads.begin(); quadIter != iterEnd; quadIter++)
|
||||
{
|
||||
Quad& quad = *quadIter;
|
||||
m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[1],quad.vertices[2]);
|
||||
m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[2],quad.vertices[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_meshCurrent->m_Region = m_regSizeInVoxels;
|
||||
m_meshCurrent->removeUnusedVertices();
|
||||
|
||||
m_meshCurrent->m_vecLodRecords.clear();
|
||||
LodRecord lodRecord;
|
||||
lodRecord.beginIndex = 0;
|
||||
lodRecord.endIndex = m_meshCurrent->getNoOfIndices();
|
||||
m_meshCurrent->m_vecLodRecords.push_back(lodRecord);
|
||||
}
|
||||
|
||||
template<typename VolumeType, typename IsQuadNeeded>
|
||||
int32_t CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::addVertex(float fX, float fY, float fZ, uint32_t uMaterialIn, Array<3, IndexAndMaterial>& existingVertices)
|
||||
{
|
||||
uint32_t uX = static_cast<uint32_t>(fX + 0.75f);
|
||||
uint32_t uY = static_cast<uint32_t>(fY + 0.75f);
|
||||
|
||||
for(uint32_t ct = 0; ct < MaxVerticesPerPosition; ct++)
|
||||
{
|
||||
IndexAndMaterial& rEntry = existingVertices[uX][uY][ct];
|
||||
|
||||
if(rEntry.iIndex == -1)
|
||||
{
|
||||
//No vertices matched and we've now hit an empty space. Fill it by creating a vertex.
|
||||
rEntry.iIndex = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(fX, fY, fZ), uMaterialIn));
|
||||
rEntry.uMaterial = uMaterialIn;
|
||||
|
||||
return rEntry.iIndex;
|
||||
}
|
||||
|
||||
//If we have an existing vertex and the material matches then we can return it.
|
||||
if(rEntry.uMaterial == static_cast<int32_t>(uMaterialIn))
|
||||
{
|
||||
return rEntry.iIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// If we exit the loop here then apparently all the slots were full but none of them matched. I don't think
|
||||
// this can happen so let's put an assert to make sure. If you hit this assert then please report it to us!
|
||||
assert(false);
|
||||
return -1; //Should never happen.
|
||||
}
|
||||
|
||||
template<typename VolumeType, typename IsQuadNeeded>
|
||||
bool CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::performQuadMerging(std::list<Quad>& quads)
|
||||
{
|
||||
bool bDidMerge = false;
|
||||
for(typename std::list<Quad>::iterator outerIter = quads.begin(); outerIter != quads.end(); outerIter++)
|
||||
{
|
||||
typename std::list<Quad>::iterator innerIter = outerIter;
|
||||
innerIter++;
|
||||
while(innerIter != quads.end())
|
||||
{
|
||||
Quad& q1 = *outerIter;
|
||||
Quad& q2 = *innerIter;
|
||||
|
||||
bool result = mergeQuads(q1,q2);
|
||||
|
||||
if(result)
|
||||
{
|
||||
bDidMerge = true;
|
||||
innerIter = quads.erase(innerIter);
|
||||
}
|
||||
else
|
||||
{
|
||||
innerIter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bDidMerge;
|
||||
}
|
||||
|
||||
template<typename VolumeType, typename IsQuadNeeded>
|
||||
bool CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::mergeQuads(Quad& q1, Quad& q2)
|
||||
{
|
||||
//All four vertices of a given quad have the same material,
|
||||
//so just check that the first pair of vertices match.
|
||||
if(std::abs(m_meshCurrent->getVertices()[q1.vertices[0]].getMaterial() - m_meshCurrent->getVertices()[q2.vertices[0]].getMaterial()) < 0.001)
|
||||
{
|
||||
//Now check whether quad 2 is adjacent to quad one by comparing vertices.
|
||||
//Adjacent quads must share two vertices, and the second quad could be to the
|
||||
//top, bottom, left, of right of the first one. This gives four combinations to test.
|
||||
if((q1.vertices[0] == q2.vertices[1]) && ((q1.vertices[3] == q2.vertices[2])))
|
||||
{
|
||||
q1.vertices[0] = q2.vertices[0];
|
||||
q1.vertices[3] = q2.vertices[3];
|
||||
return true;
|
||||
}
|
||||
else if((q1.vertices[3] == q2.vertices[0]) && ((q1.vertices[2] == q2.vertices[1])))
|
||||
{
|
||||
q1.vertices[3] = q2.vertices[3];
|
||||
q1.vertices[2] = q2.vertices[2];
|
||||
return true;
|
||||
}
|
||||
else if((q1.vertices[1] == q2.vertices[0]) && ((q1.vertices[2] == q2.vertices[3])))
|
||||
{
|
||||
q1.vertices[1] = q2.vertices[1];
|
||||
q1.vertices[2] = q2.vertices[2];
|
||||
return true;
|
||||
}
|
||||
else if((q1.vertices[0] == q2.vertices[3]) && ((q1.vertices[1] == q2.vertices[2])))
|
||||
{
|
||||
q1.vertices[0] = q2.vertices[0];
|
||||
q1.vertices[1] = q2.vertices[1];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//Quads cannot be merged.
|
||||
return false;
|
||||
}
|
||||
}
|
59
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractorWithNormals.h
vendored
Normal file
59
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractorWithNormals.h
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
/*******************************************************************************
|
||||
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_CubicSurfaceExtractorWithNormals_H__
|
||||
#define __PolyVox_CubicSurfaceExtractorWithNormals_H__
|
||||
|
||||
#include "PolyVoxCore/DefaultIsQuadNeeded.h"
|
||||
|
||||
#include "PolyVoxCore/Array.h"
|
||||
#include "PolyVoxCore/SurfaceMesh.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template<typename VolumeType, typename IsQuadNeeded = DefaultIsQuadNeeded<typename VolumeType::VoxelType> >
|
||||
class CubicSurfaceExtractorWithNormals
|
||||
{
|
||||
public:
|
||||
CubicSurfaceExtractorWithNormals(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded());
|
||||
|
||||
void execute();
|
||||
|
||||
private:
|
||||
IsQuadNeeded m_funcIsQuadNeededCallback;
|
||||
|
||||
//The volume data and a sampler to access it.
|
||||
VolumeType* m_volData;
|
||||
typename VolumeType::Sampler m_sampVolume;
|
||||
|
||||
//The surface patch we are currently filling.
|
||||
SurfaceMesh<PositionMaterialNormal>* m_meshCurrent;
|
||||
|
||||
//Information about the region we are currently processing
|
||||
Region m_regSizeInVoxels;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.inl"
|
||||
|
||||
#endif
|
128
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractorWithNormals.inl
vendored
Normal file
128
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractorWithNormals.inl
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template<typename VolumeType, typename IsQuadNeeded>
|
||||
CubicSurfaceExtractorWithNormals<VolumeType, IsQuadNeeded>::CubicSurfaceExtractorWithNormals(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result, IsQuadNeeded isQuadNeeded)
|
||||
:m_volData(volData)
|
||||
,m_sampVolume(volData)
|
||||
,m_meshCurrent(result)
|
||||
,m_regSizeInVoxels(region)
|
||||
{
|
||||
m_funcIsQuadNeededCallback = isQuadNeeded;
|
||||
}
|
||||
|
||||
template<typename VolumeType, typename IsQuadNeeded>
|
||||
void CubicSurfaceExtractorWithNormals<VolumeType, IsQuadNeeded>::execute()
|
||||
{
|
||||
m_meshCurrent->clear();
|
||||
|
||||
for(int32_t z = m_regSizeInVoxels.getLowerCorner().getZ(); z < m_regSizeInVoxels.getUpperCorner().getZ(); z++)
|
||||
{
|
||||
for(int32_t y = m_regSizeInVoxels.getLowerCorner().getY(); y < m_regSizeInVoxels.getUpperCorner().getY(); y++)
|
||||
{
|
||||
for(int32_t x = m_regSizeInVoxels.getLowerCorner().getX(); x < m_regSizeInVoxels.getUpperCorner().getX(); x++)
|
||||
{
|
||||
// these are always positive anyway
|
||||
float regX = static_cast<float>(x - m_regSizeInVoxels.getLowerCorner().getX());
|
||||
float regY = static_cast<float>(y - m_regSizeInVoxels.getLowerCorner().getY());
|
||||
float regZ = static_cast<float>(z - m_regSizeInVoxels.getLowerCorner().getZ());
|
||||
|
||||
uint32_t material = 0;
|
||||
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelAt(x,y,z), m_volData->getVoxelAt(x+1,y,z), material))
|
||||
{
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ - 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), static_cast<float>(material)));
|
||||
|
||||
m_meshCurrent->addTriangleCubic(v0,v2,v1);
|
||||
m_meshCurrent->addTriangleCubic(v1,v2,v3);
|
||||
}
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelAt(x+1,y,z), m_volData->getVoxelAt(x,y,z), material))
|
||||
{
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ - 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), static_cast<float>(material)));
|
||||
|
||||
m_meshCurrent->addTriangleCubic(v0,v1,v2);
|
||||
m_meshCurrent->addTriangleCubic(v1,v3,v2);
|
||||
}
|
||||
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelAt(x,y,z), m_volData->getVoxelAt(x,y+1,z), material))
|
||||
{
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), static_cast<float>(material)));
|
||||
|
||||
m_meshCurrent->addTriangleCubic(v0,v1,v2);
|
||||
m_meshCurrent->addTriangleCubic(v1,v3,v2);
|
||||
}
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelAt(x,y+1,z), m_volData->getVoxelAt(x,y,z), material))
|
||||
{
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), static_cast<float>(material)));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), static_cast<float>(material)));
|
||||
|
||||
m_meshCurrent->addTriangleCubic(v0,v2,v1);
|
||||
m_meshCurrent->addTriangleCubic(v1,v2,v3);
|
||||
}
|
||||
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelAt(x,y,z), m_volData->getVoxelAt(x,y,z+1), material))
|
||||
{
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), static_cast<float>(material)));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), static_cast<float>(material)));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), static_cast<float>(material)));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), static_cast<float>(material)));
|
||||
|
||||
m_meshCurrent->addTriangleCubic(v0,v2,v1);
|
||||
m_meshCurrent->addTriangleCubic(v1,v2,v3);
|
||||
}
|
||||
if(m_funcIsQuadNeededCallback(m_volData->getVoxelAt(x,y,z+1), m_volData->getVoxelAt(x,y,z), material))
|
||||
{
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), static_cast<float>(material)));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), static_cast<float>(material)));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), static_cast<float>(material)));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), static_cast<float>(material)));
|
||||
|
||||
m_meshCurrent->addTriangleCubic(v0,v1,v2);
|
||||
m_meshCurrent->addTriangleCubic(v1,v3,v2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_meshCurrent->m_Region = m_regSizeInVoxels;
|
||||
|
||||
m_meshCurrent->m_vecLodRecords.clear();
|
||||
LodRecord lodRecord;
|
||||
lodRecord.beginIndex = 0;
|
||||
lodRecord.endIndex = m_meshCurrent->getNoOfIndices();
|
||||
m_meshCurrent->m_vecLodRecords.push_back(lodRecord);
|
||||
}
|
||||
}
|
50
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/DefaultIsQuadNeeded.h
vendored
Normal file
50
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/DefaultIsQuadNeeded.h
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
/*******************************************************************************
|
||||
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_DefaultIsQuadNeeded_H__
|
||||
#define __PolyVox_DefaultIsQuadNeeded_H__
|
||||
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template<typename VoxelType>
|
||||
class DefaultIsQuadNeeded
|
||||
{
|
||||
public:
|
||||
bool operator()(VoxelType back, VoxelType front, uint32_t& materialToUse)
|
||||
{
|
||||
if((back > 0) && (front == 0))
|
||||
{
|
||||
materialToUse = static_cast<uint32_t>(back);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif //__PolyVox_DefaultIsQuadNeeded_H__
|
132
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/DefaultMarchingCubesController.h
vendored
Normal file
132
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/DefaultMarchingCubesController.h
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
/*******************************************************************************
|
||||
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_MarchingCubesController_H__
|
||||
#define __PolyVox_MarchingCubesController_H__
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// This class provides a default implementation of a controller for the MarchingCubesSurfaceExtractor. It controls the behaviour of the
|
||||
/// MarchingCubesSurfaceExtractor and provides the required properties from the underlying voxel type.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// PolyVox does not enforce any requirements regarding what data must be present in a voxel, and instead allows any primitive or user-defined
|
||||
/// type to be used. However, the Marching Cubes algorithm does have some requirents about the underlying data in that conceptually it operates
|
||||
/// on a <i>density field</i>. In addition, the PolyVox implementation of the Marching Cubes algorithm also understands the idea of each voxel
|
||||
/// having a material which is copied into the vertex data.
|
||||
///
|
||||
/// Because we want the MarchingCubesSurfaceExtractor to work on <i>any</i> voxel type, we use a <i>Marching Cubes controller</i> (passed as
|
||||
/// a parameter of the MarchingCubesSurfaceExtractor) to expose the required properties. This parameter defaults to the DefaultMarchingCubesController.
|
||||
/// The main implementation of this class is designed to work with primitives data types, and the class is also specialised for the Material,
|
||||
/// Density and MaterialdensityPair classes.
|
||||
///
|
||||
/// If you create a custom class for your voxel data then you probably want to include a specialisation of DefaultMarchingCubesController,
|
||||
/// though you don't have to if you don't want to use the Marching Cubes algorithm or if you prefer to define a seperate Marching Cubes controller
|
||||
/// and pass it as an explicit parameter (rather than relying on the default).
|
||||
///
|
||||
/// For primitive types, the DefaultMarchingCubesController considers the value of the voxel to represent it's density and just returns a constant
|
||||
/// for the material. So you can, for example, run the MarchingCubesSurfaceExtractor on a volume of floats or ints.
|
||||
///
|
||||
/// It is possible to customise the behaviour of the controller by providing a threshold value through the constructor. The extracted surface
|
||||
/// will pass through the density value specified by the threshold, and so you should make sure that the threshold value you choose is between
|
||||
/// the minimum and maximum values found in your volume data. By default it is in the middle of the representable range of the underlying type.
|
||||
///
|
||||
/// \sa MarchingCubesSurfaceExtractor
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<typename VoxelType>
|
||||
class DefaultMarchingCubesController
|
||||
{
|
||||
public:
|
||||
/// Used to inform the MarchingCubesSurfaceExtractor about which type it should use for representing densities.
|
||||
typedef VoxelType DensityType;
|
||||
/// Used to inform the MarchingCubesSurfaceExtractor about which type it should use for representing materials. We're using a float here
|
||||
/// because this implementation always returns a constant value off 1.0f. PolyVox also uses floats to store the materials in the mesh vertices
|
||||
/// but this is not really desirable on modern hardware. We'll probably come back to material representation in the future.
|
||||
typedef float MaterialType;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructor
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// This version of the constructor takes no parameters and sets the threshold to the middle of the representable range of the underlying type.
|
||||
/// For example, if the voxel type is 'uint8_t' then the representable range is 0-255, and the threshold will be set to 127. On the other hand,
|
||||
/// if the voxel type is 'float' then the representable range is -FLT_MAX to FLT_MAX and the threshold will be set to zero.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
DefaultMarchingCubesController(void)
|
||||
{
|
||||
m_tThreshold = ((std::numeric_limits<DensityType>::min)() + (std::numeric_limits<DensityType>::max)()) / 2;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructor
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// This version of the constructor allows you to set a custom threshold.
|
||||
/// \param tThreshold The threshold to use.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
DefaultMarchingCubesController(DensityType tThreshold)
|
||||
{
|
||||
m_tThreshold = tThreshold;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Converts the underlying voxel type into a density value.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// The default implementation of this function just returns the voxel type directly and is suitable for primitives types. Specialisations of
|
||||
/// this class can modify this behaviour.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
DensityType convertToDensity(VoxelType voxel)
|
||||
{
|
||||
return voxel;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Converts the underlying voxel type into a material value.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// The default implementation of this function just returns the constant '1'. There's not much else it can do, as it needs to work with primitive
|
||||
/// types and the actual value of the type is already being considered to be the density. Specialisations of this class can modify this behaviour.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
MaterialType convertToMaterial(VoxelType /*voxel*/)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Returns the density value which was passed to the constructor.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// As mentioned in the class description, the extracted surface will pass through the density value specified by the threshold, and so you
|
||||
/// should make sure that the threshold value you choose is between the minimum and maximum values found in your volume data. By default it
|
||||
///is in the middle of the representable range of the underlying type.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
DensityType getThreshold(void)
|
||||
{
|
||||
return m_tThreshold;
|
||||
}
|
||||
|
||||
private:
|
||||
DensityType m_tThreshold;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
185
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Density.h
vendored
Normal file
185
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Density.h
vendored
Normal file
@ -0,0 +1,185 @@
|
||||
/*******************************************************************************
|
||||
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_Density_H__
|
||||
#define __PolyVox_Density_H__
|
||||
|
||||
#include "PolyVoxCore/DefaultMarchingCubesController.h" //We'll specialise the controller contained in here
|
||||
|
||||
#include "Impl/TypeDef.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/// This class represents a voxel storing only a density.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Detailed description...
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// int32_t template parameter is a dummy, required as the compiler expects to be able to declare an
|
||||
// instance of VoxelType::MaterialType without knowing that VoxelType doesn't actually have a material.
|
||||
template <typename Type>
|
||||
class Density
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
Density() : m_uDensity(0) {}
|
||||
|
||||
/// Copy constructor
|
||||
Density(Type uDensity) : m_uDensity(uDensity) {}
|
||||
|
||||
// The LowPassFilter uses this to convert between normal and accumulated types.
|
||||
/// Copy constructor with cast
|
||||
template <typename CastType> explicit Density(const Density<CastType>& density)
|
||||
{
|
||||
m_uDensity = static_cast<Type>(density.getDensity());
|
||||
}
|
||||
|
||||
bool operator==(const Density& rhs) const
|
||||
{
|
||||
return (m_uDensity == rhs.m_uDensity);
|
||||
};
|
||||
|
||||
bool operator!=(const Density& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
// For densities we can supply mathematical operators which behave in an intuitive way.
|
||||
// In particular the ability to add and subtract densities is important in order to
|
||||
// apply an averaging filter. The ability to divide by an integer is also needed for
|
||||
// this same purpose.
|
||||
Density<Type>& operator+=(const Density<Type>& rhs)
|
||||
{
|
||||
m_uDensity += rhs.m_uDensity;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Density<Type>& operator-=(const Density<Type>& rhs)
|
||||
{
|
||||
m_uDensity -= rhs.m_uDensity;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Density<Type>& operator/=(uint32_t rhs)
|
||||
{
|
||||
m_uDensity /= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \return The current density of the voxel
|
||||
Type getDensity() const { return m_uDensity; }
|
||||
/**
|
||||
* Set the density of the voxel
|
||||
*
|
||||
* \param uDensity The density to set to
|
||||
*/
|
||||
void setDensity(Type uDensity) { m_uDensity = uDensity; }
|
||||
|
||||
/// \return The maximum allowed density of the voxel
|
||||
static Type getMaxDensity() { return (std::numeric_limits<Type>::max)(); }
|
||||
/// \return The minimum allowed density of the voxel
|
||||
static Type getMinDensity() { return (std::numeric_limits<Type>::min)(); }
|
||||
|
||||
private:
|
||||
Type m_uDensity;
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
Density<Type> operator+(const Density<Type>& lhs, const Density<Type>& rhs)
|
||||
{
|
||||
Density<Type> result = lhs;
|
||||
result += rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
Density<Type> operator-(const Density<Type>& lhs, const Density<Type>& rhs)
|
||||
{
|
||||
Density<Type> result = lhs;
|
||||
result -= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
Density<Type> operator/(const Density<Type>& lhs, uint32_t rhs)
|
||||
{
|
||||
Density<Type> result = lhs;
|
||||
result /= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
// These are the predefined density types. The 8-bit types are sufficient for many purposes (including
|
||||
// most games) but 16-bit and float types do have uses particularly in medical/scientific visualisation.
|
||||
typedef Density<uint8_t> Density8;
|
||||
typedef Density<uint16_t> Density16;
|
||||
typedef Density<uint32_t> Density32;
|
||||
typedef Density<float> DensityFloat;
|
||||
|
||||
/**
|
||||
* This is a specialisation of DefaultMarchingCubesController for the Density voxel type
|
||||
*/
|
||||
template <typename Type>
|
||||
class DefaultMarchingCubesController< Density<Type> >
|
||||
{
|
||||
public:
|
||||
typedef Type DensityType;
|
||||
typedef float MaterialType;
|
||||
|
||||
DefaultMarchingCubesController(void)
|
||||
{
|
||||
// Default to a threshold value halfway between the min and max possible values.
|
||||
m_tThreshold = (Density<Type>::getMinDensity() + Density<Type>::getMaxDensity()) / 2;
|
||||
}
|
||||
|
||||
DefaultMarchingCubesController(DensityType tThreshold)
|
||||
{
|
||||
m_tThreshold = tThreshold;
|
||||
}
|
||||
|
||||
DensityType convertToDensity(Density<Type> voxel)
|
||||
{
|
||||
return voxel.getDensity();
|
||||
}
|
||||
|
||||
MaterialType convertToMaterial(Density<Type> /*voxel*/)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
DensityType getThreshold(void)
|
||||
{
|
||||
return m_tThreshold;
|
||||
}
|
||||
|
||||
private:
|
||||
DensityType m_tThreshold;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //__PolyVox_Density_H__
|
64
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/GradientEstimators.h
vendored
Normal file
64
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/GradientEstimators.h
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/*******************************************************************************
|
||||
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_GradientEstimators_H__
|
||||
#define __PolyVox_GradientEstimators_H__
|
||||
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
#include "PolyVoxCore/VoxelFilters.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
enum NormalGenerationMethod
|
||||
{
|
||||
SIMPLE, ///<Fastest
|
||||
CENTRAL_DIFFERENCE,
|
||||
SOBEL,
|
||||
CENTRAL_DIFFERENCE_SMOOTHED,
|
||||
SOBEL_SMOOTHED ///<Smoothest
|
||||
};
|
||||
|
||||
template<typename VolumeType>
|
||||
Vector3DFloat computeCentralDifferenceGradient(const typename VolumeType::Sampler& volIter);
|
||||
|
||||
template<typename VolumeType>
|
||||
Vector3DFloat computeSmoothCentralDifferenceGradient(typename VolumeType::Sampler& volIter);
|
||||
|
||||
template<typename VolumeType>
|
||||
Vector3DFloat computeDecimatedCentralDifferenceGradient(typename VolumeType::Sampler& volIter);
|
||||
|
||||
template<typename VolumeType>
|
||||
Vector3DFloat computeSobelGradient(const typename VolumeType::Sampler& volIter);
|
||||
|
||||
template<typename VolumeType>
|
||||
Vector3DFloat computeSmoothSobelGradient(typename VolumeType::Sampler& volIter);
|
||||
|
||||
//POLYVOX_API void computeNormalsForVertices(VolumeType<uint8_t>* volumeData, SurfaceMesh<PositionMaterialNormal>& mesh, NormalGenerationMethod normalGenerationMethod);
|
||||
//POLYVOX_API Vector3DFloat computeNormal(VolumeType<uint8_t>* volumeData, const Vector3DFloat& v3dPos, NormalGenerationMethod normalGenerationMethod);
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/GradientEstimators.inl"
|
||||
|
||||
#endif //__PolyVox_GradientEstimators_H__
|
302
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/GradientEstimators.inl
vendored
Normal file
302
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/GradientEstimators.inl
vendored
Normal file
@ -0,0 +1,302 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template<typename VolumeType>
|
||||
Vector3DFloat computeCentralDifferenceGradient(const typename VolumeType::Sampler& volIter)
|
||||
{
|
||||
//FIXME - bitwise way of doing this?
|
||||
typename VolumeType::VoxelType voxel1nx = volIter.peekVoxel1nx0py0pz() > 0 ? 1: 0;
|
||||
typename VolumeType::VoxelType voxel1px = volIter.peekVoxel1px0py0pz() > 0 ? 1: 0;
|
||||
|
||||
typename VolumeType::VoxelType voxel1ny = volIter.peekVoxel0px1ny0pz() > 0 ? 1: 0;
|
||||
typename VolumeType::VoxelType voxel1py = volIter.peekVoxel0px1py0pz() > 0 ? 1: 0;
|
||||
|
||||
typename VolumeType::VoxelType voxel1nz = volIter.peekVoxel0px0py1nz() > 0 ? 1: 0;
|
||||
typename VolumeType::VoxelType voxel1pz = volIter.peekVoxel0px0py1pz() > 0 ? 1: 0;
|
||||
|
||||
return Vector3DFloat
|
||||
(
|
||||
static_cast<float>(voxel1nx) - static_cast<float>(voxel1px),
|
||||
static_cast<float>(voxel1ny) - static_cast<float>(voxel1py),
|
||||
static_cast<float>(voxel1nz) - static_cast<float>(voxel1pz)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename VolumeType>
|
||||
Vector3DFloat computeDecimatedCentralDifferenceGradient(const typename VolumeType::Sampler& volIter)
|
||||
{
|
||||
const int32_t x = volIter.getPosition().getX();
|
||||
const int32_t y = volIter.getPosition().getY();
|
||||
const int32_t z = volIter.getPosition().getZ();
|
||||
|
||||
//FIXME - bitwise way of doing this?
|
||||
typename VolumeType::VoxelType voxel1nx = volIter.getVoxelAt(x-2, y ,z ) > 0 ? 1: 0;
|
||||
typename VolumeType::VoxelType voxel1px = volIter.getVoxelAt(x-2, y ,z ) > 0 ? 1: 0;
|
||||
|
||||
typename VolumeType::VoxelType voxel1ny = volIter.getVoxelAt(x , y-2,z ) > 0 ? 1: 0;
|
||||
typename VolumeType::VoxelType voxel1py = volIter.getVoxelAt(x , y-2,z ) > 0 ? 1: 0;
|
||||
|
||||
typename VolumeType::VoxelType voxel1nz = volIter.getVoxelAt(x , y ,z-2) > 0 ? 1: 0;
|
||||
typename VolumeType::VoxelType voxel1pz = volIter.getVoxelAt(x , y ,z-2) > 0 ? 1: 0;
|
||||
|
||||
return Vector3DFloat
|
||||
(
|
||||
static_cast<float>(voxel1nx) - static_cast<float>(voxel1px),
|
||||
static_cast<float>(voxel1ny) - static_cast<float>(voxel1py),
|
||||
static_cast<float>(voxel1nz) - static_cast<float>(voxel1pz)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename VolumeType>
|
||||
Vector3DFloat computeSmoothCentralDifferenceGradient(typename VolumeType::Sampler& volIter)
|
||||
{
|
||||
int32_t initialX = volIter.getPosition().getX();
|
||||
int32_t initialY = volIter.getPosition().getY();
|
||||
int32_t initialZ = volIter.getPosition().getZ();
|
||||
|
||||
//FIXME - bitwise way of doing this?
|
||||
volIter.setPosition(initialX-1, initialY, initialZ);
|
||||
float voxel1nx = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX+1, initialY, initialZ);
|
||||
float voxel1px = computeSmoothedVoxel(volIter);
|
||||
|
||||
volIter.setPosition(initialX, initialY-1, initialZ);
|
||||
float voxel1ny = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX, initialY+1, initialZ);
|
||||
float voxel1py = computeSmoothedVoxel(volIter);
|
||||
|
||||
volIter.setPosition(initialX, initialY, initialZ-1);
|
||||
float voxel1nz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX, initialY, initialZ+1);
|
||||
float voxel1pz = computeSmoothedVoxel(volIter);
|
||||
|
||||
return Vector3DFloat
|
||||
(
|
||||
voxel1nx - voxel1px,
|
||||
voxel1ny - voxel1py,
|
||||
voxel1nz - voxel1pz
|
||||
);
|
||||
}
|
||||
|
||||
template<typename VolumeType>
|
||||
Vector3DFloat computeSobelGradient(const typename VolumeType::Sampler& volIter)
|
||||
{
|
||||
static const int weights[3][3][3] = { { {2,3,2}, {3,6,3}, {2,3,2} }, {
|
||||
{3,6,3}, {6,0,6}, {3,6,3} }, { {2,3,2}, {3,6,3}, {2,3,2} } };
|
||||
|
||||
const typename VolumeType::VoxelType pVoxel1nx1ny1nz = volIter.peekVoxel1nx1ny1nz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1nx1ny0pz = volIter.peekVoxel1nx1ny0pz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1nx1ny1pz = volIter.peekVoxel1nx1ny1pz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1nx0py1nz = volIter.peekVoxel1nx0py1nz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1nx0py0pz = volIter.peekVoxel1nx0py0pz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1nx0py1pz = volIter.peekVoxel1nx0py1pz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1nx1py1nz = volIter.peekVoxel1nx1py1nz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1nx1py0pz = volIter.peekVoxel1nx1py0pz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1nx1py1pz = volIter.peekVoxel1nx1py1pz() > 0 ? 1: 0;
|
||||
|
||||
const typename VolumeType::VoxelType pVoxel0px1ny1nz = volIter.peekVoxel0px1ny1nz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel0px1ny0pz = volIter.peekVoxel0px1ny0pz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel0px1ny1pz = volIter.peekVoxel0px1ny1pz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel0px0py1nz = volIter.peekVoxel0px0py1nz() > 0 ? 1: 0;
|
||||
//const VolumeType::VoxelType pVoxel0px0py0pz = volIter.peekVoxel0px0py0pz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel0px0py1pz = volIter.peekVoxel0px0py1pz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel0px1py1nz = volIter.peekVoxel0px1py1nz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel0px1py0pz = volIter.peekVoxel0px1py0pz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel0px1py1pz = volIter.peekVoxel0px1py1pz() > 0 ? 1: 0;
|
||||
|
||||
const typename VolumeType::VoxelType pVoxel1px1ny1nz = volIter.peekVoxel1px1ny1nz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1px1ny0pz = volIter.peekVoxel1px1ny0pz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1px1ny1pz = volIter.peekVoxel1px1ny1pz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1px0py1nz = volIter.peekVoxel1px0py1nz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1px0py0pz = volIter.peekVoxel1px0py0pz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1px0py1pz = volIter.peekVoxel1px0py1pz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1px1py1nz = volIter.peekVoxel1px1py1nz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1px1py0pz = volIter.peekVoxel1px1py0pz() > 0 ? 1: 0;
|
||||
const typename VolumeType::VoxelType pVoxel1px1py1pz = volIter.peekVoxel1px1py1pz() > 0 ? 1: 0;
|
||||
|
||||
const int xGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
|
||||
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
|
||||
pVoxel1nx1ny1pz - weights[0][1][0] * pVoxel1nx0py1nz -
|
||||
weights[1][1][0] * pVoxel1nx0py0pz - weights[2][1][0] *
|
||||
pVoxel1nx0py1pz - weights[0][2][0] * pVoxel1nx1py1nz -
|
||||
weights[1][2][0] * pVoxel1nx1py0pz - weights[2][2][0] *
|
||||
pVoxel1nx1py1pz + weights[0][0][2] * pVoxel1px1ny1nz +
|
||||
weights[1][0][2] * pVoxel1px1ny0pz + weights[2][0][2] *
|
||||
pVoxel1px1ny1pz + weights[0][1][2] * pVoxel1px0py1nz +
|
||||
weights[1][1][2] * pVoxel1px0py0pz + weights[2][1][2] *
|
||||
pVoxel1px0py1pz + weights[0][2][2] * pVoxel1px1py1nz +
|
||||
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
|
||||
pVoxel1px1py1pz);
|
||||
|
||||
const int yGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
|
||||
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
|
||||
pVoxel1nx1ny1pz + weights[0][2][0] * pVoxel1nx1py1nz +
|
||||
weights[1][2][0] * pVoxel1nx1py0pz + weights[2][2][0] *
|
||||
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz -
|
||||
weights[1][0][1] * pVoxel0px1ny0pz - weights[2][0][1] *
|
||||
pVoxel0px1ny1pz + weights[0][2][1] * pVoxel0px1py1nz +
|
||||
weights[1][2][1] * pVoxel0px1py0pz + weights[2][2][1] *
|
||||
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz -
|
||||
weights[1][0][2] * pVoxel1px1ny0pz - weights[2][0][2] *
|
||||
pVoxel1px1ny1pz + weights[0][2][2] * pVoxel1px1py1nz +
|
||||
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
|
||||
pVoxel1px1py1pz);
|
||||
|
||||
const int zGrad(- weights[0][0][0] * pVoxel1nx1ny1nz +
|
||||
weights[2][0][0] * pVoxel1nx1ny1pz - weights[0][1][0] *
|
||||
pVoxel1nx0py1nz + weights[2][1][0] * pVoxel1nx0py1pz -
|
||||
weights[0][2][0] * pVoxel1nx1py1nz + weights[2][2][0] *
|
||||
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz +
|
||||
weights[2][0][1] * pVoxel0px1ny1pz - weights[0][1][1] *
|
||||
pVoxel0px0py1nz + weights[2][1][1] * pVoxel0px0py1pz -
|
||||
weights[0][2][1] * pVoxel0px1py1nz + weights[2][2][1] *
|
||||
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz +
|
||||
weights[2][0][2] * pVoxel1px1ny1pz - weights[0][1][2] *
|
||||
pVoxel1px0py1nz + weights[2][1][2] * pVoxel1px0py1pz -
|
||||
weights[0][2][2] * pVoxel1px1py1nz + weights[2][2][2] *
|
||||
pVoxel1px1py1pz);
|
||||
|
||||
//Note: The above actually give gradients going from low density to high density.
|
||||
//For our normals we want the the other way around, so we switch the components as we return them.
|
||||
return Vector3DFloat(static_cast<float>(-xGrad),static_cast<float>(-yGrad),static_cast<float>(-zGrad));
|
||||
}
|
||||
|
||||
template<typename VolumeType>
|
||||
Vector3DFloat computeSmoothSobelGradient(typename VolumeType::Sampler& volIter)
|
||||
{
|
||||
static const int weights[3][3][3] = { { {2,3,2}, {3,6,3}, {2,3,2} }, {
|
||||
{3,6,3}, {6,0,6}, {3,6,3} }, { {2,3,2}, {3,6,3}, {2,3,2} } };
|
||||
|
||||
int32_t initialX = volIter.getPosition().getX();
|
||||
int32_t initialY = volIter.getPosition().getY();
|
||||
int32_t initialZ = volIter.getPosition().getZ();
|
||||
|
||||
volIter.setPosition(initialX-1, initialY-1, initialZ-1); const float pVoxel1nx1ny1nz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX-1, initialY-1, initialZ ); const float pVoxel1nx1ny0pz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX-1, initialY-1, initialZ+1); const float pVoxel1nx1ny1pz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX-1, initialY , initialZ-1); const float pVoxel1nx0py1nz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX-1, initialY , initialZ ); const float pVoxel1nx0py0pz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX-1, initialY , initialZ+1); const float pVoxel1nx0py1pz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX-1, initialY+1, initialZ-1); const float pVoxel1nx1py1nz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX-1, initialY+1, initialZ ); const float pVoxel1nx1py0pz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX-1, initialY+1, initialZ+1); const float pVoxel1nx1py1pz = computeSmoothedVoxel(volIter);
|
||||
|
||||
volIter.setPosition(initialX , initialY-1, initialZ-1); const float pVoxel0px1ny1nz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX , initialY-1, initialZ ); const float pVoxel0px1ny0pz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX , initialY-1, initialZ+1); const float pVoxel0px1ny1pz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX , initialY , initialZ-1); const float pVoxel0px0py1nz = computeSmoothedVoxel(volIter);
|
||||
//volIter.setPosition(initialX , initialY , initialZ ); const float pVoxel0px0py0pz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX , initialY , initialZ+1); const float pVoxel0px0py1pz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX , initialY+1, initialZ-1); const float pVoxel0px1py1nz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX , initialY+1, initialZ ); const float pVoxel0px1py0pz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX , initialY+1, initialZ+1); const float pVoxel0px1py1pz = computeSmoothedVoxel(volIter);
|
||||
|
||||
volIter.setPosition(initialX+1, initialY-1, initialZ-1); const float pVoxel1px1ny1nz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX+1, initialY-1, initialZ ); const float pVoxel1px1ny0pz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX+1, initialY-1, initialZ+1); const float pVoxel1px1ny1pz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX+1, initialY , initialZ-1); const float pVoxel1px0py1nz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX+1, initialY , initialZ ); const float pVoxel1px0py0pz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX+1, initialY , initialZ+1); const float pVoxel1px0py1pz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX+1, initialY+1, initialZ-1); const float pVoxel1px1py1nz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX+1, initialY+1, initialZ ); const float pVoxel1px1py0pz = computeSmoothedVoxel(volIter);
|
||||
volIter.setPosition(initialX+1, initialY+1, initialZ+1); const float pVoxel1px1py1pz = computeSmoothedVoxel(volIter);
|
||||
|
||||
/*const VoxelType pVoxel1nx1ny1nz = volIter.peekVoxel1nx1ny1nz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1nx1ny0pz = volIter.peekVoxel1nx1ny0pz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1nx1ny1pz = volIter.peekVoxel1nx1ny1pz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1nx0py1nz = volIter.peekVoxel1nx0py1nz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1nx0py0pz = volIter.peekVoxel1nx0py0pz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1nx0py1pz = volIter.peekVoxel1nx0py1pz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1nx1py1nz = volIter.peekVoxel1nx1py1nz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1nx1py0pz = volIter.peekVoxel1nx1py0pz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1nx1py1pz = volIter.peekVoxel1nx1py1pz() > 0 ? 1: 0;
|
||||
|
||||
const VoxelType pVoxel0px1ny1nz = volIter.peekVoxel0px1ny1nz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel0px1ny0pz = volIter.peekVoxel0px1ny0pz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel0px1ny1pz = volIter.peekVoxel0px1ny1pz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel0px0py1nz = volIter.peekVoxel0px0py1nz() > 0 ? 1: 0;
|
||||
//const VoxelType pVoxel0px0py0pz = volIter.peekVoxel0px0py0pz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel0px0py1pz = volIter.peekVoxel0px0py1pz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel0px1py1nz = volIter.peekVoxel0px1py1nz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel0px1py0pz = volIter.peekVoxel0px1py0pz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel0px1py1pz = volIter.peekVoxel0px1py1pz() > 0 ? 1: 0;
|
||||
|
||||
const VoxelType pVoxel1px1ny1nz = volIter.peekVoxel1px1ny1nz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1px1ny0pz = volIter.peekVoxel1px1ny0pz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1px1ny1pz = volIter.peekVoxel1px1ny1pz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1px0py1nz = volIter.peekVoxel1px0py1nz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1px0py0pz = volIter.peekVoxel1px0py0pz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1px0py1pz = volIter.peekVoxel1px0py1pz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1px1py1nz = volIter.peekVoxel1px1py1nz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1px1py0pz = volIter.peekVoxel1px1py0pz() > 0 ? 1: 0;
|
||||
const VoxelType pVoxel1px1py1pz = volIter.peekVoxel1px1py1pz() > 0 ? 1: 0;*/
|
||||
|
||||
const float xGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
|
||||
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
|
||||
pVoxel1nx1ny1pz - weights[0][1][0] * pVoxel1nx0py1nz -
|
||||
weights[1][1][0] * pVoxel1nx0py0pz - weights[2][1][0] *
|
||||
pVoxel1nx0py1pz - weights[0][2][0] * pVoxel1nx1py1nz -
|
||||
weights[1][2][0] * pVoxel1nx1py0pz - weights[2][2][0] *
|
||||
pVoxel1nx1py1pz + weights[0][0][2] * pVoxel1px1ny1nz +
|
||||
weights[1][0][2] * pVoxel1px1ny0pz + weights[2][0][2] *
|
||||
pVoxel1px1ny1pz + weights[0][1][2] * pVoxel1px0py1nz +
|
||||
weights[1][1][2] * pVoxel1px0py0pz + weights[2][1][2] *
|
||||
pVoxel1px0py1pz + weights[0][2][2] * pVoxel1px1py1nz +
|
||||
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
|
||||
pVoxel1px1py1pz);
|
||||
|
||||
const float yGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
|
||||
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
|
||||
pVoxel1nx1ny1pz + weights[0][2][0] * pVoxel1nx1py1nz +
|
||||
weights[1][2][0] * pVoxel1nx1py0pz + weights[2][2][0] *
|
||||
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz -
|
||||
weights[1][0][1] * pVoxel0px1ny0pz - weights[2][0][1] *
|
||||
pVoxel0px1ny1pz + weights[0][2][1] * pVoxel0px1py1nz +
|
||||
weights[1][2][1] * pVoxel0px1py0pz + weights[2][2][1] *
|
||||
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz -
|
||||
weights[1][0][2] * pVoxel1px1ny0pz - weights[2][0][2] *
|
||||
pVoxel1px1ny1pz + weights[0][2][2] * pVoxel1px1py1nz +
|
||||
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
|
||||
pVoxel1px1py1pz);
|
||||
|
||||
const float zGrad(- weights[0][0][0] * pVoxel1nx1ny1nz +
|
||||
weights[2][0][0] * pVoxel1nx1ny1pz - weights[0][1][0] *
|
||||
pVoxel1nx0py1nz + weights[2][1][0] * pVoxel1nx0py1pz -
|
||||
weights[0][2][0] * pVoxel1nx1py1nz + weights[2][2][0] *
|
||||
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz +
|
||||
weights[2][0][1] * pVoxel0px1ny1pz - weights[0][1][1] *
|
||||
pVoxel0px0py1nz + weights[2][1][1] * pVoxel0px0py1pz -
|
||||
weights[0][2][1] * pVoxel0px1py1nz + weights[2][2][1] *
|
||||
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz +
|
||||
weights[2][0][2] * pVoxel1px1ny1pz - weights[0][1][2] *
|
||||
pVoxel1px0py1nz + weights[2][1][2] * pVoxel1px0py1pz -
|
||||
weights[0][2][2] * pVoxel1px1py1nz + weights[2][2][2] *
|
||||
pVoxel1px1py1pz);
|
||||
|
||||
//Note: The above actually give gradients going from low density to high density.
|
||||
//For our normals we want the the other way around, so we switch the components as we return them.
|
||||
return Vector3DFloat(-xGrad,-yGrad,-zGrad);
|
||||
}
|
||||
}
|
223
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/AStarPathfinderImpl.h
vendored
Normal file
223
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/AStarPathfinderImpl.h
vendored
Normal file
@ -0,0 +1,223 @@
|
||||
/*******************************************************************************
|
||||
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_AStarPathfinderImpl_H__
|
||||
#define __PolyVox_AStarPathfinderImpl_H__
|
||||
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits> //For numeric_limits
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
class OpenNodesContainer;
|
||||
class ClosedNodesContainer;
|
||||
class ThermiteGameLogic;
|
||||
|
||||
/// The Connectivity of a voxel determines how many neighbours it has.
|
||||
enum Connectivity
|
||||
{
|
||||
/// Each voxel has six neighbours, which are those sharing a face.
|
||||
SixConnected,
|
||||
/// Each voxel has 18 neighbours, which are those sharing a face or an edge.
|
||||
EighteenConnected,
|
||||
/// Each voxel has 26 neighbours, which are those sharing a face, edge, or corner.
|
||||
TwentySixConnected
|
||||
};
|
||||
|
||||
struct Node
|
||||
{
|
||||
Node(int x, int y, int z)
|
||||
:gVal(std::numeric_limits<float>::quiet_NaN()) //Initilise with NaNs so that we will
|
||||
,hVal(std::numeric_limits<float>::quiet_NaN()) //know if we forget to set these properly.
|
||||
,parent(0)
|
||||
{
|
||||
position.setX(x);
|
||||
position.setY(y);
|
||||
position.setZ(z);
|
||||
}
|
||||
|
||||
bool operator==(const Node& rhs) const
|
||||
{
|
||||
return position == rhs.position;
|
||||
}
|
||||
|
||||
bool operator<(const Node& rhs) const
|
||||
{
|
||||
if (position.getX() < rhs.position.getX())
|
||||
return true;
|
||||
if (rhs.position.getX() < position.getX())
|
||||
return false;
|
||||
|
||||
if (position.getY() < rhs.position.getY())
|
||||
return true;
|
||||
if (rhs.position.getY() < position.getY())
|
||||
return false;
|
||||
|
||||
if (position.getZ() < rhs.position.getZ())
|
||||
return true;
|
||||
if (rhs.position.getZ() < position.getZ())
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PolyVox::Vector3DInt32 position;
|
||||
float gVal;
|
||||
float hVal;
|
||||
Node* parent;
|
||||
|
||||
float f(void) const
|
||||
{
|
||||
return gVal + hVal;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::set<Node> AllNodesContainer;
|
||||
|
||||
class AllNodesContainerIteratorComparator
|
||||
{
|
||||
public:
|
||||
bool operator() (const AllNodesContainer::iterator& lhs, const AllNodesContainer::iterator& rhs) const
|
||||
{
|
||||
return (&(*lhs)) < (&(*rhs));
|
||||
}
|
||||
};
|
||||
|
||||
class NodeSort
|
||||
{
|
||||
public:
|
||||
bool operator() (const AllNodesContainer::iterator& lhs, const AllNodesContainer::iterator& rhs) const
|
||||
{
|
||||
return lhs->f() > rhs->f();
|
||||
}
|
||||
};
|
||||
|
||||
class OpenNodesContainer
|
||||
{
|
||||
public:
|
||||
typedef std::vector<AllNodesContainer::iterator>::iterator iterator;
|
||||
|
||||
public:
|
||||
void clear(void)
|
||||
{
|
||||
open.clear();
|
||||
}
|
||||
|
||||
bool empty(void) const
|
||||
{
|
||||
return open.empty();
|
||||
}
|
||||
|
||||
void insert(AllNodesContainer::iterator node)
|
||||
{
|
||||
open.push_back(node);
|
||||
push_heap(open.begin(), open.end(), NodeSort());
|
||||
}
|
||||
|
||||
AllNodesContainer::iterator getFirst(void)
|
||||
{
|
||||
return open[0];
|
||||
}
|
||||
|
||||
void removeFirst(void)
|
||||
{
|
||||
pop_heap(open.begin(), open.end(), NodeSort());
|
||||
open.pop_back();
|
||||
}
|
||||
|
||||
void remove(iterator iterToRemove)
|
||||
{
|
||||
open.erase(iterToRemove);
|
||||
make_heap(open.begin(), open.end(), NodeSort());
|
||||
}
|
||||
|
||||
iterator begin(void)
|
||||
{
|
||||
return open.begin();
|
||||
}
|
||||
|
||||
iterator end(void)
|
||||
{
|
||||
return open.end();
|
||||
}
|
||||
|
||||
iterator find(AllNodesContainer::iterator node)
|
||||
{
|
||||
std::vector<AllNodesContainer::iterator>::iterator openIter = std::find(open.begin(), open.end(), node);
|
||||
return openIter;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<AllNodesContainer::iterator> open;
|
||||
};
|
||||
|
||||
class ClosedNodesContainer
|
||||
{
|
||||
public:
|
||||
typedef std::set<AllNodesContainer::iterator, AllNodesContainerIteratorComparator>::iterator iterator;
|
||||
|
||||
public:
|
||||
void clear(void)
|
||||
{
|
||||
closed.clear();
|
||||
}
|
||||
|
||||
void insert(AllNodesContainer::iterator node)
|
||||
{
|
||||
closed.insert(node);
|
||||
}
|
||||
|
||||
void remove(iterator iterToRemove)
|
||||
{
|
||||
closed.erase(iterToRemove);
|
||||
}
|
||||
|
||||
iterator begin(void)
|
||||
{
|
||||
return closed.begin();
|
||||
}
|
||||
|
||||
iterator end(void)
|
||||
{
|
||||
return closed.end();
|
||||
}
|
||||
|
||||
iterator find(AllNodesContainer::iterator node)
|
||||
{
|
||||
iterator iter = std::find(closed.begin(), closed.end(), node);
|
||||
return iter;
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<AllNodesContainer::iterator, AllNodesContainerIteratorComparator> closed;
|
||||
};
|
||||
|
||||
|
||||
//bool operator<(const AllNodesContainer::iterator& lhs, const AllNodesContainer::iterator& rhs);
|
||||
}
|
||||
|
||||
#endif //__PolyVox_AStarPathfinderImpl_H__
|
61
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/ArraySizesImpl.h
vendored
Normal file
61
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/ArraySizesImpl.h
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
/*******************************************************************************
|
||||
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_ArraySizesImpl_H__
|
||||
#define __PolyVox_ArraySizesImpl_H__
|
||||
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/*
|
||||
This class provides the implementation details behind ArraySizes. It is actually
|
||||
quite similar to ArraySizes, but an important difference is that it is templatised
|
||||
whereas ArraySizes is not. This allows us to use a recursive template pattern without
|
||||
exposing the use of templates to the user.
|
||||
|
||||
It is based on the following article: http://www.drdobbs.com/cpp/184401319
|
||||
*/
|
||||
template <uint32_t N>
|
||||
class ArraySizesImpl
|
||||
{
|
||||
typedef const uint32_t (&UIntArrayN)[N];
|
||||
|
||||
friend class ArraySizes;
|
||||
friend class ArraySizesImpl<N-1>;
|
||||
|
||||
public:
|
||||
ArraySizesImpl<N+1> operator () (uint32_t uSize);
|
||||
|
||||
operator UIntArrayN () const;
|
||||
|
||||
private:
|
||||
ArraySizesImpl(const uint32_t (&pSizes)[N-1], uint32_t uSize);
|
||||
|
||||
uint32_t m_pSizes[N];
|
||||
};
|
||||
}//namespace PolyVox
|
||||
|
||||
#include "PolyVoxCore/Impl/ArraySizesImpl.inl"
|
||||
|
||||
#endif //__PolyVox_ArraySizesImpl_H__
|
46
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/ArraySizesImpl.inl
vendored
Normal file
46
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/ArraySizesImpl.inl
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/*******************************************************************************
|
||||
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 <algorithm>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <uint32_t N>
|
||||
ArraySizesImpl<N+1> ArraySizesImpl<N>::operator () (uint32_t uSize)
|
||||
{
|
||||
return ArraySizesImpl<N+1>(m_pSizes, uSize);
|
||||
}
|
||||
|
||||
template <uint32_t N>
|
||||
ArraySizesImpl<N>::operator UIntArrayN () const
|
||||
{
|
||||
return m_pSizes;
|
||||
}
|
||||
|
||||
template <uint32_t N>
|
||||
ArraySizesImpl<N>::ArraySizesImpl(const uint32_t (&pSizes)[N-1], uint32_t uSize)
|
||||
{
|
||||
std::copy(&pSizes[0],&pSizes[N-1],m_pSizes);
|
||||
m_pSizes[N-1]=uSize;
|
||||
}
|
||||
}//namespace PolyVox
|
78
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.h
vendored
Normal file
78
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.h
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
/*******************************************************************************
|
||||
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_Block_H__
|
||||
#define __PolyVox_Block_H__
|
||||
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
class Block
|
||||
{
|
||||
template <typename LengthType>
|
||||
struct RunlengthEntry
|
||||
{
|
||||
LengthType length;
|
||||
VoxelType value;
|
||||
|
||||
//We can parametise the length on anything up to uint32_t.
|
||||
//This lets us experiment with the optimal size in the future.
|
||||
static uint32_t maxRunlength(void) {return (std::numeric_limits<LengthType>::max)();}
|
||||
};
|
||||
|
||||
public:
|
||||
Block(uint16_t uSideLength = 0);
|
||||
|
||||
uint16_t getSideLength(void) const;
|
||||
VoxelType getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const;
|
||||
VoxelType getVoxelAt(const Vector3DUint16& v3dPos) const;
|
||||
|
||||
void setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue);
|
||||
void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue);
|
||||
|
||||
void fill(VoxelType tValue);
|
||||
void initialise(uint16_t uSideLength);
|
||||
uint32_t calculateSizeInBytes(void);
|
||||
|
||||
public:
|
||||
void compress(void);
|
||||
void uncompress(void);
|
||||
|
||||
std::vector< RunlengthEntry<uint16_t> > m_vecCompressedData;
|
||||
VoxelType* m_tUncompressedData;
|
||||
uint16_t m_uSideLength;
|
||||
uint8_t m_uSideLengthPower;
|
||||
bool m_bIsCompressed;
|
||||
bool m_bIsUncompressedDataModified;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/Impl/Block.inl"
|
||||
|
||||
#endif
|
214
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.inl
vendored
Normal file
214
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.inl
vendored
Normal file
@ -0,0 +1,214 @@
|
||||
/*******************************************************************************
|
||||
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 "PolyVoxCore/Impl/Utility.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring> //For memcpy
|
||||
#include <limits>
|
||||
#include <stdexcept> //for std::invalid_argument
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
Block<VoxelType>::Block(uint16_t uSideLength)
|
||||
:m_tUncompressedData(0)
|
||||
,m_uSideLength(0)
|
||||
,m_uSideLengthPower(0)
|
||||
,m_bIsCompressed(true)
|
||||
,m_bIsUncompressedDataModified(true)
|
||||
{
|
||||
if(uSideLength != 0)
|
||||
{
|
||||
initialise(uSideLength);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
uint16_t Block<VoxelType>::getSideLength(void) const
|
||||
{
|
||||
return m_uSideLength;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType Block<VoxelType>::getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const
|
||||
{
|
||||
assert(uXPos < m_uSideLength);
|
||||
assert(uYPos < m_uSideLength);
|
||||
assert(uZPos < m_uSideLength);
|
||||
|
||||
assert(m_tUncompressedData);
|
||||
|
||||
return m_tUncompressedData
|
||||
[
|
||||
uXPos +
|
||||
uYPos * m_uSideLength +
|
||||
uZPos * m_uSideLength * m_uSideLength
|
||||
];
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType Block<VoxelType>::getVoxelAt(const Vector3DUint16& v3dPos) const
|
||||
{
|
||||
return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void Block<VoxelType>::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue)
|
||||
{
|
||||
assert(uXPos < m_uSideLength);
|
||||
assert(uYPos < m_uSideLength);
|
||||
assert(uZPos < m_uSideLength);
|
||||
|
||||
assert(m_tUncompressedData);
|
||||
|
||||
m_tUncompressedData
|
||||
[
|
||||
uXPos +
|
||||
uYPos * m_uSideLength +
|
||||
uZPos * m_uSideLength * m_uSideLength
|
||||
] = tValue;
|
||||
|
||||
m_bIsUncompressedDataModified = true;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void Block<VoxelType>::setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue)
|
||||
{
|
||||
setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void Block<VoxelType>::fill(VoxelType tValue)
|
||||
{
|
||||
if(!m_bIsCompressed)
|
||||
{
|
||||
//The memset *may* be faster than the std::fill(), but it doesn't compile nicely
|
||||
//in 64-bit mode as casting the pointer to an int causes a loss of precision.
|
||||
const uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength;
|
||||
std::fill(m_tUncompressedData, m_tUncompressedData + uNoOfVoxels, tValue);
|
||||
|
||||
m_bIsUncompressedDataModified = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
RunlengthEntry<uint16_t> rle;
|
||||
rle.length = m_uSideLength*m_uSideLength*m_uSideLength;
|
||||
rle.value = tValue;
|
||||
m_vecCompressedData.clear();
|
||||
m_vecCompressedData.push_back(rle);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void Block<VoxelType>::initialise(uint16_t uSideLength)
|
||||
{
|
||||
//Debug mode validation
|
||||
assert(isPowerOf2(uSideLength));
|
||||
|
||||
//Release mode validation
|
||||
if(!isPowerOf2(uSideLength))
|
||||
{
|
||||
throw std::invalid_argument("Block side length must be a power of two.");
|
||||
}
|
||||
|
||||
//Compute the side length
|
||||
m_uSideLength = uSideLength;
|
||||
m_uSideLengthPower = logBase2(uSideLength);
|
||||
|
||||
Block<VoxelType>::fill(VoxelType());
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
uint32_t Block<VoxelType>::calculateSizeInBytes(void)
|
||||
{
|
||||
uint32_t uSizeInBytes = sizeof(Block<VoxelType>);
|
||||
uSizeInBytes += m_vecCompressedData.capacity() * sizeof(RunlengthEntry<uint16_t>);
|
||||
return uSizeInBytes;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void Block<VoxelType>::compress(void)
|
||||
{
|
||||
assert(m_bIsCompressed == false);
|
||||
assert(m_tUncompressedData != 0);
|
||||
|
||||
//If the uncompressed data hasn't actually been
|
||||
//modified then we don't need to redo the compression.
|
||||
if(m_bIsUncompressedDataModified)
|
||||
{
|
||||
uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength;
|
||||
m_vecCompressedData.clear();
|
||||
|
||||
RunlengthEntry<uint16_t> entry;
|
||||
entry.length = 1;
|
||||
entry.value = m_tUncompressedData[0];
|
||||
|
||||
for(uint32_t ct = 1; ct < uNoOfVoxels; ++ct)
|
||||
{
|
||||
VoxelType value = m_tUncompressedData[ct];
|
||||
if((value == entry.value) && (entry.length < entry.maxRunlength()))
|
||||
{
|
||||
entry.length++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vecCompressedData.push_back(entry);
|
||||
entry.value = value;
|
||||
entry.length = 1;
|
||||
}
|
||||
}
|
||||
|
||||
m_vecCompressedData.push_back(entry);
|
||||
|
||||
//Shrink the vectors to their contents (maybe slow?):
|
||||
//http://stackoverflow.com/questions/1111078/reduce-the-capacity-of-an-stl-vector
|
||||
//C++0x may have a shrink_to_fit() function?
|
||||
std::vector< RunlengthEntry<uint16_t> >(m_vecCompressedData).swap(m_vecCompressedData);
|
||||
}
|
||||
|
||||
//Flag the uncompressed data as no longer being used.
|
||||
delete[] m_tUncompressedData;
|
||||
m_tUncompressedData = 0;
|
||||
m_bIsCompressed = true;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void Block<VoxelType>::uncompress(void)
|
||||
{
|
||||
assert(m_bIsCompressed == true);
|
||||
assert(m_tUncompressedData == 0);
|
||||
m_tUncompressedData = new VoxelType[m_uSideLength * m_uSideLength * m_uSideLength];
|
||||
|
||||
VoxelType* pUncompressedData = m_tUncompressedData;
|
||||
for(uint32_t ct = 0; ct < m_vecCompressedData.size(); ++ct)
|
||||
{
|
||||
std::fill(pUncompressedData, pUncompressedData + m_vecCompressedData[ct].length, m_vecCompressedData[ct].value);
|
||||
pUncompressedData += m_vecCompressedData[ct].length;
|
||||
}
|
||||
|
||||
m_bIsCompressed = false;
|
||||
m_bIsUncompressedDataModified = false;
|
||||
}
|
||||
}
|
35
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/MarchingCubesTables.h
vendored
Normal file
35
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/MarchingCubesTables.h
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __PolyVox_MarchingCubeTables_H__
|
||||
#define __PolyVox_MarchingCubeTables_H__
|
||||
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
extern const POLYVOX_API int edgeTable[256];
|
||||
extern const POLYVOX_API int triTable[256][16];
|
||||
}
|
||||
|
||||
#endif
|
36
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/RandomUnitVectors.h
vendored
Normal file
36
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/RandomUnitVectors.h
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/*******************************************************************************
|
||||
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_RandomUnitVectors_H__
|
||||
#define __PolyVox_RandomUnitVectors_H__
|
||||
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
extern POLYVOX_API const Vector3DFloat randomUnitVectors[];
|
||||
}
|
||||
|
||||
#endif //__PolyVox_RandomUnitVectors_H__
|
36
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/RandomVectors.h
vendored
Normal file
36
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/RandomVectors.h
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/*******************************************************************************
|
||||
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_RandomVectors_H__
|
||||
#define __PolyVox_RandomVectors_H__
|
||||
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
extern POLYVOX_API const Vector3DFloat randomVectors[];
|
||||
}
|
||||
|
||||
#endif //__PolyVox_RandomVectors_H__
|
88
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/SubArray.h
vendored
Normal file
88
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/SubArray.h
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
/*******************************************************************************
|
||||
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_SubArray_H__
|
||||
#define __PolyVox_SubArray_H__
|
||||
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <uint32_t noOfDims, typename ElementType> class Array;
|
||||
|
||||
/*
|
||||
This class forms part of the implementation of the Array class. The operator[]
|
||||
return a SubArray of the next size down, so that multiple []'s can be chained
|
||||
together. It is a seperate class from Array so that it can have a reduced interface,
|
||||
and also so that it never takes ownership of the memory to which it points.
|
||||
|
||||
It is based on the following article: http://www.drdobbs.com/cpp/184401319
|
||||
*/
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
class SubArray
|
||||
{
|
||||
friend class Array<noOfDims+1, ElementType>;
|
||||
friend class SubArray<noOfDims+1, ElementType>;
|
||||
|
||||
public:
|
||||
SubArray<noOfDims-1, ElementType> operator [](uint32_t uIndex);
|
||||
|
||||
const SubArray<noOfDims-1, ElementType> operator [](uint32_t uIndex) const;
|
||||
|
||||
private:
|
||||
SubArray<noOfDims, ElementType>(ElementType * pElements, uint32_t * pDimensions, uint32_t * pOffsets);
|
||||
|
||||
uint32_t * m_pDimensions;
|
||||
uint32_t * m_pOffsets;
|
||||
uint32_t m_uNoOfElements;
|
||||
ElementType * m_pElements;
|
||||
};
|
||||
|
||||
template <typename ElementType>
|
||||
class SubArray<1, ElementType>
|
||||
{
|
||||
friend class Array<2, ElementType>;
|
||||
friend class SubArray<2, ElementType>;
|
||||
|
||||
public:
|
||||
ElementType & operator [] (uint32_t uIndex);
|
||||
|
||||
const ElementType & operator [] (uint32_t uIndex) const;
|
||||
|
||||
private:
|
||||
SubArray<1, ElementType>(ElementType * pElements, uint32_t * pDimensions, uint32_t * /*pOffsets*/);
|
||||
|
||||
uint32_t * m_pDimensions;
|
||||
ElementType * m_pElements;
|
||||
};
|
||||
|
||||
template <typename ElementType>
|
||||
class SubArray<0, ElementType>
|
||||
{
|
||||
//Zero dimensional subarray is meaningless.
|
||||
};
|
||||
}//namespace PolyVox
|
||||
|
||||
#include "PolyVoxCore/Impl/SubArray.inl"
|
||||
|
||||
#endif //__PolyVox_SubArray_H__
|
76
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/SubArray.inl
vendored
Normal file
76
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/SubArray.inl
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
/*******************************************************************************
|
||||
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 <cassert>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
SubArray<noOfDims-1, ElementType> SubArray<noOfDims, ElementType>::operator[](uint32_t uIndex)
|
||||
{
|
||||
assert(uIndex<m_pDimensions[0]);
|
||||
return
|
||||
SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]],
|
||||
m_pDimensions+1, m_pOffsets+1);
|
||||
}
|
||||
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
const SubArray<noOfDims-1, ElementType> SubArray<noOfDims, ElementType>::operator[](uint32_t uIndex) const
|
||||
{
|
||||
assert(uIndex<m_pDimensions[0]);
|
||||
return
|
||||
SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]],
|
||||
m_pDimensions+1, m_pOffsets+1);
|
||||
}
|
||||
|
||||
template <uint32_t noOfDims, typename ElementType>
|
||||
SubArray<noOfDims, ElementType>::SubArray(ElementType * pElements, uint32_t * pDimensions, uint32_t * pOffsets)
|
||||
:m_pDimensions(pDimensions)
|
||||
,m_pOffsets(pOffsets)
|
||||
,m_uNoOfElements(0)
|
||||
,m_pElements(pElements)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template <typename ElementType>
|
||||
ElementType& SubArray<1, ElementType>::operator[] (uint32_t uIndex)
|
||||
{
|
||||
assert(uIndex<m_pDimensions[0]);
|
||||
return m_pElements[uIndex];
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
const ElementType& SubArray<1, ElementType>::operator[] (uint32_t uIndex) const
|
||||
{
|
||||
assert(uIndex<m_pDimensions[0]);
|
||||
return m_pElements[uIndex];
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
SubArray<1, ElementType>::SubArray(ElementType * pElements, uint32_t * pDimensions, uint32_t * /*pOffsets*/)
|
||||
:m_pDimensions(pDimensions)
|
||||
,m_pElements(pElements)
|
||||
{
|
||||
}
|
||||
}//namespace PolyVox
|
105
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/TypeDef.h
vendored
Normal file
105
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/TypeDef.h
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
/*******************************************************************************
|
||||
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_TypeDef_H__
|
||||
#define __PolyVox_TypeDef_H__
|
||||
|
||||
//Definitions needed to make library functions accessable
|
||||
// See http://gcc.gnu.org/wiki/Visibility for more info.
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#define POLYVOX_HELPER_IMPORT __declspec(dllimport)
|
||||
#define POLYVOX_HELPER_EXPORT __declspec(dllexport)
|
||||
#define POLYVOX_HELPER_LOCAL
|
||||
#define POLYVOX_DEPRECATED __declspec(deprecated)
|
||||
#else
|
||||
#define POLYVOX_DEPRECATED __attribute__((deprecated))
|
||||
#if __GNUC__ >= 4
|
||||
#define POLYVOX_HELPER_IMPORT __attribute__ ((visibility("default")))
|
||||
#define POLYVOX_HELPER_EXPORT __attribute__ ((visibility("default")))
|
||||
#define POLYVOX_HELPER_LOCAL __attribute__ ((visibility("hidden")))
|
||||
#else
|
||||
#define POLYVOX_HELPER_IMPORT
|
||||
#define POLYVOX_HELPER_EXPORT
|
||||
#define POLYVOX_HELPER_LOCAL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Now we use the generic helper definitions above to define POLYVOX_API and POLYVOX_LOCAL.
|
||||
// POLYVOX_API is used for the public API symbols. It either imports or exports (or does nothing for static build)
|
||||
// POLYVOX_LOCAL is used for non-api symbols.
|
||||
|
||||
#ifdef POLYVOX_SHARED // defined if PolyVox is compiled as a shared library
|
||||
#ifdef POLYVOX_SHARED_EXPORTS // defined if we are building the PolyVox shared library (instead of using it)
|
||||
#define POLYVOX_API POLYVOX_HELPER_EXPORT
|
||||
#else
|
||||
#define POLYVOX_API POLYVOX_HELPER_IMPORT
|
||||
#endif // POLYVOX_SHARED_EXPORTS
|
||||
#define POLYVOX_LOCAL POLYVOX_HELPER_LOCAL
|
||||
#else // POLYVOX_SHARED is not defined: this means PolyVox is a static library.
|
||||
#define POLYVOX_API
|
||||
#define POLYVOX_LOCAL
|
||||
#endif // POLYVOX_SHARED
|
||||
|
||||
//Check which compiler we are using and work around unsupported features as necessary.
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1600)
|
||||
//To support old (pre-vc2010) Microsoft compilers we use boost to replace the
|
||||
//std::shared_ptr and potentially other C++0x features. To use this capability you
|
||||
//will need to make sure you have boost installed on your system.
|
||||
#include <boost/smart_ptr.hpp>
|
||||
#define polyvox_shared_ptr boost::shared_ptr
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#define polyvox_function boost::function
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#define polyvox_bind boost::bind
|
||||
#define polyvox_placeholder_1 _1
|
||||
#define polyvox_placeholder_2 _2
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
#define static_assert BOOST_STATIC_ASSERT
|
||||
|
||||
|
||||
//As long as we're requiring boost, we'll use it to compensate
|
||||
//for the missing cstdint header too.
|
||||
#include <boost/cstdint.hpp>
|
||||
using boost::int8_t;
|
||||
using boost::int16_t;
|
||||
using boost::int32_t;
|
||||
using boost::uint8_t;
|
||||
using boost::uint16_t;
|
||||
using boost::uint32_t;
|
||||
#else
|
||||
//We have a decent compiler - use real C++0x features
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#define polyvox_shared_ptr std::shared_ptr
|
||||
#define polyvox_function std::function
|
||||
#define polyvox_bind std::bind
|
||||
#define polyvox_placeholder_1 std::placeholders::_1
|
||||
#define polyvox_placeholder_2 std::placeholders::_2
|
||||
//#define static_assert static_assert //we can use this
|
||||
#endif
|
||||
|
||||
#endif
|
37
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/Utility.h
vendored
Normal file
37
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Impl/Utility.h
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
/*******************************************************************************
|
||||
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_Utility_H__
|
||||
#define __PolyVox_Utility_H__
|
||||
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
POLYVOX_API uint8_t logBase2(uint32_t uInput);
|
||||
POLYVOX_API bool isPowerOf2(uint32_t uInput);
|
||||
}
|
||||
|
||||
#endif
|
82
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Interpolation.h
vendored
Normal file
82
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Interpolation.h
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
/*******************************************************************************
|
||||
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_Interpolation_H__
|
||||
#define __PolyVox_Interpolation_H__
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename Type>
|
||||
Type lerp(
|
||||
const Type& v0,const Type& v1,
|
||||
const float x)
|
||||
{
|
||||
assert((x >= 0.0f) && (x <= 1.0f));
|
||||
|
||||
//Interpolate along X
|
||||
Type v0_1 = v0 + x * (v1 - v0);
|
||||
|
||||
return v0_1;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
Type bilerp(
|
||||
const Type& v00,const Type& v10,const Type& v01,const Type& v11,
|
||||
const float x, const float y)
|
||||
{
|
||||
assert((x >= 0.0f) && (y >= 0.0f) &&
|
||||
(x <= 1.0f) && (y <= 1.0f));
|
||||
|
||||
// Linearly interpolate along x
|
||||
Type v00_10 = lerp(v00, v10, x);
|
||||
Type v01_11 = lerp(v01, v11, x);
|
||||
|
||||
// And linearly interpolate the results along y
|
||||
Type v00_10__v01_11 = lerp(v00_10, v01_11, y);
|
||||
|
||||
return v00_10__v01_11;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
Type trilerp(
|
||||
const Type& v000,const Type& v100,const Type& v010,const Type& v110,
|
||||
const Type& v001,const Type& v101,const Type& v011,const Type& v111,
|
||||
const float x, const float y, const float z)
|
||||
{
|
||||
assert((x >= 0.0f) && (y >= 0.0f) && (z >= 0.0f) &&
|
||||
(x <= 1.0f) && (y <= 1.0f) && (z <= 1.0f));
|
||||
|
||||
// Bilinearly interpolate along Y
|
||||
Type v000_v100__v010_v110 = bilerp(v000, v100, v010, v110, x, y);
|
||||
Type v001_v101__v011_v111 = bilerp(v001, v101, v011, v111, x, y);
|
||||
|
||||
// And linearly interpolate the results along z
|
||||
Type v000_v100__v010_v110____v001_v101__v011_v111 = lerp(v000_v100__v010_v110, v001_v101__v011_v111, z);
|
||||
|
||||
return v000_v100__v010_v110____v001_v101__v011_v111;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //__PolyVox_Interpolation_H__
|
46
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/IteratorController.h
vendored
Normal file
46
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/IteratorController.h
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/*******************************************************************************
|
||||
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_IteratorController_H__
|
||||
#define __PolyVox_IteratorController_H__
|
||||
|
||||
#include "PolyVoxCore/Region.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename IteratorType>
|
||||
class IteratorController
|
||||
{
|
||||
public:
|
||||
void reset(void);
|
||||
bool moveForward(void);
|
||||
|
||||
public:
|
||||
Region m_regValid;
|
||||
IteratorType* m_Iter;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/IteratorController.inl"
|
||||
|
||||
#endif //__PolyVox_IteratorController_H__
|
63
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/IteratorController.inl
vendored
Normal file
63
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/IteratorController.inl
vendored
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.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename IteratorType>
|
||||
void IteratorController<IteratorType>::reset(void)
|
||||
{
|
||||
m_Iter->setPosition(m_regValid.getLowerCorner());
|
||||
}
|
||||
|
||||
template <typename IteratorType>
|
||||
bool IteratorController<IteratorType>::moveForward(void)
|
||||
{
|
||||
Vector3DInt32 v3dInitialPosition(m_Iter->getPosition().getX(), m_Iter->getPosition().getY(), m_Iter->getPosition().getZ());
|
||||
|
||||
if(v3dInitialPosition.getX() < m_regValid.getUpperCorner().getX())
|
||||
{
|
||||
m_Iter->movePositiveX();
|
||||
return true;
|
||||
}
|
||||
|
||||
v3dInitialPosition.setX(m_regValid.getLowerCorner().getX());
|
||||
|
||||
if(v3dInitialPosition.getY() < m_regValid.getUpperCorner().getY())
|
||||
{
|
||||
v3dInitialPosition.setY(v3dInitialPosition.getY() + 1);
|
||||
m_Iter->setPosition(v3dInitialPosition);
|
||||
return true;
|
||||
}
|
||||
|
||||
v3dInitialPosition.setY(m_regValid.getLowerCorner().getY());
|
||||
|
||||
if(v3dInitialPosition.getZ() < m_regValid.getUpperCorner().getZ())
|
||||
{
|
||||
v3dInitialPosition.setZ(v3dInitialPosition.getZ() + 1);
|
||||
m_Iter->setPosition(v3dInitialPosition);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
360
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h
vendored
Normal file
360
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h
vendored
Normal file
@ -0,0 +1,360 @@
|
||||
/*******************************************************************************
|
||||
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_LargeVolume_H__
|
||||
#define __PolyVox_LargeVolume_H__
|
||||
|
||||
#include "PolyVoxCore/BaseVolume.h"
|
||||
#include "Impl/Block.h"
|
||||
#include "PolyVoxCore/Log.h"
|
||||
#include "PolyVoxCore/Region.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
#include <limits>
|
||||
#include <cassert>
|
||||
#include <cstdlib> //For abort()
|
||||
#include <cstring> //For memcpy
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stdexcept> //For invalid_argument
|
||||
#include <vector>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType> class ConstVolumeProxy;
|
||||
|
||||
/// The LargeVolume class provides a memory efficient method of storing voxel data while also allowing fast access and modification.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// A LargeVolume is essentially a 3D array in which each element (or <i>voxel</i>) is identified by a three dimensional (x,y,z) coordinate.
|
||||
/// We use the LargeVolume class to store our data in an efficient way, and it is the input to many of the algorithms (such as the surface
|
||||
/// extractors) which form the heart of PolyVox. The LargeVolume class is templatised so that different types of data can be stored within each voxel.
|
||||
///
|
||||
/// Basic usage
|
||||
/// -----------
|
||||
///
|
||||
/// The following code snippet shows how to construct a volume and demonstrates basic usage:
|
||||
///
|
||||
/// \code
|
||||
/// LargeVolume<Material8> volume(Region(Vector3DInt32(0,0,0), Vector3DInt32(63,127,255)));
|
||||
/// volume.setVoxelAt(15, 90, 42, Material8(5));
|
||||
/// std::cout << "Voxel at (15, 90, 42) has value: " << volume.getVoxelAt(15, 90, 42).getMaterial() << std::endl;
|
||||
/// std::cout << "Width = " << volume.getWidth() << ", Height = " << volume.getHeight() << ", Depth = " << volume.getDepth() << std::endl;
|
||||
/// \endcode
|
||||
///
|
||||
/// In this particular example each voxel in the LargeVolume is of type 'Material8', as specified by the template parameter. This is one of several
|
||||
/// predefined voxel types, and it is also possible to define your own. The Material8 type simply holds an integer value where zero represents
|
||||
/// empty space and any other value represents a solid material.
|
||||
///
|
||||
/// The LargeVolume constructor takes a Region as a parameter. This specifies the valid range of voxels which can be held in the volume, so in this
|
||||
/// particular case the valid voxel positions are (0,0,0) to (63, 127, 255). Attempts to access voxels outside this range will result is accessing the
|
||||
/// border value (see getBorderValue() and setBorderValue()). PolyVox also has support for near infinite volumes which will be discussed later.
|
||||
///
|
||||
/// Access to individual voxels is provided via the setVoxelAt() and getVoxelAt() member functions. Advanced users may also be interested in
|
||||
/// the Sampler class for faster read-only access to a large number of voxels.
|
||||
///
|
||||
/// Lastly the example prints out some properties of the LargeVolume. Note that the dimentsions getWidth(), getHeight(), and getDepth() are inclusive, such
|
||||
/// that the width is 64 when the range of valid x coordinates goes from 0 to 63.
|
||||
///
|
||||
/// Data Representaion
|
||||
/// ------------------
|
||||
/// If stored carelessly, volume data can take up a huge amount of memory. For example, a volume of dimensions 1024x1024x1024 with
|
||||
/// 1 byte per voxel will require 1GB of memory if stored in an uncompressed form. Natuarally our LargeVolume class is much more efficient
|
||||
/// than this and it is worth understanding (at least at a high level) the approach which is used.
|
||||
///
|
||||
/// Essentially, the LargeVolume class stores its data as a collection of blocks. Each of these block is much smaller than the whole volume,
|
||||
/// for example a typical size might be 32x32x32 voxels (though is is configurable by the user). In this case, a 256x512x1024 volume
|
||||
/// would contain 8x16x32 = 4096 blocks. The data for each block is stored in a compressed form, which uses only a small amout of
|
||||
/// memory but it is hard to modify the data. Therefore, before any given voxel can be modified, its corresponding block must be uncompressed.
|
||||
///
|
||||
/// The compression and decompression of block is a relatively slow process and so we aim to do this as rarely as possible. In order
|
||||
/// to achive this, the volume class stores a cache of recently used blocks and their associated uncompressed data. Each time a voxel
|
||||
/// is touched a timestamp is updated on the corresponding block. When the cache becomes full the block with the oldest timestamp is
|
||||
/// recompressed and moved out of the cache.
|
||||
///
|
||||
/// Achieving high compression rates
|
||||
/// --------------------------------
|
||||
/// The compression rates which can be achieved can vary significantly depending the nature of the data you are storing, but you can
|
||||
/// encourage high compression rates by making your data as homogenous as possible. If you are simply storing a material with each
|
||||
/// voxel then this will probably happen naturally. Games such as Minecraft which use this approach will typically involve large areas
|
||||
/// of the same material which will compress down well.
|
||||
///
|
||||
/// However, if you are storing density values then you may want to take some care. The advantage of storing smoothly changing values
|
||||
/// is that you can get smooth surfaces extracted, but storing smoothly changing values inside or outside objects (rather than just
|
||||
/// on the boundary) does not benefit the surface and is very hard to compress effectively. You may wish to apply some thresholding to
|
||||
/// your density values to reduce this problem (this threasholding should only be applied to voxels who don't contribute to the surface).
|
||||
///
|
||||
/// Paging large volumes
|
||||
/// --------------------
|
||||
/// The compression scheme described previously will typically allow you to load several billion voxels into a few hundred megabytes of memory,
|
||||
/// though as explained the exact compression rate is highly dependant on your data. If you have more data than this then PolyVox provides a
|
||||
/// mechanism by which parts of the volume can be paged out of memory by calling user supplied callback functions. This mechanism allows a
|
||||
/// potentially unlimited amount of data to be loaded, provided the user is able to take responsibility for storing any data which PolyVox
|
||||
/// cannot fit in memory, and then returning it back to PolyVox on demand. For example, the user might choose to temporarily store this data
|
||||
/// on disk or stream it to a remote database.
|
||||
///
|
||||
/// You can construct such a LargeVolume as follows:
|
||||
///
|
||||
/// \code
|
||||
/// void myDataRequiredHandler(const ConstVolumeProxy<MaterialDensityPair44>& volume, const PolyVox::Region& reg)
|
||||
/// {
|
||||
/// //This function is being called because part of the data is missing from memory and needs to be supplied. The parameter
|
||||
/// //'volume' provides access to the volume data, and the parameter 'reg' indicates which region of the volume you need fill.
|
||||
/// }
|
||||
///
|
||||
/// void myDataOverflowHandler(const ConstVolumeProxy<MaterialDensityPair44>& vol, const PolyVox::Region& reg)
|
||||
/// {
|
||||
/// //This function is being called because part of the data is about to be removed from memory. The parameter 'volume'
|
||||
/// //provides access to the volume data, and the parameter 'reg' indicates which region of the volume you need to store.
|
||||
/// }
|
||||
///
|
||||
/// LargeVolume<Density>volData(&myDataRequiredHandler, &myDataOverflowHandler);
|
||||
/// \endcode
|
||||
///
|
||||
/// Essentially you are providing an extension to the LargeVolume class - a way for data to be stored once PolyVox has run out of memory for it. Note
|
||||
/// that you don't actually have to do anything with the data - you could simply decide that once it gets removed from memory it doesn't matter
|
||||
/// anymore. But you still need to be ready to then provide something to PolyVox (even if it's just default data) in the event that it is requested.
|
||||
///
|
||||
/// Cache-aware traversal
|
||||
/// ---------------------
|
||||
/// You might be suprised at just how many cache misses can occur when you traverse the volume in a naive manner. Consider a 1024x1024x1024 volume
|
||||
/// with blocks of size 32x32x32. And imagine you iterate over this volume with a simple three-level for loop which iterates over x, the y, then z.
|
||||
/// If you start at position (0,0,0) then ny the time you reach position (1023,0,0) you have touched 1024 voxels along one edge of the volume and
|
||||
/// have pulled 32 blocks into the cache. By the time you reach (1023,1023,0) you have hit 1024x1024 voxels and pulled 32x32 blocks into the cache.
|
||||
/// You are now ready to touch voxel (0,0,1) which is right nect to where you started, but unless your cache is at least 32x32 blocks large then this
|
||||
/// initial block has already been cleared from the cache.
|
||||
///
|
||||
/// Ensuring you have a large enough cache size can obviously help the above situation, but you might also consider iterating over the voxels in a
|
||||
/// different order. For example, if you replace your three-level loop with a six-level loop then you can first process all the voxels between (0,0,0)
|
||||
/// and (31,31,31), then process all the voxels between (32,0,0) and (63,0,0), and so forth. Using this approach you will have no cache misses even
|
||||
/// is your cache sise is only one. Of course the logic is more complex, but writing code in such a cache-aware manner may be beneficial in some situations.
|
||||
///
|
||||
/// Threading
|
||||
/// ---------
|
||||
/// The LargeVolume class does not make any guarentees about thread safety. You should ensure that all accesses are performed from the same thread.
|
||||
/// This is true even if you are only reading data from the volume, as concurrently reading from different threads can invalidate the contents
|
||||
/// of the block cache (amoung other problems).
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
class LargeVolume : public BaseVolume<VoxelType>
|
||||
{
|
||||
public:
|
||||
//There seems to be some descrepency between Visual Studio and GCC about how the following class should be declared.
|
||||
//There is a work around (see also See http://goo.gl/qu1wn) given below which appears to work on VS2010 and GCC, but
|
||||
//which seems to cause internal compiler errors on VS2008 when building with the /Gm 'Enable Minimal Rebuild' compiler
|
||||
//option. For now it seems best to 'fix' it with the preprocessor insstead, but maybe the workaround can be reinstated
|
||||
//in the future
|
||||
//typedef Volume<VoxelType> VolumeOfVoxelType; //Workaround for GCC/VS2010 differences.
|
||||
//class Sampler : public VolumeOfVoxelType::template Sampler< LargeVolume<VoxelType> >
|
||||
#if defined(_MSC_VER)
|
||||
class Sampler : public BaseVolume<VoxelType>::Sampler< LargeVolume<VoxelType> > //This line works on VS2010
|
||||
#else
|
||||
class Sampler : public BaseVolume<VoxelType>::template Sampler< LargeVolume<VoxelType> > //This line works on GCC
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
Sampler(LargeVolume<VoxelType>* volume);
|
||||
~Sampler();
|
||||
|
||||
Sampler& operator=(const Sampler& rhs);
|
||||
|
||||
VoxelType getSubSampledVoxel(uint8_t uLevel) const;
|
||||
inline VoxelType getVoxel(void) const;
|
||||
|
||||
void setPosition(const Vector3DInt32& v3dNewPos);
|
||||
void setPosition(int32_t xPos, int32_t yPos, int32_t zPos);
|
||||
inline bool setVoxel(VoxelType tValue);
|
||||
|
||||
void movePositiveX(void);
|
||||
void movePositiveY(void);
|
||||
void movePositiveZ(void);
|
||||
|
||||
void moveNegativeX(void);
|
||||
void moveNegativeY(void);
|
||||
void moveNegativeZ(void);
|
||||
|
||||
inline VoxelType peekVoxel1nx1ny1nz(void) const;
|
||||
inline VoxelType peekVoxel1nx1ny0pz(void) const;
|
||||
inline VoxelType peekVoxel1nx1ny1pz(void) const;
|
||||
inline VoxelType peekVoxel1nx0py1nz(void) const;
|
||||
inline VoxelType peekVoxel1nx0py0pz(void) const;
|
||||
inline VoxelType peekVoxel1nx0py1pz(void) const;
|
||||
inline VoxelType peekVoxel1nx1py1nz(void) const;
|
||||
inline VoxelType peekVoxel1nx1py0pz(void) const;
|
||||
inline VoxelType peekVoxel1nx1py1pz(void) const;
|
||||
|
||||
inline VoxelType peekVoxel0px1ny1nz(void) const;
|
||||
inline VoxelType peekVoxel0px1ny0pz(void) const;
|
||||
inline VoxelType peekVoxel0px1ny1pz(void) const;
|
||||
inline VoxelType peekVoxel0px0py1nz(void) const;
|
||||
inline VoxelType peekVoxel0px0py0pz(void) const;
|
||||
inline VoxelType peekVoxel0px0py1pz(void) const;
|
||||
inline VoxelType peekVoxel0px1py1nz(void) const;
|
||||
inline VoxelType peekVoxel0px1py0pz(void) const;
|
||||
inline VoxelType peekVoxel0px1py1pz(void) const;
|
||||
|
||||
inline VoxelType peekVoxel1px1ny1nz(void) const;
|
||||
inline VoxelType peekVoxel1px1ny0pz(void) const;
|
||||
inline VoxelType peekVoxel1px1ny1pz(void) const;
|
||||
inline VoxelType peekVoxel1px0py1nz(void) const;
|
||||
inline VoxelType peekVoxel1px0py0pz(void) const;
|
||||
inline VoxelType peekVoxel1px0py1pz(void) const;
|
||||
inline VoxelType peekVoxel1px1py1nz(void) const;
|
||||
inline VoxelType peekVoxel1px1py0pz(void) const;
|
||||
inline VoxelType peekVoxel1px1py1pz(void) const;
|
||||
|
||||
private:
|
||||
//Other current position information
|
||||
VoxelType* mCurrentVoxel;
|
||||
};
|
||||
|
||||
// Make the ConstVolumeProxy a friend
|
||||
friend class ConstVolumeProxy<VoxelType>;
|
||||
|
||||
struct LoadedBlock
|
||||
{
|
||||
public:
|
||||
LoadedBlock(uint16_t uSideLength = 0)
|
||||
:block(uSideLength)
|
||||
,timestamp(0)
|
||||
{
|
||||
}
|
||||
|
||||
Block<VoxelType> block;
|
||||
uint32_t timestamp;
|
||||
};
|
||||
|
||||
public:
|
||||
/// Constructor for creating a very large paging volume.
|
||||
LargeVolume
|
||||
(
|
||||
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler,
|
||||
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler,
|
||||
uint16_t uBlockSideLength = 32
|
||||
);
|
||||
/// Constructor for creating a fixed size volume.
|
||||
LargeVolume
|
||||
(
|
||||
const Region& regValid,
|
||||
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler = 0,
|
||||
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler = 0,
|
||||
bool bPagingEnabled = false,
|
||||
uint16_t uBlockSideLength = 32
|
||||
);
|
||||
/// Destructor
|
||||
~LargeVolume();
|
||||
|
||||
/// Gets the value used for voxels which are outside the volume
|
||||
VoxelType getBorderValue(void) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
|
||||
|
||||
//Sets whether or not blocks are compressed in memory
|
||||
void setCompressionEnabled(bool bCompressionEnabled);
|
||||
/// Sets the number of blocks for which uncompressed data is stored
|
||||
void setMaxNumberOfUncompressedBlocks(uint32_t uMaxNumberOfUncompressedBlocks);
|
||||
/// Sets the number of blocks which can be in memory before the paging system starts unloading them
|
||||
void setMaxNumberOfBlocksInMemory(uint32_t uMaxNumberOfBlocksInMemory);
|
||||
/// Sets the value used for voxels which are outside the volume
|
||||
void setBorderValue(const VoxelType& tBorder);
|
||||
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue);
|
||||
/// Sets the voxel at the position given by a 3D vector
|
||||
bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue);
|
||||
/// Tries to ensure that the voxels within the specified Region are loaded into memory.
|
||||
void prefetch(Region regPrefetch);
|
||||
/// Ensures that any voxels within the specified Region are removed from memory.
|
||||
void flush(Region regFlush);
|
||||
/// Removes all voxels from memory
|
||||
void flushAll();
|
||||
|
||||
/// Empties the cache of uncompressed blocks
|
||||
void clearBlockCache(void);
|
||||
/// Calculates the approximate compression ratio of the store volume data
|
||||
float calculateCompressionRatio(void);
|
||||
/// Calculates approximatly how many bytes of memory the volume is currently using.
|
||||
uint32_t calculateSizeInBytes(void);
|
||||
|
||||
protected:
|
||||
/// Copy constructor
|
||||
LargeVolume(const LargeVolume& rhs);
|
||||
|
||||
/// Assignment operator
|
||||
LargeVolume& operator=(const LargeVolume& rhs);
|
||||
|
||||
private:
|
||||
void initialise(const Region& regValidRegion, uint16_t uBlockSideLength);
|
||||
|
||||
/// gets called when a new region is allocated and needs to be filled
|
||||
/// NOTE: accessing ANY voxels outside this region during the process of this function
|
||||
/// is absolutely unsafe
|
||||
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> m_funcDataRequiredHandler;
|
||||
/// gets called when a Region needs to be stored by the user, because LargeVolume will erase it right after
|
||||
/// this function returns
|
||||
/// NOTE: accessing ANY voxels outside this region during the process of this function
|
||||
/// is absolutely unsafe
|
||||
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> m_funcDataOverflowHandler;
|
||||
|
||||
Block<VoxelType>* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const;
|
||||
void eraseBlock(typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock) const;
|
||||
/// this function can be called by m_funcDataRequiredHandler without causing any weird effects
|
||||
bool setVoxelAtConst(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const;
|
||||
|
||||
//The block data
|
||||
mutable std::map<Vector3DInt32, LoadedBlock > m_pBlocks;
|
||||
|
||||
//The cache of uncompressed blocks. The uncompressed block data and the timestamps are stored here rather
|
||||
//than in the Block class. This is so that in the future each VolumeIterator might to maintain its own cache
|
||||
//of blocks. However, this could mean the same block data is uncompressed and modified in more than one
|
||||
//location in memory... could be messy with threading.
|
||||
mutable std::vector< LoadedBlock* > m_vecUncompressedBlockCache;
|
||||
mutable uint32_t m_uTimestamper;
|
||||
mutable Vector3DInt32 m_v3dLastAccessedBlockPos;
|
||||
mutable Block<VoxelType>* m_pLastAccessedBlock;
|
||||
uint32_t m_uMaxNumberOfUncompressedBlocks;
|
||||
uint32_t m_uMaxNumberOfBlocksInMemory;
|
||||
|
||||
//We don't store an actual Block for the border, just the uncompressed data. This is partly because the border
|
||||
//block does not have a position (so can't be passed to getUncompressedBlock()) and partly because there's a
|
||||
//good chance we'll often hit it anyway. It's a chunk of homogenous data (rather than a single value) so that
|
||||
//the VolumeIterator can do it's usual pointer arithmetic without needing to know it's gone outside the volume.
|
||||
VoxelType* m_pUncompressedBorderData;
|
||||
|
||||
//The size of the volume
|
||||
Region m_regValidRegionInBlocks;
|
||||
|
||||
//The size of the blocks
|
||||
uint16_t m_uBlockSideLength;
|
||||
uint8_t m_uBlockSideLengthPower;
|
||||
|
||||
bool m_bCompressionEnabled;
|
||||
bool m_bPagingEnabled;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/LargeVolume.inl"
|
||||
#include "PolyVoxCore/LargeVolumeSampler.inl"
|
||||
|
||||
#endif //__PolyVox_LargeVolume_H__
|
667
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl
vendored
Normal file
667
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl
vendored
Normal file
@ -0,0 +1,667 @@
|
||||
/*******************************************************************************
|
||||
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.
|
||||
*******************************************************************************/
|
||||
|
||||
//Included here rather than in the .h because it refers to LargeVolume (avoids forward declaration)
|
||||
#include "PolyVoxCore/ConstVolumeProxy.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// When construncting a very large volume you need to be prepared to handle the scenario where there is so much data that PolyVox cannot fit it all in memory. When PolyVox runs out of memory, it identifies the least recently used data and hands it back to the application via a callback function. It is then the responsibility of the application to store this data until PolyVox needs it again (as signalled by another callback function). Please see the LargeVolume class documentation for a full description of this process and the required function signatures. If you really don't want to handle these events then you can provide null pointers here, in which case the data will be discarded and/or filled with default values.
|
||||
/// \param dataRequiredHandler The callback function which will be called when PolyVox tries to use data which is not currently in memory.
|
||||
/// \param dataOverflowHandler The callback function which will be called when PolyVox has too much data and needs to remove some from memory.
|
||||
/// \param uBlockSideLength The size of the blocks making up the volume. Small blocks will compress/decompress faster, but there will also be more of them meaning voxel access could be slower.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
LargeVolume<VoxelType>::LargeVolume
|
||||
(
|
||||
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler,
|
||||
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler,
|
||||
uint16_t uBlockSideLength
|
||||
)
|
||||
:BaseVolume<VoxelType>(Region::MaxRegion)
|
||||
{
|
||||
m_funcDataRequiredHandler = dataRequiredHandler;
|
||||
m_funcDataOverflowHandler = dataOverflowHandler;
|
||||
m_bPagingEnabled = true;
|
||||
//Create a volume of the right size.
|
||||
initialise(Region::MaxRegion,uBlockSideLength);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This constructor creates a volume with a fixed size which is specified as a parameter. By default this constructor will not enable paging but you can override this if desired. If you do wish to enable paging then you are required to provide the call back function (see the other LargeVolume constructor).
|
||||
/// \param regValid Specifies the minimum and maximum valid voxel positions.
|
||||
/// \param dataRequiredHandler The callback function which will be called when PolyVox tries to use data which is not currently in momory.
|
||||
/// \param dataOverflowHandler The callback function which will be called when PolyVox has too much data and needs to remove some from memory.
|
||||
/// \param bPagingEnabled Controls whether or not paging is enabled for this LargeVolume.
|
||||
/// \param uBlockSideLength The size of the blocks making up the volume. Small blocks will compress/decompress faster, but there will also be more of them meaning voxel access could be slower.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
LargeVolume<VoxelType>::LargeVolume
|
||||
(
|
||||
const Region& regValid,
|
||||
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler,
|
||||
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler,
|
||||
bool bPagingEnabled,
|
||||
uint16_t uBlockSideLength
|
||||
)
|
||||
:BaseVolume<VoxelType>(regValid)
|
||||
{
|
||||
m_funcDataRequiredHandler = dataRequiredHandler;
|
||||
m_funcDataOverflowHandler = dataOverflowHandler;
|
||||
m_bPagingEnabled = bPagingEnabled;
|
||||
|
||||
//Create a volume of the right size.
|
||||
initialise(regValid,uBlockSideLength);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This function should never be called. Copying volumes by value would be expensive, and we want to prevent users from doing
|
||||
/// it by accident (such as when passing them as paramenters to functions). That said, there are times when you really do want to
|
||||
/// make a copy of a volume and in this case you should look at the Volumeresampler.
|
||||
///
|
||||
/// \sa VolumeResampler
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
LargeVolume<VoxelType>::LargeVolume(const LargeVolume<VoxelType>& /*rhs*/)
|
||||
{
|
||||
assert(false); // See function comment above.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Destroys the volume The destructor will call flushAll() to ensure that a paging volume has the chance to save it's data via the dataOverflowHandler() if desired.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
LargeVolume<VoxelType>::~LargeVolume()
|
||||
{
|
||||
flushAll();
|
||||
delete[] m_pUncompressedBorderData;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This function should never be called. Copying volumes by value would be expensive, and we want to prevent users from doing
|
||||
/// it by accident (such as when passing them as paramenters to functions). That said, there are times when you really do want to
|
||||
/// make a copy of a volume and in this case you should look at the Volumeresampler.
|
||||
///
|
||||
/// \sa VolumeResampler
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
LargeVolume<VoxelType>& LargeVolume<VoxelType>::operator=(const LargeVolume<VoxelType>& /*rhs*/)
|
||||
{
|
||||
assert(false); // See function comment above.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// The border value is returned whenever an atempt is made to read a voxel which
|
||||
/// is outside the extents of the volume.
|
||||
/// \return The value used for voxels outside of the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::getBorderValue(void) const
|
||||
{
|
||||
return *m_pUncompressedBorderData;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param uXPos The \c x position of the voxel
|
||||
/// \param uYPos The \c y position of the voxel
|
||||
/// \param uZPos The \c z position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
|
||||
{
|
||||
if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)))
|
||||
{
|
||||
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
|
||||
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
|
||||
const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
|
||||
|
||||
const uint16_t xOffset = static_cast<uint16_t>(uXPos - (blockX << m_uBlockSideLengthPower));
|
||||
const uint16_t yOffset = static_cast<uint16_t>(uYPos - (blockY << m_uBlockSideLengthPower));
|
||||
const uint16_t zOffset = static_cast<uint16_t>(uZPos - (blockZ << m_uBlockSideLengthPower));
|
||||
|
||||
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||
|
||||
return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return getBorderValue();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos The 3D position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::getVoxelAt(const Vector3DInt32& v3dPos) const
|
||||
{
|
||||
return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Enabling compression allows significantly more data to be stored in memory.
|
||||
/// \param bCompressionEnabled Specifies whether compression is enabled.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::setCompressionEnabled(bool bCompressionEnabled)
|
||||
{
|
||||
//Early out - nothing to do
|
||||
if(m_bCompressionEnabled == bCompressionEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_bCompressionEnabled = bCompressionEnabled;
|
||||
|
||||
if(m_bCompressionEnabled)
|
||||
{
|
||||
//If compression has been enabled then we need to start honouring the max number of
|
||||
//uncompressed blocks. Because compression has been disabled for a while we might have
|
||||
//gone above that limit. Easiest solution is just to clear the cache and start again.
|
||||
clearBlockCache();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Increasing the size of the block cache will increase memory but may improve performance.
|
||||
/// You may want to set this to a large value (e.g. 1024) when you are first loading your
|
||||
/// volume data and then set it to a smaller value (e.g.64) for general processing.
|
||||
/// \param uMaxNumberOfUncompressedBlocks The number of blocks for which uncompressed data can be cached.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::setMaxNumberOfUncompressedBlocks(uint32_t uMaxNumberOfUncompressedBlocks)
|
||||
{
|
||||
clearBlockCache();
|
||||
|
||||
m_uMaxNumberOfUncompressedBlocks = uMaxNumberOfUncompressedBlocks;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Increasing the number of blocks in memory causes fewer calls to dataRequiredHandler()/dataOverflowHandler()
|
||||
/// \param uMaxNumberOfBlocksInMemory The number of blocks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::setMaxNumberOfBlocksInMemory(uint32_t uMaxNumberOfBlocksInMemory)
|
||||
{
|
||||
if(m_pBlocks.size() > uMaxNumberOfBlocksInMemory)
|
||||
{
|
||||
flushAll();
|
||||
}
|
||||
m_uMaxNumberOfBlocksInMemory = uMaxNumberOfBlocksInMemory;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param tBorder The value to use for voxels outside the volume.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::setBorderValue(const VoxelType& tBorder)
|
||||
{
|
||||
/*Block<VoxelType>* pUncompressedBorderBlock = getUncompressedBlock(&m_pBorderBlock);
|
||||
return pUncompressedBorderBlock->fill(tBorder);*/
|
||||
std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, tBorder);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param uXPos the \c x position of the voxel
|
||||
/// \param uYPos the \c y position of the voxel
|
||||
/// \param uZPos the \c z position of the voxel
|
||||
/// \param tValue the value to which the voxel will be set
|
||||
/// \return whether the requested position is inside the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
bool LargeVolume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue)
|
||||
{
|
||||
assert(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
|
||||
|
||||
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
|
||||
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
|
||||
const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
|
||||
|
||||
const uint16_t xOffset = static_cast<uint16_t>(uXPos - (blockX << m_uBlockSideLengthPower));
|
||||
const uint16_t yOffset = static_cast<uint16_t>(uYPos - (blockY << m_uBlockSideLengthPower));
|
||||
const uint16_t zOffset = static_cast<uint16_t>(uZPos - (blockZ << m_uBlockSideLengthPower));
|
||||
|
||||
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||
|
||||
pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
|
||||
|
||||
//Return true to indicate that we modified a voxel.
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos the 3D position of the voxel
|
||||
/// \param tValue the value to which the voxel will be set
|
||||
/// \return whether the requested position is inside the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
bool LargeVolume<VoxelType>::setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue)
|
||||
{
|
||||
return setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Note that if MaxNumberOfBlocksInMemory is not large enough to support the region this function will only load part of the region. In this case it is undefined which parts will actually be loaded. If all the voxels in the given region are already loaded, this function will not do anything. Other voxels might be unloaded to make space for the new voxels.
|
||||
/// \param regPrefetch The Region of voxels to prefetch into memory.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::prefetch(Region regPrefetch)
|
||||
{
|
||||
Vector3DInt32 v3dStart;
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
v3dStart.setElement(i, regPrefetch.getLowerCorner().getElement(i) >> m_uBlockSideLengthPower);
|
||||
}
|
||||
|
||||
Vector3DInt32 v3dEnd;
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
v3dEnd.setElement(i, regPrefetch.getUpperCorner().getElement(i) >> m_uBlockSideLengthPower);
|
||||
}
|
||||
|
||||
Vector3DInt32 v3dSize = v3dEnd - v3dStart + Vector3DInt32(1,1,1);
|
||||
uint32_t numblocks = static_cast<uint32_t>(v3dSize.getX() * v3dSize.getY() * v3dSize.getZ());
|
||||
if(numblocks > m_uMaxNumberOfBlocksInMemory)
|
||||
{
|
||||
// cannot support the amount of blocks... so only load the maximum possible
|
||||
numblocks = m_uMaxNumberOfBlocksInMemory;
|
||||
}
|
||||
for(int32_t x = v3dStart.getX(); x <= v3dEnd.getX(); x++)
|
||||
{
|
||||
for(int32_t y = v3dStart.getY(); y <= v3dEnd.getY(); y++)
|
||||
{
|
||||
for(int32_t z = v3dStart.getZ(); z <= v3dEnd.getZ(); z++)
|
||||
{
|
||||
Vector3DInt32 pos(x,y,z);
|
||||
typename std::map<Vector3DInt32, LoadedBlock>::iterator itBlock = m_pBlocks.find(pos);
|
||||
|
||||
if(itBlock != m_pBlocks.end())
|
||||
{
|
||||
// If the block is already loaded then we don't load it again. This means it does not get uncompressed,
|
||||
// whereas if we were to call getUncompressedBlock() regardless then it would also get uncompressed.
|
||||
// This might be nice, but on the prefetch region could be bigger than the uncompressed cache size.
|
||||
// This would limit the amount of prefetching we could do.
|
||||
continue;
|
||||
}
|
||||
|
||||
if(numblocks == 0)
|
||||
{
|
||||
// Loading any more blocks would attempt to overflow the memory and therefore erase blocks
|
||||
// we loaded in the beginning. This wouldn't cause logic problems but would be wasteful.
|
||||
return;
|
||||
}
|
||||
// load a block
|
||||
numblocks--;
|
||||
getUncompressedBlock(x,y,z);
|
||||
} // for z
|
||||
} // for y
|
||||
} // for x
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Removes all voxels from memory, and calls dataOverflowHandler() to ensure the application has a chance to store the data.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::flushAll()
|
||||
{
|
||||
typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
|
||||
//Replaced the for loop here as the call to
|
||||
//eraseBlock was invalidating the iterator.
|
||||
while(m_pBlocks.size() > 0)
|
||||
{
|
||||
eraseBlock(m_pBlocks.begin());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Removes all voxels in the specified Region from memory, and calls dataOverflowHandler() to ensure the application has a chance to store the data. It is possible that there are no voxels loaded in the Region, in which case the function will have no effect.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::flush(Region regFlush)
|
||||
{
|
||||
Vector3DInt32 v3dStart;
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
v3dStart.setElement(i, regFlush.getLowerCorner().getElement(i) >> m_uBlockSideLengthPower);
|
||||
}
|
||||
|
||||
Vector3DInt32 v3dEnd;
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
v3dEnd.setElement(i, regFlush.getUpperCorner().getElement(i) >> m_uBlockSideLengthPower);
|
||||
}
|
||||
|
||||
for(int32_t x = v3dStart.getX(); x <= v3dEnd.getX(); x++)
|
||||
{
|
||||
for(int32_t y = v3dStart.getY(); y <= v3dEnd.getY(); y++)
|
||||
{
|
||||
for(int32_t z = v3dStart.getZ(); z <= v3dEnd.getZ(); z++)
|
||||
{
|
||||
Vector3DInt32 pos(x,y,z);
|
||||
typename std::map<Vector3DInt32, LoadedBlock>::iterator itBlock = m_pBlocks.find(pos);
|
||||
if(itBlock == m_pBlocks.end())
|
||||
{
|
||||
// not loaded, not unloading
|
||||
continue;
|
||||
}
|
||||
eraseBlock(itBlock);
|
||||
// eraseBlock might cause a call to getUncompressedBlock, which again sets m_pLastAccessedBlock
|
||||
if(m_v3dLastAccessedBlockPos == pos)
|
||||
{
|
||||
m_pLastAccessedBlock = 0;
|
||||
}
|
||||
} // for z
|
||||
} // for y
|
||||
} // for x
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::clearBlockCache(void)
|
||||
{
|
||||
for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
|
||||
{
|
||||
m_vecUncompressedBlockCache[ct]->block.compress();
|
||||
}
|
||||
m_vecUncompressedBlockCache.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This function should probably be made internal...
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::initialise(const Region& regValidRegion, uint16_t uBlockSideLength)
|
||||
{
|
||||
//Debug mode validation
|
||||
assert(uBlockSideLength > 0);
|
||||
|
||||
//Release mode validation
|
||||
if(uBlockSideLength == 0)
|
||||
{
|
||||
throw std::invalid_argument("Block side length cannot be zero.");
|
||||
}
|
||||
if(!isPowerOf2(uBlockSideLength))
|
||||
{
|
||||
throw std::invalid_argument("Block side length must be a power of two.");
|
||||
}
|
||||
|
||||
m_uTimestamper = 0;
|
||||
m_uMaxNumberOfUncompressedBlocks = 16;
|
||||
m_uBlockSideLength = uBlockSideLength;
|
||||
m_pUncompressedBorderData = 0;
|
||||
m_uMaxNumberOfBlocksInMemory = 1024;
|
||||
m_v3dLastAccessedBlockPos = Vector3DInt32(0,0,0); //There are no invalid positions, but initially the m_pLastAccessedBlock pointer will be null;
|
||||
m_pLastAccessedBlock = 0;
|
||||
m_bCompressionEnabled = true;
|
||||
|
||||
this->m_regValidRegion = regValidRegion;
|
||||
|
||||
//m_regValidRegionInBlocks.setLowerCorner(this->m_regValidRegion.getLowerCorner() / static_cast<int32_t>(uBlockSideLength));
|
||||
//m_regValidRegionInBlocks.setUpperCorner(this->m_regValidRegion.getUpperCorner() / static_cast<int32_t>(uBlockSideLength));
|
||||
//Compute the block side length
|
||||
m_uBlockSideLength = uBlockSideLength;
|
||||
m_uBlockSideLengthPower = logBase2(m_uBlockSideLength);
|
||||
//m_regValidRegionInBlocks.setLowerX(this->m_regValidRegion.getLowerX() >> m_uBlockSideLengthPower);
|
||||
//m_regValidRegionInBlocks.setLowerY(this->m_regValidRegion.getLowerY() >> m_uBlockSideLengthPower);
|
||||
//m_regValidRegionInBlocks.setLowerZ(this->m_regValidRegion.getLowerZ() >> m_uBlockSideLengthPower);
|
||||
m_regValidRegionInBlocks.setLowerCorner(Vector3DInt32(this->m_regValidRegion.getLowerCorner().getX() >> m_uBlockSideLengthPower, this->m_regValidRegion.getLowerCorner().getY() >> m_uBlockSideLengthPower, this->m_regValidRegion.getLowerCorner().getZ() >> m_uBlockSideLengthPower));
|
||||
//m_regValidRegionInBlocks.setUpperX(this->m_regValidRegion.getUpperX() >> m_uBlockSideLengthPower);
|
||||
//m_regValidRegionInBlocks.setUpperY(this->m_regValidRegion.getUpperY() >> m_uBlockSideLengthPower);
|
||||
//m_regValidRegionInBlocks.setUpperZ(this->m_regValidRegion.getUpperZ() >> m_uBlockSideLengthPower);
|
||||
m_regValidRegionInBlocks.setUpperCorner(Vector3DInt32(this->m_regValidRegion.getUpperCorner().getX() >> m_uBlockSideLengthPower, this->m_regValidRegion.getUpperCorner().getY() >> m_uBlockSideLengthPower, this->m_regValidRegion.getUpperCorner().getZ() >> m_uBlockSideLengthPower));
|
||||
|
||||
setMaxNumberOfUncompressedBlocks(m_uMaxNumberOfUncompressedBlocks);
|
||||
|
||||
//Clear the previous data
|
||||
m_pBlocks.clear();
|
||||
|
||||
//Clear the previous data
|
||||
m_pBlocks.clear();
|
||||
|
||||
//Create the border block
|
||||
m_pUncompressedBorderData = new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength];
|
||||
std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, VoxelType());
|
||||
|
||||
//Other properties we might find useful later
|
||||
this->m_uLongestSideLength = (std::max)((std::max)(this->getWidth(),this->getHeight()),this->getDepth());
|
||||
this->m_uShortestSideLength = (std::min)((std::min)(this->getWidth(),this->getHeight()),this->getDepth());
|
||||
this->m_fDiagonalLength = sqrtf(static_cast<float>(this->getWidth() * this->getWidth() + this->getHeight() * this->getHeight() + this->getDepth() * this->getDepth()));
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::eraseBlock(typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock) const
|
||||
{
|
||||
if(m_funcDataOverflowHandler)
|
||||
{
|
||||
Vector3DInt32 v3dPos = itBlock->first;
|
||||
Vector3DInt32 v3dLower(v3dPos.getX() << m_uBlockSideLengthPower, v3dPos.getY() << m_uBlockSideLengthPower, v3dPos.getZ() << m_uBlockSideLengthPower);
|
||||
Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uBlockSideLength-1, m_uBlockSideLength-1, m_uBlockSideLength-1);
|
||||
|
||||
Region reg(v3dLower, v3dUpper);
|
||||
ConstVolumeProxy<VoxelType> ConstVolumeProxy(*this, reg);
|
||||
|
||||
m_funcDataOverflowHandler(ConstVolumeProxy, reg);
|
||||
}
|
||||
if(m_bCompressionEnabled) {
|
||||
for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
|
||||
{
|
||||
// find the block in the uncompressed cache
|
||||
if(m_vecUncompressedBlockCache[ct] == &(itBlock->second))
|
||||
{
|
||||
// TODO: compression is unneccessary? or will not compressing this cause a memleak?
|
||||
itBlock->second.block.compress();
|
||||
// put last object in cache here
|
||||
m_vecUncompressedBlockCache[ct] = m_vecUncompressedBlockCache.back();
|
||||
// decrease cache size by one since last element is now in here twice
|
||||
m_vecUncompressedBlockCache.resize(m_vecUncompressedBlockCache.size()-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_pBlocks.erase(itBlock);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
bool LargeVolume<VoxelType>::setVoxelAtConst(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const
|
||||
{
|
||||
//We don't have any range checks in this function because it
|
||||
//is a private function only called by the ConstVolumeProxy. The
|
||||
//ConstVolumeProxy takes care of ensuring the range is appropriate.
|
||||
|
||||
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
|
||||
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
|
||||
const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
|
||||
|
||||
const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
|
||||
const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
|
||||
const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
|
||||
|
||||
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||
|
||||
pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
|
||||
|
||||
//Return true to indicate that we modified a voxel.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <typename VoxelType>
|
||||
Block<VoxelType>* LargeVolume<VoxelType>::getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const
|
||||
{
|
||||
Vector3DInt32 v3dBlockPos(uBlockX, uBlockY, uBlockZ);
|
||||
|
||||
//Check if we have the same block as last time, if so there's no need to even update
|
||||
//the time stamp. If we updated it everytime then that would be every time we touched
|
||||
//a voxel, which would overflow a uint32_t and require us to use a uint64_t instead.
|
||||
//This check should also provide a significant speed boost as usually it is true.
|
||||
if((v3dBlockPos == m_v3dLastAccessedBlockPos) && (m_pLastAccessedBlock != 0))
|
||||
{
|
||||
assert(m_pLastAccessedBlock->m_tUncompressedData);
|
||||
return m_pLastAccessedBlock;
|
||||
}
|
||||
|
||||
typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock = m_pBlocks.find(v3dBlockPos);
|
||||
// check whether the block is already loaded
|
||||
if(itBlock == m_pBlocks.end())
|
||||
{
|
||||
//The block is not in the map, so we will have to create a new block and add it.
|
||||
//Before we do so, we might want to dump some existing data to make space. We
|
||||
//Only do this if paging is enabled.
|
||||
if(m_bPagingEnabled)
|
||||
{
|
||||
// check wether another block needs to be unloaded before this one can be loaded
|
||||
if(m_pBlocks.size() == m_uMaxNumberOfBlocksInMemory)
|
||||
{
|
||||
// find the least recently used block
|
||||
typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
|
||||
typename std::map<Vector3DInt32, LoadedBlock >::iterator itUnloadBlock = m_pBlocks.begin();
|
||||
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
|
||||
{
|
||||
if(i->second.timestamp < itUnloadBlock->second.timestamp)
|
||||
{
|
||||
itUnloadBlock = i;
|
||||
}
|
||||
}
|
||||
eraseBlock(itUnloadBlock);
|
||||
}
|
||||
}
|
||||
|
||||
// create the new block
|
||||
LoadedBlock newBlock(m_uBlockSideLength);
|
||||
itBlock = m_pBlocks.insert(std::make_pair(v3dBlockPos, newBlock)).first;
|
||||
|
||||
//We have created the new block. If paging is enabled it should be used to
|
||||
//fill in the required data. Otherwise it is just left in the default state.
|
||||
if(m_bPagingEnabled)
|
||||
{
|
||||
if(m_funcDataRequiredHandler)
|
||||
{
|
||||
// "load" will actually call setVoxel, which will in turn call this function again but the block will be found
|
||||
// so this if(itBlock == m_pBlocks.end()) never is entered
|
||||
//FIXME - can we pass the block around so that we don't have to find it again when we recursively call this function?
|
||||
Vector3DInt32 v3dLower(v3dBlockPos.getX() << m_uBlockSideLengthPower, v3dBlockPos.getY() << m_uBlockSideLengthPower, v3dBlockPos.getZ() << m_uBlockSideLengthPower);
|
||||
Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uBlockSideLength-1, m_uBlockSideLength-1, m_uBlockSideLength-1);
|
||||
Region reg(v3dLower, v3dUpper);
|
||||
ConstVolumeProxy<VoxelType> ConstVolumeProxy(*this, reg);
|
||||
m_funcDataRequiredHandler(ConstVolumeProxy, reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Get the block and mark that we accessed it
|
||||
LoadedBlock& loadedBlock = itBlock->second;
|
||||
loadedBlock.timestamp = ++m_uTimestamper;
|
||||
m_v3dLastAccessedBlockPos = v3dBlockPos;
|
||||
m_pLastAccessedBlock = &(loadedBlock.block);
|
||||
|
||||
if(loadedBlock.block.m_bIsCompressed == false)
|
||||
{
|
||||
assert(m_pLastAccessedBlock->m_tUncompressedData);
|
||||
return m_pLastAccessedBlock;
|
||||
}
|
||||
|
||||
//If we are allowed to compress then check whether we need to
|
||||
if((m_bCompressionEnabled) && (m_vecUncompressedBlockCache.size() == m_uMaxNumberOfUncompressedBlocks))
|
||||
{
|
||||
int32_t leastRecentlyUsedBlockIndex = -1;
|
||||
uint32_t uLeastRecentTimestamp = (std::numeric_limits<uint32_t>::max)();
|
||||
|
||||
//Currently we find the oldest block by iterating over the whole array. Of course we could store the blocks sorted by
|
||||
//timestamp (set, priority_queue, etc) but then we'll need to move them around as the timestamp changes. Can come back
|
||||
//to this if it proves to be a bottleneck (compraed to the cost of actually doing the compression/decompression).
|
||||
for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
|
||||
{
|
||||
if(m_vecUncompressedBlockCache[ct]->timestamp < uLeastRecentTimestamp)
|
||||
{
|
||||
uLeastRecentTimestamp = m_vecUncompressedBlockCache[ct]->timestamp;
|
||||
leastRecentlyUsedBlockIndex = ct;
|
||||
}
|
||||
}
|
||||
|
||||
//Compress the least recently used block.
|
||||
m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex]->block.compress();
|
||||
|
||||
//We don't actually remove any elements from this vector, we
|
||||
//simply change the pointer to point at the new uncompressed bloack.
|
||||
m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex] = &loadedBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vecUncompressedBlockCache.push_back(&loadedBlock);
|
||||
}
|
||||
|
||||
loadedBlock.block.uncompress();
|
||||
|
||||
m_pLastAccessedBlock = &(loadedBlock.block);
|
||||
assert(m_pLastAccessedBlock->m_tUncompressedData);
|
||||
return m_pLastAccessedBlock;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Note: This function needs reviewing for accuracy...
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
float LargeVolume<VoxelType>::calculateCompressionRatio(void)
|
||||
{
|
||||
float fRawSize = m_pBlocks.size() * m_uBlockSideLength * m_uBlockSideLength* m_uBlockSideLength * sizeof(VoxelType);
|
||||
float fCompressedSize = calculateSizeInBytes();
|
||||
return fCompressedSize/fRawSize;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Note: This function needs reviewing for accuracy...
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
uint32_t LargeVolume<VoxelType>::calculateSizeInBytes(void)
|
||||
{
|
||||
uint32_t uSizeInBytes = sizeof(LargeVolume);
|
||||
|
||||
//Memory used by the blocks
|
||||
typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
|
||||
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
|
||||
{
|
||||
//Inaccurate - account for rest of loaded block.
|
||||
uSizeInBytes += i->second.block.calculateSizeInBytes();
|
||||
}
|
||||
|
||||
//Memory used by the block cache.
|
||||
uSizeInBytes += m_vecUncompressedBlockCache.capacity() * sizeof(LoadedBlock);
|
||||
uSizeInBytes += m_vecUncompressedBlockCache.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
|
||||
|
||||
//Memory used by border data.
|
||||
if(m_pUncompressedBorderData)
|
||||
{
|
||||
uSizeInBytes += m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
|
||||
}
|
||||
|
||||
return uSizeInBytes;
|
||||
}
|
||||
|
||||
}
|
||||
|
515
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/LargeVolumeSampler.inl
vendored
Normal file
515
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/LargeVolumeSampler.inl
vendored
Normal file
@ -0,0 +1,515 @@
|
||||
/*******************************************************************************
|
||||
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.
|
||||
*******************************************************************************/
|
||||
|
||||
#define BORDER_LOW(x) ((( x >> this->mVolume->m_uBlockSideLengthPower) << this->mVolume->m_uBlockSideLengthPower) != x)
|
||||
#define BORDER_HIGH(x) ((( (x+1) >> this->mVolume->m_uBlockSideLengthPower) << this->mVolume->m_uBlockSideLengthPower) != (x+1))
|
||||
//#define BORDER_LOW(x) (( x % mVolume->m_uBlockSideLength) != 0)
|
||||
//#define BORDER_HIGH(x) (( x % mVolume->m_uBlockSideLength) != mVolume->m_uBlockSideLength - 1)
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
LargeVolume<VoxelType>::Sampler::Sampler(LargeVolume<VoxelType>* volume)
|
||||
:BaseVolume<VoxelType>::template Sampler< LargeVolume<VoxelType> >(volume)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
LargeVolume<VoxelType>::Sampler::~Sampler()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
typename LargeVolume<VoxelType>::Sampler& LargeVolume<VoxelType>::Sampler::operator=(const typename LargeVolume<VoxelType>::Sampler& rhs)
|
||||
{
|
||||
if(this == &rhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
this->mVolume = rhs.mVolume;
|
||||
this->mXPosInVolume = rhs.mXPosInVolume;
|
||||
this->mYPosInVolume = rhs.mYPosInVolume;
|
||||
this->mZPosInVolume = rhs.mZPosInVolume;
|
||||
mCurrentVoxel = rhs.mCurrentVoxel;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::getSubSampledVoxel(uint8_t uLevel) const
|
||||
{
|
||||
if(uLevel == 0)
|
||||
{
|
||||
return getVoxel();
|
||||
}
|
||||
else if(uLevel == 1)
|
||||
{
|
||||
VoxelType tValue = getVoxel();
|
||||
tValue = (std::min)(tValue, peekVoxel1px0py0pz());
|
||||
tValue = (std::min)(tValue, peekVoxel0px1py0pz());
|
||||
tValue = (std::min)(tValue, peekVoxel1px1py0pz());
|
||||
tValue = (std::min)(tValue, peekVoxel0px0py1pz());
|
||||
tValue = (std::min)(tValue, peekVoxel1px0py1pz());
|
||||
tValue = (std::min)(tValue, peekVoxel0px1py1pz());
|
||||
tValue = (std::min)(tValue, peekVoxel1px1py1pz());
|
||||
return tValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t uSize = 1 << uLevel;
|
||||
|
||||
VoxelType tValue = (std::numeric_limits<VoxelType>::max)();
|
||||
for(uint8_t z = 0; z < uSize; ++z)
|
||||
{
|
||||
for(uint8_t y = 0; y < uSize; ++y)
|
||||
{
|
||||
for(uint8_t x = 0; x < uSize; ++x)
|
||||
{
|
||||
tValue = (std::min)(tValue, this->mVolume->getVoxelAt(this->mXPosInVolume + x, this->mYPosInVolume + y, this->mZPosInVolume + z));
|
||||
}
|
||||
}
|
||||
}
|
||||
return tValue;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::getVoxel(void) const
|
||||
{
|
||||
return *mCurrentVoxel;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::Sampler::setPosition(const Vector3DInt32& v3dNewPos)
|
||||
{
|
||||
setPosition(v3dNewPos.getX(), v3dNewPos.getY(), v3dNewPos.getZ());
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::Sampler::setPosition(int32_t xPos, int32_t yPos, int32_t zPos)
|
||||
{
|
||||
this->mXPosInVolume = xPos;
|
||||
this->mYPosInVolume = yPos;
|
||||
this->mZPosInVolume = zPos;
|
||||
|
||||
const int32_t uXBlock = this->mXPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
const int32_t uYBlock = this->mYPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
const int32_t uZBlock = this->mZPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
|
||||
const uint16_t uXPosInBlock = static_cast<uint16_t>(this->mXPosInVolume - (uXBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
const uint16_t uYPosInBlock = static_cast<uint16_t>(this->mYPosInVolume - (uYBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
const uint16_t uZPosInBlock = static_cast<uint16_t>(this->mZPosInVolume - (uZBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
|
||||
const uint32_t uVoxelIndexInBlock = uXPosInBlock +
|
||||
uYPosInBlock * this->mVolume->m_uBlockSideLength +
|
||||
uZPosInBlock * this->mVolume->m_uBlockSideLength * this->mVolume->m_uBlockSideLength;
|
||||
|
||||
if(this->mVolume->m_regValidRegionInBlocks.containsPoint(Vector3DInt32(uXBlock, uYBlock, uZBlock)))
|
||||
{
|
||||
Block<VoxelType>* pUncompressedCurrentBlock = this->mVolume->getUncompressedBlock(uXBlock, uYBlock, uZBlock);
|
||||
|
||||
mCurrentVoxel = pUncompressedCurrentBlock->m_tUncompressedData + uVoxelIndexInBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentVoxel = this->mVolume->m_pUncompressedBorderData + uVoxelIndexInBlock;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
bool LargeVolume<VoxelType>::Sampler::setVoxel(VoxelType tValue)
|
||||
{
|
||||
//*mCurrentVoxel = tValue;
|
||||
//Need to think what effect this has on any existing iterators.
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::Sampler::movePositiveX(void)
|
||||
{
|
||||
//Note the *pre* increament here
|
||||
if((++this->mXPosInVolume) % this->mVolume->m_uBlockSideLength != 0)
|
||||
{
|
||||
//No need to compute new block.
|
||||
++mCurrentVoxel;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this.
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::Sampler::movePositiveY(void)
|
||||
{
|
||||
//Note the *pre* increament here
|
||||
if((++this->mYPosInVolume) % this->mVolume->m_uBlockSideLength != 0)
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel += this->mVolume->m_uBlockSideLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this.
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::Sampler::movePositiveZ(void)
|
||||
{
|
||||
//Note the *pre* increament here
|
||||
if((++this->mZPosInVolume) % this->mVolume->m_uBlockSideLength != 0)
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel += this->mVolume->m_uBlockSideLength * this->mVolume->m_uBlockSideLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this.
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::Sampler::moveNegativeX(void)
|
||||
{
|
||||
//Note the *post* decreament here
|
||||
if((this->mXPosInVolume--) % this->mVolume->m_uBlockSideLength != 0)
|
||||
{
|
||||
//No need to compute new block.
|
||||
--mCurrentVoxel;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this.
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::Sampler::moveNegativeY(void)
|
||||
{
|
||||
//Note the *post* decreament here
|
||||
if((this->mYPosInVolume--) % this->mVolume->m_uBlockSideLength != 0)
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel -= this->mVolume->m_uBlockSideLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this.
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void LargeVolume<VoxelType>::Sampler::moveNegativeZ(void)
|
||||
{
|
||||
//Note the *post* decreament here
|
||||
if((this->mZPosInVolume--) % this->mVolume->m_uBlockSideLength != 0)
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel -= this->mVolume->m_uBlockSideLength * this->mVolume->m_uBlockSideLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this.
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx0py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx0py0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx0py1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx1py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx1py0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1nx1py1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px0py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px0py0pz(void) const
|
||||
{
|
||||
return *mCurrentVoxel;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px0py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px1py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px1py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel0px1py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px0py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px0py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px0py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px1py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px1py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType LargeVolume<VoxelType>::Sampler::peekVoxel1px1py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
}
|
||||
}
|
||||
|
||||
#undef BORDER_LOW
|
||||
#undef BORDER_HIGH
|
63
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Log.h
vendored
Normal file
63
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Log.h
vendored
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.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __PolyVox_Log_H__
|
||||
#define __PolyVox_Log_H__
|
||||
|
||||
#include "Impl/TypeDef.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
//Note: The functions in this file are not for the user to call - they are
|
||||
//intended for internal use only. The only exception is that you may set the
|
||||
//logHandler pointer to point at your own handling funtion for printing, etc.
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Log levels for filtering logging events
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
enum LogSeverity
|
||||
{
|
||||
LS_DEBUG, ///< Only displayed if it is a debug build
|
||||
LS_INFO,
|
||||
LS_WARN,
|
||||
LS_ERROR
|
||||
};
|
||||
|
||||
POLYVOX_API extern void (*logHandler)(std::string, int severity);
|
||||
}
|
||||
|
||||
//Debug severity messages are only used if we are a debug build
|
||||
#ifdef _DEBUG
|
||||
#define POLYVOX_LOG_DEBUG(message) if(logHandler){logHandler(message, LS_DEBUG);}
|
||||
#else
|
||||
#define POLYVOX_LOG_DEBUG(message)
|
||||
#endif
|
||||
|
||||
//Other severity levels work in both debug and release
|
||||
#define POLYVOX_LOG_INFO(message) if(logHandler){logHandler(message, LS_INFO);}
|
||||
#define POLYVOX_LOG_WARN(message) if(logHandler){logHandler(message, LS_WARN);}
|
||||
#define POLYVOX_LOG_ERROR(message) if(logHandler){logHandler(message, LS_ERROR);}
|
||||
|
||||
#endif
|
60
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/LowPassFilter.h
vendored
Normal file
60
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/LowPassFilter.h
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
/*******************************************************************************
|
||||
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_LowPassFilter_H__
|
||||
#define __PolyVox_LowPassFilter_H__
|
||||
|
||||
#include "PolyVoxCore/IteratorController.h"
|
||||
#include "PolyVoxCore/RawVolume.h" //Is this desirable?
|
||||
#include "PolyVoxCore/Region.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template< typename SrcVolumeType, typename DstVolumeType, typename AccumulationType>
|
||||
class LowPassFilter
|
||||
{
|
||||
public:
|
||||
LowPassFilter(SrcVolumeType* pVolSrc, Region regSrc, DstVolumeType* pVolDst, Region regDst, uint32_t uKernelSize);
|
||||
|
||||
void execute();
|
||||
void executeSAT();
|
||||
|
||||
private:
|
||||
//Source data
|
||||
SrcVolumeType* m_pVolSrc;
|
||||
Region m_regSrc;
|
||||
|
||||
//Destination data
|
||||
DstVolumeType* m_pVolDst;
|
||||
Region m_regDst;
|
||||
|
||||
//Kernel size
|
||||
uint32_t m_uKernelSize;
|
||||
};
|
||||
|
||||
}//namespace PolyVox
|
||||
|
||||
#include "PolyVoxCore/LowPassFilter.inl"
|
||||
|
||||
#endif //__PolyVox_LowPassFilter_H__
|
||||
|
254
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/LowPassFilter.inl
vendored
Normal file
254
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/LowPassFilter.inl
vendored
Normal file
@ -0,0 +1,254 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/**
|
||||
* \param pVolSrc
|
||||
* \param regSrc
|
||||
* \param[out] pVolDst
|
||||
* \param regDst
|
||||
* \param uKernelSize
|
||||
*/
|
||||
template< typename SrcVolumeType, typename DstVolumeType, typename AccumulationType>
|
||||
LowPassFilter<SrcVolumeType, DstVolumeType, AccumulationType>::LowPassFilter(SrcVolumeType* pVolSrc, Region regSrc, DstVolumeType* pVolDst, Region regDst, uint32_t uKernelSize)
|
||||
:m_pVolSrc(pVolSrc)
|
||||
,m_regSrc(regSrc)
|
||||
,m_pVolDst(pVolDst)
|
||||
,m_regDst(regDst)
|
||||
,m_uKernelSize(uKernelSize)
|
||||
{
|
||||
//Kernel size must be at least three
|
||||
assert(m_uKernelSize >= 3);
|
||||
m_uKernelSize = std::max(m_uKernelSize, static_cast<uint32_t>(3)); //For release builds
|
||||
|
||||
//Kernel size must be odd
|
||||
assert(m_uKernelSize % 2 == 1);
|
||||
if(m_uKernelSize % 2 == 0) //For release builds
|
||||
{
|
||||
m_uKernelSize++;
|
||||
}
|
||||
}
|
||||
|
||||
template< typename SrcVolumeType, typename DstVolumeType, typename AccumulationType>
|
||||
void LowPassFilter<SrcVolumeType, DstVolumeType, AccumulationType>::execute()
|
||||
{
|
||||
int32_t iSrcMinX = m_regSrc.getLowerCorner().getX();
|
||||
int32_t iSrcMinY = m_regSrc.getLowerCorner().getY();
|
||||
int32_t iSrcMinZ = m_regSrc.getLowerCorner().getZ();
|
||||
|
||||
int32_t iSrcMaxX = m_regSrc.getUpperCorner().getX();
|
||||
int32_t iSrcMaxY = m_regSrc.getUpperCorner().getY();
|
||||
int32_t iSrcMaxZ = m_regSrc.getUpperCorner().getZ();
|
||||
|
||||
int32_t iDstMinX = m_regDst.getLowerCorner().getX();
|
||||
int32_t iDstMinY = m_regDst.getLowerCorner().getY();
|
||||
int32_t iDstMinZ = m_regDst.getLowerCorner().getZ();
|
||||
|
||||
//int32_t iDstMaxX = m_regDst.getUpperCorner().getX();
|
||||
//int32_t iDstMaxY = m_regDst.getUpperCorner().getY();
|
||||
//int32_t iDstMaxZ = m_regDst.getUpperCorner().getZ();
|
||||
|
||||
typename SrcVolumeType::Sampler srcSampler(m_pVolSrc);
|
||||
|
||||
for(int32_t iSrcZ = iSrcMinZ, iDstZ = iDstMinZ; iSrcZ <= iSrcMaxZ; iSrcZ++, iDstZ++)
|
||||
{
|
||||
for(int32_t iSrcY = iSrcMinY, iDstY = iDstMinY; iSrcY <= iSrcMaxY; iSrcY++, iDstY++)
|
||||
{
|
||||
for(int32_t iSrcX = iSrcMinX, iDstX = iDstMinX; iSrcX <= iSrcMaxX; iSrcX++, iDstX++)
|
||||
{
|
||||
AccumulationType tSrcVoxel(0);
|
||||
srcSampler.setPosition(iSrcX, iSrcY, iSrcZ);
|
||||
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1ny1nz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1ny0pz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1ny1pz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx0py1nz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx0py0pz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx0py1pz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1py1nz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1py0pz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1py1pz());
|
||||
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1ny1nz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1ny0pz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1ny1pz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px0py1nz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px0py0pz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px0py1pz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1py1nz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1py0pz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1py1pz());
|
||||
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1ny1nz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1ny0pz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1ny1pz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px0py1nz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px0py0pz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px0py1pz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1py1nz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1py0pz());
|
||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1py1pz());
|
||||
|
||||
tSrcVoxel /= 27;
|
||||
|
||||
//tSrcVoxel.setDensity(uDensity);
|
||||
m_pVolDst->setVoxelAt(iSrcX, iSrcY, iSrcZ, static_cast<typename DstVolumeType::VoxelType>(tSrcVoxel));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template< typename SrcVolumeType, typename DstVolumeType, typename AccumulationType>
|
||||
void LowPassFilter<SrcVolumeType, DstVolumeType, AccumulationType>::executeSAT()
|
||||
{
|
||||
const uint32_t border = (m_uKernelSize - 1) / 2;
|
||||
|
||||
Vector3DInt32 satLowerCorner = m_regSrc.getLowerCorner() - Vector3DInt32(border, border, border);
|
||||
Vector3DInt32 satUpperCorner = m_regSrc.getUpperCorner() + Vector3DInt32(border, border, border);
|
||||
|
||||
//Use floats for the SAT volume to ensure it works with negative
|
||||
//densities and with both integral and floating point input volumes.
|
||||
RawVolume<AccumulationType> satVolume(Region(satLowerCorner, satUpperCorner));
|
||||
|
||||
//Clear to zeros (necessary?)
|
||||
//FIXME - use Volume::fill() method. Implemented in base class as below
|
||||
//but with optimised implementations in subclasses?
|
||||
for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
|
||||
{
|
||||
for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
|
||||
{
|
||||
for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
|
||||
{
|
||||
satVolume.setVoxelAt(x,y,z,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typename RawVolume<AccumulationType>::Sampler satVolumeIter(&satVolume);
|
||||
|
||||
IteratorController<typename RawVolume<AccumulationType>::Sampler> satIterCont;
|
||||
satIterCont.m_regValid = Region(satLowerCorner, satUpperCorner);
|
||||
satIterCont.m_Iter = &satVolumeIter;
|
||||
satIterCont.reset();
|
||||
|
||||
typename SrcVolumeType::Sampler srcVolumeIter(m_pVolSrc);
|
||||
|
||||
IteratorController<typename SrcVolumeType::Sampler> srcIterCont;
|
||||
srcIterCont.m_regValid = Region(satLowerCorner, satUpperCorner);
|
||||
srcIterCont.m_Iter = &srcVolumeIter;
|
||||
srcIterCont.reset();
|
||||
|
||||
do
|
||||
{
|
||||
AccumulationType previousSum = static_cast<AccumulationType>(satVolumeIter.peekVoxel1nx0py0pz());
|
||||
AccumulationType currentVal = static_cast<AccumulationType>(srcVolumeIter.getVoxel());
|
||||
|
||||
satVolumeIter.setVoxel(previousSum + currentVal);
|
||||
|
||||
srcIterCont.moveForward();
|
||||
|
||||
}while(satIterCont.moveForward());
|
||||
|
||||
//Build SAT in three passes
|
||||
/*for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
|
||||
{
|
||||
for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
|
||||
{
|
||||
for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
|
||||
{
|
||||
AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x-1,y,z));
|
||||
AccumulationType currentVal = static_cast<AccumulationType>(m_pVolSrc->getVoxelAt(x,y,z));
|
||||
|
||||
satVolume.setVoxelAt(x,y,z,previousSum + currentVal);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
|
||||
{
|
||||
for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
|
||||
{
|
||||
for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
|
||||
{
|
||||
AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x,y-1,z));
|
||||
AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x,y,z));
|
||||
|
||||
satVolume.setVoxelAt(x,y,z,previousSum + currentSum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
|
||||
{
|
||||
for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
|
||||
{
|
||||
for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
|
||||
{
|
||||
AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x,y,z-1));
|
||||
AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x,y,z));
|
||||
|
||||
satVolume.setVoxelAt(x,y,z,previousSum + currentSum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Now compute the average
|
||||
const Vector3DInt32& v3dDstLowerCorner = m_regDst.getLowerCorner();
|
||||
const Vector3DInt32& v3dDstUpperCorner = m_regDst.getUpperCorner();
|
||||
|
||||
const Vector3DInt32& v3dSrcLowerCorner = m_regSrc.getLowerCorner();
|
||||
|
||||
for(int32_t iDstZ = v3dDstLowerCorner.getZ(), iSrcZ = v3dSrcLowerCorner.getZ(); iDstZ <= v3dDstUpperCorner.getZ(); iDstZ++, iSrcZ++)
|
||||
{
|
||||
for(int32_t iDstY = v3dDstLowerCorner.getY(), iSrcY = v3dSrcLowerCorner.getY(); iDstY <= v3dDstUpperCorner.getY(); iDstY++, iSrcY++)
|
||||
{
|
||||
for(int32_t iDstX = v3dDstLowerCorner.getX(), iSrcX = v3dSrcLowerCorner.getX(); iDstX <= v3dDstUpperCorner.getX(); iDstX++, iSrcX++)
|
||||
{
|
||||
int32_t satLowerX = iSrcX - border - 1;
|
||||
int32_t satLowerY = iSrcY - border - 1;
|
||||
int32_t satLowerZ = iSrcZ - border - 1;
|
||||
|
||||
int32_t satUpperX = iSrcX + border;
|
||||
int32_t satUpperY = iSrcY + border;
|
||||
int32_t satUpperZ = iSrcZ + border;
|
||||
|
||||
AccumulationType a = satVolume.getVoxelAt(satLowerX,satLowerY,satLowerZ);
|
||||
AccumulationType b = satVolume.getVoxelAt(satUpperX,satLowerY,satLowerZ);
|
||||
AccumulationType c = satVolume.getVoxelAt(satLowerX,satUpperY,satLowerZ);
|
||||
AccumulationType d = satVolume.getVoxelAt(satUpperX,satUpperY,satLowerZ);
|
||||
AccumulationType e = satVolume.getVoxelAt(satLowerX,satLowerY,satUpperZ);
|
||||
AccumulationType f = satVolume.getVoxelAt(satUpperX,satLowerY,satUpperZ);
|
||||
AccumulationType g = satVolume.getVoxelAt(satLowerX,satUpperY,satUpperZ);
|
||||
AccumulationType h = satVolume.getVoxelAt(satUpperX,satUpperY,satUpperZ);
|
||||
|
||||
AccumulationType sum = h+c-d-g-f-a+b+e;
|
||||
uint32_t sideLength = border * 2 + 1;
|
||||
AccumulationType average = sum / (sideLength*sideLength*sideLength);
|
||||
|
||||
m_pVolDst->setVoxelAt(iDstX, iDstY, iDstZ, static_cast<typename DstVolumeType::VoxelType>(average));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
210
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h
vendored
Normal file
210
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
/*******************************************************************************
|
||||
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_SurfaceExtractor_H__
|
||||
#define __PolyVox_SurfaceExtractor_H__
|
||||
|
||||
#include "Impl/MarchingCubesTables.h"
|
||||
#include "Impl/TypeDef.h"
|
||||
|
||||
#include "PolyVoxCore/Array.h"
|
||||
#include "PolyVoxCore/SurfaceMesh.h"
|
||||
#include "PolyVoxCore/DefaultMarchingCubesController.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template< typename VolumeType, typename Controller = DefaultMarchingCubesController<typename VolumeType::VoxelType> >
|
||||
class MarchingCubesSurfaceExtractor
|
||||
{
|
||||
public:
|
||||
MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result, Controller controller = Controller());
|
||||
|
||||
void execute();
|
||||
|
||||
private:
|
||||
//Compute the cell bitmask for a particular slice in z.
|
||||
template<bool isPrevZAvail>
|
||||
uint32_t computeBitmaskForSlice(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask);
|
||||
|
||||
//Compute the cell bitmask for a given cell.
|
||||
template<bool isPrevXAvail, bool isPrevYAvail, bool isPrevZAvail>
|
||||
void computeBitmaskForCell(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask, uint32_t uXRegSpace, uint32_t uYRegSpace);
|
||||
|
||||
//Use the cell bitmasks to generate all the vertices needed for that slice
|
||||
void generateVerticesForSlice(const Array2DUint8& pCurrentBitmask,
|
||||
Array2DInt32& m_pCurrentVertexIndicesX,
|
||||
Array2DInt32& m_pCurrentVertexIndicesY,
|
||||
Array2DInt32& m_pCurrentVertexIndicesZ);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: These two functions are in the .h file rather than the .inl due to an apparent bug in VC2010.
|
||||
//See http://stackoverflow.com/questions/1484885/strange-vc-compile-error-c2244 for details.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Vector3DFloat computeCentralDifferenceGradient(const typename VolumeType::Sampler& volIter)
|
||||
{
|
||||
//FIXME - Should actually use DensityType here, both in principle and because the maths may be
|
||||
//faster (and to reduce casts). So it would be good to add a way to get DensityType from a voxel.
|
||||
//But watch out for when the DensityType is unsigned and the difference could be negative.
|
||||
float voxel1nx = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx0py0pz()));
|
||||
float voxel1px = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px0py0pz()));
|
||||
|
||||
float voxel1ny = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1ny0pz()));
|
||||
float voxel1py = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1py0pz()));
|
||||
|
||||
float voxel1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px0py1nz()));
|
||||
float voxel1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px0py1pz()));
|
||||
|
||||
return Vector3DFloat
|
||||
(
|
||||
voxel1nx - voxel1px,
|
||||
voxel1ny - voxel1py,
|
||||
voxel1nz - voxel1pz
|
||||
);
|
||||
}
|
||||
|
||||
Vector3DFloat computeSobelGradient(const typename VolumeType::Sampler& volIter)
|
||||
{
|
||||
static const int weights[3][3][3] = { { {2,3,2}, {3,6,3}, {2,3,2} }, {
|
||||
{3,6,3}, {6,0,6}, {3,6,3} }, { {2,3,2}, {3,6,3}, {2,3,2} } };
|
||||
|
||||
//FIXME - Should actually use DensityType here, both in principle and because the maths may be
|
||||
//faster (and to reduce casts). So it would be good to add a way to get DensityType from a voxel.
|
||||
//But watch out for when the DensityType is unsigned and the difference could be negative.
|
||||
const float pVoxel1nx1ny1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1ny1nz()));
|
||||
const float pVoxel1nx1ny0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1ny0pz()));
|
||||
const float pVoxel1nx1ny1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1ny1pz()));
|
||||
const float pVoxel1nx0py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx0py1nz()));
|
||||
const float pVoxel1nx0py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx0py0pz()));
|
||||
const float pVoxel1nx0py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx0py1pz()));
|
||||
const float pVoxel1nx1py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1py1nz()));
|
||||
const float pVoxel1nx1py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1py0pz()));
|
||||
const float pVoxel1nx1py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1py1pz()));
|
||||
|
||||
const float pVoxel0px1ny1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1ny1nz()));
|
||||
const float pVoxel0px1ny0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1ny0pz()));
|
||||
const float pVoxel0px1ny1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1ny1pz()));
|
||||
const float pVoxel0px0py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px0py1nz()));
|
||||
//const float pVoxel0px0py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px0py0pz()));
|
||||
const float pVoxel0px0py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px0py1pz()));
|
||||
const float pVoxel0px1py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1py1nz()));
|
||||
const float pVoxel0px1py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1py0pz()));
|
||||
const float pVoxel0px1py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1py1pz()));
|
||||
|
||||
const float pVoxel1px1ny1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1ny1nz()));
|
||||
const float pVoxel1px1ny0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1ny0pz()));
|
||||
const float pVoxel1px1ny1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1ny1pz()));
|
||||
const float pVoxel1px0py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px0py1nz()));
|
||||
const float pVoxel1px0py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px0py0pz()));
|
||||
const float pVoxel1px0py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px0py1pz()));
|
||||
const float pVoxel1px1py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1py1nz()));
|
||||
const float pVoxel1px1py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1py0pz()));
|
||||
const float pVoxel1px1py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1py1pz()));
|
||||
|
||||
const float xGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
|
||||
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
|
||||
pVoxel1nx1ny1pz - weights[0][1][0] * pVoxel1nx0py1nz -
|
||||
weights[1][1][0] * pVoxel1nx0py0pz - weights[2][1][0] *
|
||||
pVoxel1nx0py1pz - weights[0][2][0] * pVoxel1nx1py1nz -
|
||||
weights[1][2][0] * pVoxel1nx1py0pz - weights[2][2][0] *
|
||||
pVoxel1nx1py1pz + weights[0][0][2] * pVoxel1px1ny1nz +
|
||||
weights[1][0][2] * pVoxel1px1ny0pz + weights[2][0][2] *
|
||||
pVoxel1px1ny1pz + weights[0][1][2] * pVoxel1px0py1nz +
|
||||
weights[1][1][2] * pVoxel1px0py0pz + weights[2][1][2] *
|
||||
pVoxel1px0py1pz + weights[0][2][2] * pVoxel1px1py1nz +
|
||||
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
|
||||
pVoxel1px1py1pz);
|
||||
|
||||
const float yGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
|
||||
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
|
||||
pVoxel1nx1ny1pz + weights[0][2][0] * pVoxel1nx1py1nz +
|
||||
weights[1][2][0] * pVoxel1nx1py0pz + weights[2][2][0] *
|
||||
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz -
|
||||
weights[1][0][1] * pVoxel0px1ny0pz - weights[2][0][1] *
|
||||
pVoxel0px1ny1pz + weights[0][2][1] * pVoxel0px1py1nz +
|
||||
weights[1][2][1] * pVoxel0px1py0pz + weights[2][2][1] *
|
||||
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz -
|
||||
weights[1][0][2] * pVoxel1px1ny0pz - weights[2][0][2] *
|
||||
pVoxel1px1ny1pz + weights[0][2][2] * pVoxel1px1py1nz +
|
||||
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
|
||||
pVoxel1px1py1pz);
|
||||
|
||||
const float zGrad(- weights[0][0][0] * pVoxel1nx1ny1nz +
|
||||
weights[2][0][0] * pVoxel1nx1ny1pz - weights[0][1][0] *
|
||||
pVoxel1nx0py1nz + weights[2][1][0] * pVoxel1nx0py1pz -
|
||||
weights[0][2][0] * pVoxel1nx1py1nz + weights[2][2][0] *
|
||||
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz +
|
||||
weights[2][0][1] * pVoxel0px1ny1pz - weights[0][1][1] *
|
||||
pVoxel0px0py1nz + weights[2][1][1] * pVoxel0px0py1pz -
|
||||
weights[0][2][1] * pVoxel0px1py1nz + weights[2][2][1] *
|
||||
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz +
|
||||
weights[2][0][2] * pVoxel1px1ny1pz - weights[0][1][2] *
|
||||
pVoxel1px0py1nz + weights[2][1][2] * pVoxel1px0py1pz -
|
||||
weights[0][2][2] * pVoxel1px1py1nz + weights[2][2][2] *
|
||||
pVoxel1px1py1pz);
|
||||
|
||||
//Note: The above actually give gradients going from low density to high density.
|
||||
//For our normals we want the the other way around, so we switch the components as we return them.
|
||||
return Vector3DFloat(-xGrad,-yGrad,-zGrad);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// End of compiler bug workaroumd.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Use the cell bitmasks to generate all the indices needed for that slice
|
||||
void generateIndicesForSlice(const Array2DUint8& pPreviousBitmask,
|
||||
const Array2DInt32& m_pPreviousVertexIndicesX,
|
||||
const Array2DInt32& m_pPreviousVertexIndicesY,
|
||||
const Array2DInt32& m_pPreviousVertexIndicesZ,
|
||||
const Array2DInt32& m_pCurrentVertexIndicesX,
|
||||
const Array2DInt32& m_pCurrentVertexIndicesY);
|
||||
|
||||
//The volume data and a sampler to access it.
|
||||
VolumeType* m_volData;
|
||||
typename VolumeType::Sampler m_sampVolume;
|
||||
|
||||
//Used to return the number of cells in a slice which contain triangles.
|
||||
uint32_t m_uNoOfOccupiedCells;
|
||||
|
||||
//The surface patch we are currently filling.
|
||||
SurfaceMesh<PositionMaterialNormal>* m_meshCurrent;
|
||||
|
||||
//Information about the region we are currently processing
|
||||
Region m_regSizeInVoxels;
|
||||
Region m_regSizeInCells;
|
||||
/*Region m_regSizeInVoxelsCropped;
|
||||
Region m_regSizeInVoxelsUncropped;
|
||||
Region m_regVolumeCropped;*/
|
||||
Region m_regSlicePrevious;
|
||||
Region m_regSliceCurrent;
|
||||
|
||||
//Our threshold value
|
||||
typename Controller::DensityType m_tThreshold;
|
||||
|
||||
//Used to convert arbitrary voxel types in densities and materials.
|
||||
Controller m_controller;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.inl"
|
||||
|
||||
#endif
|
622
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl
vendored
Normal file
622
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl
vendored
Normal file
@ -0,0 +1,622 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template<typename VolumeType, typename Controller>
|
||||
MarchingCubesSurfaceExtractor<VolumeType, Controller>::MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result, Controller controller)
|
||||
:m_volData(volData)
|
||||
,m_sampVolume(volData)
|
||||
,m_meshCurrent(result)
|
||||
,m_regSizeInVoxels(region)
|
||||
{
|
||||
//m_regSizeInVoxels.cropTo(m_volData->getEnclosingRegion());
|
||||
m_regSizeInCells = m_regSizeInVoxels;
|
||||
m_regSizeInCells.setUpperCorner(m_regSizeInCells.getUpperCorner() - Vector3DInt32(1,1,1));
|
||||
|
||||
m_controller = controller;
|
||||
m_tThreshold = m_controller.getThreshold();
|
||||
}
|
||||
|
||||
template<typename VolumeType, typename Controller>
|
||||
void MarchingCubesSurfaceExtractor<VolumeType, Controller>::execute()
|
||||
{
|
||||
m_meshCurrent->clear();
|
||||
|
||||
uint32_t uArrayWidth = m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 1;
|
||||
uint32_t uArrayHeight = m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 1;
|
||||
uint32_t arraySizes[2]= {uArrayWidth, uArrayHeight}; // Array dimensions
|
||||
|
||||
//For edge indices
|
||||
Array2DInt32 m_pPreviousVertexIndicesX(arraySizes);
|
||||
Array2DInt32 m_pPreviousVertexIndicesY(arraySizes);
|
||||
Array2DInt32 m_pPreviousVertexIndicesZ(arraySizes);
|
||||
Array2DInt32 m_pCurrentVertexIndicesX(arraySizes);
|
||||
Array2DInt32 m_pCurrentVertexIndicesY(arraySizes);
|
||||
Array2DInt32 m_pCurrentVertexIndicesZ(arraySizes);
|
||||
|
||||
Array2DUint8 pPreviousBitmask(arraySizes);
|
||||
Array2DUint8 pCurrentBitmask(arraySizes);
|
||||
|
||||
//Create a region corresponding to the first slice
|
||||
m_regSlicePrevious = m_regSizeInVoxels;
|
||||
Vector3DInt32 v3dUpperCorner = m_regSlicePrevious.getUpperCorner();
|
||||
v3dUpperCorner.setZ(m_regSlicePrevious.getLowerCorner().getZ()); //Set the upper z to the lower z to make it one slice thick.
|
||||
m_regSlicePrevious.setUpperCorner(v3dUpperCorner);
|
||||
m_regSliceCurrent = m_regSlicePrevious;
|
||||
|
||||
uint32_t uNoOfNonEmptyCellsForSlice0 = 0;
|
||||
uint32_t uNoOfNonEmptyCellsForSlice1 = 0;
|
||||
|
||||
//Process the first slice (previous slice not available)
|
||||
computeBitmaskForSlice<false>(pPreviousBitmask, pCurrentBitmask);
|
||||
uNoOfNonEmptyCellsForSlice1 = m_uNoOfOccupiedCells;
|
||||
|
||||
if(uNoOfNonEmptyCellsForSlice1 != 0)
|
||||
{
|
||||
memset(m_pCurrentVertexIndicesX.getRawData(), 0xff, m_pCurrentVertexIndicesX.getNoOfElements() * 4);
|
||||
memset(m_pCurrentVertexIndicesY.getRawData(), 0xff, m_pCurrentVertexIndicesY.getNoOfElements() * 4);
|
||||
memset(m_pCurrentVertexIndicesZ.getRawData(), 0xff, m_pCurrentVertexIndicesZ.getNoOfElements() * 4);
|
||||
generateVerticesForSlice(pCurrentBitmask, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY, m_pCurrentVertexIndicesZ);
|
||||
}
|
||||
|
||||
std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1);
|
||||
pPreviousBitmask.swap(pCurrentBitmask);
|
||||
m_pPreviousVertexIndicesX.swap(m_pCurrentVertexIndicesX);
|
||||
m_pPreviousVertexIndicesY.swap(m_pCurrentVertexIndicesY);
|
||||
m_pPreviousVertexIndicesZ.swap(m_pCurrentVertexIndicesZ);
|
||||
|
||||
m_regSlicePrevious = m_regSliceCurrent;
|
||||
m_regSliceCurrent.shift(Vector3DInt32(0,0,1));
|
||||
|
||||
//Process the other slices (previous slice is available)
|
||||
for(int32_t uSlice = 1; uSlice <= m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ(); uSlice++)
|
||||
{
|
||||
computeBitmaskForSlice<true>(pPreviousBitmask, pCurrentBitmask);
|
||||
uNoOfNonEmptyCellsForSlice1 = m_uNoOfOccupiedCells;
|
||||
|
||||
if(uNoOfNonEmptyCellsForSlice1 != 0)
|
||||
{
|
||||
memset(m_pCurrentVertexIndicesX.getRawData(), 0xff, m_pCurrentVertexIndicesX.getNoOfElements() * 4);
|
||||
memset(m_pCurrentVertexIndicesY.getRawData(), 0xff, m_pCurrentVertexIndicesY.getNoOfElements() * 4);
|
||||
memset(m_pCurrentVertexIndicesZ.getRawData(), 0xff, m_pCurrentVertexIndicesZ.getNoOfElements() * 4);
|
||||
generateVerticesForSlice(pCurrentBitmask, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY, m_pCurrentVertexIndicesZ);
|
||||
}
|
||||
|
||||
if((uNoOfNonEmptyCellsForSlice0 != 0) || (uNoOfNonEmptyCellsForSlice1 != 0))
|
||||
{
|
||||
generateIndicesForSlice(pPreviousBitmask, m_pPreviousVertexIndicesX, m_pPreviousVertexIndicesY, m_pPreviousVertexIndicesZ, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY);
|
||||
}
|
||||
|
||||
std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1);
|
||||
pPreviousBitmask.swap(pCurrentBitmask);
|
||||
m_pPreviousVertexIndicesX.swap(m_pCurrentVertexIndicesX);
|
||||
m_pPreviousVertexIndicesY.swap(m_pCurrentVertexIndicesY);
|
||||
m_pPreviousVertexIndicesZ.swap(m_pCurrentVertexIndicesZ);
|
||||
|
||||
m_regSlicePrevious = m_regSliceCurrent;
|
||||
m_regSliceCurrent.shift(Vector3DInt32(0,0,1));
|
||||
}
|
||||
|
||||
m_meshCurrent->m_Region = m_regSizeInVoxels;
|
||||
|
||||
m_meshCurrent->m_vecLodRecords.clear();
|
||||
LodRecord lodRecord;
|
||||
lodRecord.beginIndex = 0;
|
||||
lodRecord.endIndex = m_meshCurrent->getNoOfIndices();
|
||||
m_meshCurrent->m_vecLodRecords.push_back(lodRecord);
|
||||
}
|
||||
|
||||
template<typename VolumeType, typename Controller>
|
||||
template<bool isPrevZAvail>
|
||||
uint32_t MarchingCubesSurfaceExtractor<VolumeType, Controller>::computeBitmaskForSlice(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask)
|
||||
{
|
||||
m_uNoOfOccupiedCells = 0;
|
||||
|
||||
const int32_t iMaxXVolSpace = m_regSliceCurrent.getUpperCorner().getX();
|
||||
const int32_t iMaxYVolSpace = m_regSliceCurrent.getUpperCorner().getY();
|
||||
|
||||
int32_t iZVolSpace = m_regSliceCurrent.getLowerCorner().getZ();
|
||||
|
||||
//Process the lower left corner
|
||||
int32_t iYVolSpace = m_regSliceCurrent.getLowerCorner().getY();
|
||||
int32_t iXVolSpace = m_regSliceCurrent.getLowerCorner().getX();
|
||||
|
||||
uint32_t uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
|
||||
uint32_t uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
|
||||
|
||||
m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace);
|
||||
computeBitmaskForCell<false, false, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace);
|
||||
|
||||
//Process the edge where x is minimal.
|
||||
iXVolSpace = m_regSliceCurrent.getLowerCorner().getX();
|
||||
m_sampVolume.setPosition(iXVolSpace, m_regSliceCurrent.getLowerCorner().getY(), iZVolSpace);
|
||||
for(iYVolSpace = m_regSliceCurrent.getLowerCorner().getY() + 1; iYVolSpace <= iMaxYVolSpace; iYVolSpace++)
|
||||
{
|
||||
uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
|
||||
uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
|
||||
|
||||
m_sampVolume.movePositiveY();
|
||||
|
||||
computeBitmaskForCell<false, true, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace);
|
||||
}
|
||||
|
||||
//Process the edge where y is minimal.
|
||||
iYVolSpace = m_regSliceCurrent.getLowerCorner().getY();
|
||||
m_sampVolume.setPosition(m_regSliceCurrent.getLowerCorner().getX(), iYVolSpace, iZVolSpace);
|
||||
for(iXVolSpace = m_regSliceCurrent.getLowerCorner().getX() + 1; iXVolSpace <= iMaxXVolSpace; iXVolSpace++)
|
||||
{
|
||||
uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
|
||||
uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
|
||||
|
||||
m_sampVolume.movePositiveX();
|
||||
|
||||
computeBitmaskForCell<true, false, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace);
|
||||
}
|
||||
|
||||
//Process all remaining elemnents of the slice. In this case, previous x and y values are always available
|
||||
for(iYVolSpace = m_regSliceCurrent.getLowerCorner().getY() + 1; iYVolSpace <= iMaxYVolSpace; iYVolSpace++)
|
||||
{
|
||||
m_sampVolume.setPosition(m_regSliceCurrent.getLowerCorner().getX(), iYVolSpace, iZVolSpace);
|
||||
for(iXVolSpace = m_regSliceCurrent.getLowerCorner().getX() + 1; iXVolSpace <= iMaxXVolSpace; iXVolSpace++)
|
||||
{
|
||||
uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
|
||||
uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
|
||||
|
||||
m_sampVolume.movePositiveX();
|
||||
|
||||
computeBitmaskForCell<true, true, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace);
|
||||
}
|
||||
}
|
||||
|
||||
return m_uNoOfOccupiedCells;
|
||||
}
|
||||
|
||||
template<typename VolumeType, typename Controller>
|
||||
template<bool isPrevXAvail, bool isPrevYAvail, bool isPrevZAvail>
|
||||
void MarchingCubesSurfaceExtractor<VolumeType, Controller>::computeBitmaskForCell(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask, uint32_t uXRegSpace, uint32_t uYRegSpace)
|
||||
{
|
||||
uint8_t iCubeIndex = 0;
|
||||
|
||||
typename VolumeType::VoxelType v000;
|
||||
typename VolumeType::VoxelType v100;
|
||||
typename VolumeType::VoxelType v010;
|
||||
typename VolumeType::VoxelType v110;
|
||||
typename VolumeType::VoxelType v001;
|
||||
typename VolumeType::VoxelType v101;
|
||||
typename VolumeType::VoxelType v011;
|
||||
typename VolumeType::VoxelType v111;
|
||||
|
||||
if(isPrevZAvail)
|
||||
{
|
||||
if(isPrevYAvail)
|
||||
{
|
||||
if(isPrevXAvail)
|
||||
{
|
||||
v111 = m_sampVolume.peekVoxel1px1py1pz();
|
||||
|
||||
//z
|
||||
uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace];
|
||||
iPreviousCubeIndexZ >>= 4;
|
||||
|
||||
//y
|
||||
uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
|
||||
iPreviousCubeIndexY &= 192; //192 = 128 + 64
|
||||
iPreviousCubeIndexY >>= 2;
|
||||
|
||||
//x
|
||||
uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace];
|
||||
iPreviousCubeIndexX &= 128;
|
||||
iPreviousCubeIndexX >>= 1;
|
||||
|
||||
iCubeIndex = iPreviousCubeIndexX | iPreviousCubeIndexY | iPreviousCubeIndexZ;
|
||||
|
||||
if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
|
||||
}
|
||||
else //previous X not available
|
||||
{
|
||||
v011 = m_sampVolume.peekVoxel0px1py1pz();
|
||||
v111 = m_sampVolume.peekVoxel1px1py1pz();
|
||||
|
||||
//z
|
||||
uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace];
|
||||
iPreviousCubeIndexZ >>= 4;
|
||||
|
||||
//y
|
||||
uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
|
||||
iPreviousCubeIndexY &= 192; //192 = 128 + 64
|
||||
iPreviousCubeIndexY >>= 2;
|
||||
|
||||
iCubeIndex = iPreviousCubeIndexY | iPreviousCubeIndexZ;
|
||||
|
||||
if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64;
|
||||
if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
|
||||
}
|
||||
}
|
||||
else //previous Y not available
|
||||
{
|
||||
if(isPrevXAvail)
|
||||
{
|
||||
v101 = m_sampVolume.peekVoxel1px0py1pz();
|
||||
v111 = m_sampVolume.peekVoxel1px1py1pz();
|
||||
|
||||
//z
|
||||
uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace];
|
||||
iPreviousCubeIndexZ >>= 4;
|
||||
|
||||
//x
|
||||
uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace];
|
||||
iPreviousCubeIndexX &= 160; //160 = 128+32
|
||||
iPreviousCubeIndexX >>= 1;
|
||||
|
||||
iCubeIndex = iPreviousCubeIndexX | iPreviousCubeIndexZ;
|
||||
|
||||
if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32;
|
||||
if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
|
||||
}
|
||||
else //previous X not available
|
||||
{
|
||||
v001 = m_sampVolume.peekVoxel0px0py1pz();
|
||||
v101 = m_sampVolume.peekVoxel1px0py1pz();
|
||||
v011 = m_sampVolume.peekVoxel0px1py1pz();
|
||||
v111 = m_sampVolume.peekVoxel1px1py1pz();
|
||||
|
||||
//z
|
||||
uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace];
|
||||
iCubeIndex = iPreviousCubeIndexZ >> 4;
|
||||
|
||||
if (m_controller.convertToDensity(v001) < m_tThreshold) iCubeIndex |= 16;
|
||||
if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32;
|
||||
if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64;
|
||||
if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
|
||||
}
|
||||
}
|
||||
}
|
||||
else //previous Z not available
|
||||
{
|
||||
if(isPrevYAvail)
|
||||
{
|
||||
if(isPrevXAvail)
|
||||
{
|
||||
v110 = m_sampVolume.peekVoxel1px1py0pz();
|
||||
v111 = m_sampVolume.peekVoxel1px1py1pz();
|
||||
|
||||
//y
|
||||
uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
|
||||
iPreviousCubeIndexY &= 204; //204 = 128+64+8+4
|
||||
iPreviousCubeIndexY >>= 2;
|
||||
|
||||
//x
|
||||
uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace];
|
||||
iPreviousCubeIndexX &= 170; //170 = 128+32+8+2
|
||||
iPreviousCubeIndexX >>= 1;
|
||||
|
||||
iCubeIndex = iPreviousCubeIndexX | iPreviousCubeIndexY;
|
||||
|
||||
if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8;
|
||||
if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
|
||||
}
|
||||
else //previous X not available
|
||||
{
|
||||
v010 = m_sampVolume.peekVoxel0px1py0pz();
|
||||
v110 = m_sampVolume.peekVoxel1px1py0pz();
|
||||
|
||||
v011 = m_sampVolume.peekVoxel0px1py1pz();
|
||||
v111 = m_sampVolume.peekVoxel1px1py1pz();
|
||||
|
||||
//y
|
||||
uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
|
||||
iPreviousCubeIndexY &= 204; //204 = 128+64+8+4
|
||||
iPreviousCubeIndexY >>= 2;
|
||||
|
||||
iCubeIndex = iPreviousCubeIndexY;
|
||||
|
||||
if (m_controller.convertToDensity(v010) < m_tThreshold) iCubeIndex |= 4;
|
||||
if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8;
|
||||
if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64;
|
||||
if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
|
||||
}
|
||||
}
|
||||
else //previous Y not available
|
||||
{
|
||||
if(isPrevXAvail)
|
||||
{
|
||||
v100 = m_sampVolume.peekVoxel1px0py0pz();
|
||||
v110 = m_sampVolume.peekVoxel1px1py0pz();
|
||||
|
||||
v101 = m_sampVolume.peekVoxel1px0py1pz();
|
||||
v111 = m_sampVolume.peekVoxel1px1py1pz();
|
||||
|
||||
//x
|
||||
uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace];
|
||||
iPreviousCubeIndexX &= 170; //170 = 128+32+8+2
|
||||
iPreviousCubeIndexX >>= 1;
|
||||
|
||||
iCubeIndex = iPreviousCubeIndexX;
|
||||
|
||||
if (m_controller.convertToDensity(v100) < m_tThreshold) iCubeIndex |= 2;
|
||||
if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8;
|
||||
if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32;
|
||||
if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
|
||||
}
|
||||
else //previous X not available
|
||||
{
|
||||
v000 = m_sampVolume.getVoxel();
|
||||
v100 = m_sampVolume.peekVoxel1px0py0pz();
|
||||
v010 = m_sampVolume.peekVoxel0px1py0pz();
|
||||
v110 = m_sampVolume.peekVoxel1px1py0pz();
|
||||
|
||||
v001 = m_sampVolume.peekVoxel0px0py1pz();
|
||||
v101 = m_sampVolume.peekVoxel1px0py1pz();
|
||||
v011 = m_sampVolume.peekVoxel0px1py1pz();
|
||||
v111 = m_sampVolume.peekVoxel1px1py1pz();
|
||||
|
||||
if (m_controller.convertToDensity(v000) < m_tThreshold) iCubeIndex |= 1;
|
||||
if (m_controller.convertToDensity(v100) < m_tThreshold) iCubeIndex |= 2;
|
||||
if (m_controller.convertToDensity(v010) < m_tThreshold) iCubeIndex |= 4;
|
||||
if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8;
|
||||
if (m_controller.convertToDensity(v001) < m_tThreshold) iCubeIndex |= 16;
|
||||
if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32;
|
||||
if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64;
|
||||
if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Save the bitmask
|
||||
pCurrentBitmask[uXRegSpace][uYRegSpace] = iCubeIndex;
|
||||
|
||||
if(edgeTable[iCubeIndex] != 0)
|
||||
{
|
||||
++m_uNoOfOccupiedCells;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename VolumeType, typename Controller>
|
||||
void MarchingCubesSurfaceExtractor<VolumeType, Controller>::generateVerticesForSlice(const Array2DUint8& pCurrentBitmask,
|
||||
Array2DInt32& m_pCurrentVertexIndicesX,
|
||||
Array2DInt32& m_pCurrentVertexIndicesY,
|
||||
Array2DInt32& m_pCurrentVertexIndicesZ)
|
||||
{
|
||||
int32_t iZVolSpace = m_regSliceCurrent.getLowerCorner().getZ();
|
||||
|
||||
//Iterate over each cell in the region
|
||||
for(int32_t iYVolSpace = m_regSliceCurrent.getLowerCorner().getY(); iYVolSpace <= m_regSliceCurrent.getUpperCorner().getY(); iYVolSpace++)
|
||||
{
|
||||
const uint32_t uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
|
||||
|
||||
for(int32_t iXVolSpace = m_regSliceCurrent.getLowerCorner().getX(); iXVolSpace <= m_regSliceCurrent.getUpperCorner().getX(); iXVolSpace++)
|
||||
{
|
||||
//Current position
|
||||
const uint32_t uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
|
||||
|
||||
//Determine the index into the edge table which tells us which vertices are inside of the surface
|
||||
uint8_t iCubeIndex = pCurrentBitmask[uXRegSpace][uYRegSpace];
|
||||
|
||||
/* Cube is entirely in/out of the surface */
|
||||
if (edgeTable[iCubeIndex] == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//Check whether the generated vertex will lie on the edge of the region
|
||||
|
||||
|
||||
m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace);
|
||||
const typename VolumeType::VoxelType v000 = m_sampVolume.getVoxel();
|
||||
const Vector3DFloat n000 = computeCentralDifferenceGradient(m_sampVolume);
|
||||
|
||||
/* Find the vertices where the surface intersects the cube */
|
||||
if (edgeTable[iCubeIndex] & 1)
|
||||
{
|
||||
m_sampVolume.movePositiveX();
|
||||
const typename VolumeType::VoxelType v100 = m_sampVolume.getVoxel();
|
||||
const Vector3DFloat n100 = computeCentralDifferenceGradient(m_sampVolume);
|
||||
|
||||
float fInterp = static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v100) - m_controller.convertToDensity(v000));
|
||||
|
||||
const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()) + fInterp, static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()), static_cast<float>(iZVolSpace - m_regSizeInCells.getLowerCorner().getZ()));
|
||||
|
||||
Vector3DFloat v3dNormal = (n100*fInterp) + (n000*(1-fInterp));
|
||||
v3dNormal.normalise();
|
||||
|
||||
//Choose one of the two materials to use for the vertex (we don't interpolate as interpolation of
|
||||
//material IDs does not make sense). We take the largest, so that if we are working on a material-only
|
||||
//volume we get the one which is non-zero. Both materials can be non-zero if our volume has a density component.
|
||||
typename Controller::MaterialType uMaterial000 = m_controller.convertToMaterial(v000);
|
||||
typename Controller::MaterialType uMaterial100 = m_controller.convertToMaterial(v100);
|
||||
typename Controller::MaterialType uMaterial = (std::max)(uMaterial000, uMaterial100);
|
||||
|
||||
PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, static_cast<float>(uMaterial));
|
||||
uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
|
||||
m_pCurrentVertexIndicesX[iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()][iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()] = uLastVertexIndex;
|
||||
|
||||
m_sampVolume.moveNegativeX();
|
||||
}
|
||||
if (edgeTable[iCubeIndex] & 8)
|
||||
{
|
||||
m_sampVolume.movePositiveY();
|
||||
const typename VolumeType::VoxelType v010 = m_sampVolume.getVoxel();
|
||||
const Vector3DFloat n010 = computeCentralDifferenceGradient(m_sampVolume);
|
||||
|
||||
float fInterp = static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v010) - m_controller.convertToDensity(v000));
|
||||
|
||||
const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()), static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()) + fInterp, static_cast<float>(iZVolSpace - m_regSizeInVoxels.getLowerCorner().getZ()));
|
||||
|
||||
Vector3DFloat v3dNormal = (n010*fInterp) + (n000*(1-fInterp));
|
||||
v3dNormal.normalise();
|
||||
|
||||
//Choose one of the two materials to use for the vertex (we don't interpolate as interpolation of
|
||||
//material IDs does not make sense). We take the largest, so that if we are working on a material-only
|
||||
//volume we get the one which is non-zero. Both materials can be non-zero if our volume has a density component.
|
||||
typename Controller::MaterialType uMaterial000 = m_controller.convertToMaterial(v000);
|
||||
typename Controller::MaterialType uMaterial010 = m_controller.convertToMaterial(v010);
|
||||
typename Controller::MaterialType uMaterial = (std::max)(uMaterial000, uMaterial010);
|
||||
|
||||
PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, static_cast<float>(uMaterial));
|
||||
uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
|
||||
m_pCurrentVertexIndicesY[iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()][iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()] = uLastVertexIndex;
|
||||
|
||||
m_sampVolume.moveNegativeY();
|
||||
}
|
||||
if (edgeTable[iCubeIndex] & 256)
|
||||
{
|
||||
m_sampVolume.movePositiveZ();
|
||||
const typename VolumeType::VoxelType v001 = m_sampVolume.getVoxel();
|
||||
const Vector3DFloat n001 = computeCentralDifferenceGradient(m_sampVolume);
|
||||
|
||||
float fInterp = static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v001) - m_controller.convertToDensity(v000));
|
||||
|
||||
const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()), static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()), static_cast<float>(iZVolSpace - m_regSizeInVoxels.getLowerCorner().getZ()) + fInterp);
|
||||
|
||||
Vector3DFloat v3dNormal = (n001*fInterp) + (n000*(1-fInterp));
|
||||
v3dNormal.normalise();
|
||||
|
||||
//Choose one of the two materials to use for the vertex (we don't interpolate as interpolation of
|
||||
//material IDs does not make sense). We take the largest, so that if we are working on a material-only
|
||||
//volume we get the one which is non-zero. Both materials can be non-zero if our volume has a density component.
|
||||
typename Controller::MaterialType uMaterial000 = m_controller.convertToMaterial(v000);
|
||||
typename Controller::MaterialType uMaterial001 = m_controller.convertToMaterial(v001);
|
||||
typename Controller::MaterialType uMaterial = (std::max)(uMaterial000, uMaterial001);
|
||||
|
||||
PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, static_cast<float>(uMaterial));
|
||||
uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
|
||||
m_pCurrentVertexIndicesZ[iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()][iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()] = uLastVertexIndex;
|
||||
|
||||
m_sampVolume.moveNegativeZ();
|
||||
}
|
||||
}//For each cell
|
||||
}
|
||||
}
|
||||
|
||||
template<typename VolumeType, typename Controller>
|
||||
void MarchingCubesSurfaceExtractor<VolumeType, Controller>::generateIndicesForSlice(const Array2DUint8& pPreviousBitmask,
|
||||
const Array2DInt32& m_pPreviousVertexIndicesX,
|
||||
const Array2DInt32& m_pPreviousVertexIndicesY,
|
||||
const Array2DInt32& m_pPreviousVertexIndicesZ,
|
||||
const Array2DInt32& m_pCurrentVertexIndicesX,
|
||||
const Array2DInt32& m_pCurrentVertexIndicesY)
|
||||
{
|
||||
int32_t indlist[12];
|
||||
for(int i = 0; i < 12; i++)
|
||||
{
|
||||
indlist[i] = -1;
|
||||
}
|
||||
|
||||
for(int32_t iYVolSpace = m_regSlicePrevious.getLowerCorner().getY(); iYVolSpace <= m_regSizeInCells.getUpperCorner().getY(); iYVolSpace++)
|
||||
{
|
||||
for(int32_t iXVolSpace = m_regSlicePrevious.getLowerCorner().getX(); iXVolSpace <= m_regSizeInCells.getUpperCorner().getX(); iXVolSpace++)
|
||||
{
|
||||
int32_t iZVolSpace = m_regSlicePrevious.getLowerCorner().getZ();
|
||||
m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace);
|
||||
|
||||
//Current position
|
||||
const uint32_t uXRegSpace = m_sampVolume.getPosition().getX() - m_regSizeInVoxels.getLowerCorner().getX();
|
||||
const uint32_t uYRegSpace = m_sampVolume.getPosition().getY() - m_regSizeInVoxels.getLowerCorner().getY();
|
||||
|
||||
//Determine the index into the edge table which tells us which vertices are inside of the surface
|
||||
uint8_t iCubeIndex = pPreviousBitmask[uXRegSpace][uYRegSpace];
|
||||
|
||||
/* Cube is entirely in/out of the surface */
|
||||
if (edgeTable[iCubeIndex] == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find the vertices where the surface intersects the cube */
|
||||
if (edgeTable[iCubeIndex] & 1)
|
||||
{
|
||||
indlist[0] = m_pPreviousVertexIndicesX[uXRegSpace][uYRegSpace];
|
||||
//assert(indlist[0] != -1);
|
||||
}
|
||||
if (edgeTable[iCubeIndex] & 2)
|
||||
{
|
||||
indlist[1] = m_pPreviousVertexIndicesY[uXRegSpace+1][uYRegSpace];
|
||||
//assert(indlist[1] != -1);
|
||||
}
|
||||
if (edgeTable[iCubeIndex] & 4)
|
||||
{
|
||||
indlist[2] = m_pPreviousVertexIndicesX[uXRegSpace][uYRegSpace+1];
|
||||
//assert(indlist[2] != -1);
|
||||
}
|
||||
if (edgeTable[iCubeIndex] & 8)
|
||||
{
|
||||
indlist[3] = m_pPreviousVertexIndicesY[uXRegSpace][uYRegSpace];
|
||||
//assert(indlist[3] != -1);
|
||||
}
|
||||
if (edgeTable[iCubeIndex] & 16)
|
||||
{
|
||||
indlist[4] = m_pCurrentVertexIndicesX[uXRegSpace][uYRegSpace];
|
||||
//assert(indlist[4] != -1);
|
||||
}
|
||||
if (edgeTable[iCubeIndex] & 32)
|
||||
{
|
||||
indlist[5] = m_pCurrentVertexIndicesY[uXRegSpace+1][uYRegSpace];
|
||||
//assert(indlist[5] != -1);
|
||||
}
|
||||
if (edgeTable[iCubeIndex] & 64)
|
||||
{
|
||||
indlist[6] = m_pCurrentVertexIndicesX[uXRegSpace][uYRegSpace+1];
|
||||
//assert(indlist[6] != -1);
|
||||
}
|
||||
if (edgeTable[iCubeIndex] & 128)
|
||||
{
|
||||
indlist[7] = m_pCurrentVertexIndicesY[uXRegSpace][uYRegSpace];
|
||||
//assert(indlist[7] != -1);
|
||||
}
|
||||
if (edgeTable[iCubeIndex] & 256)
|
||||
{
|
||||
indlist[8] = m_pPreviousVertexIndicesZ[uXRegSpace][uYRegSpace];
|
||||
//assert(indlist[8] != -1);
|
||||
}
|
||||
if (edgeTable[iCubeIndex] & 512)
|
||||
{
|
||||
indlist[9] = m_pPreviousVertexIndicesZ[uXRegSpace+1][uYRegSpace];
|
||||
//assert(indlist[9] != -1);
|
||||
}
|
||||
if (edgeTable[iCubeIndex] & 1024)
|
||||
{
|
||||
indlist[10] = m_pPreviousVertexIndicesZ[uXRegSpace+1][uYRegSpace+1];
|
||||
//assert(indlist[10] != -1);
|
||||
}
|
||||
if (edgeTable[iCubeIndex] & 2048)
|
||||
{
|
||||
indlist[11] = m_pPreviousVertexIndicesZ[uXRegSpace][uYRegSpace+1];
|
||||
//assert(indlist[11] != -1);
|
||||
}
|
||||
|
||||
for (int i=0;triTable[iCubeIndex][i]!=-1;i+=3)
|
||||
{
|
||||
int32_t ind0 = indlist[triTable[iCubeIndex][i ]];
|
||||
int32_t ind1 = indlist[triTable[iCubeIndex][i+1]];
|
||||
int32_t ind2 = indlist[triTable[iCubeIndex][i+2]];
|
||||
|
||||
if((ind0 != -1) && (ind1 != -1) && (ind2 != -1))
|
||||
{
|
||||
m_meshCurrent->addTriangle(ind0, ind1, ind2);
|
||||
}
|
||||
}//For each triangle
|
||||
}//For each cell
|
||||
}
|
||||
}
|
||||
}
|
96
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Material.h
vendored
Normal file
96
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Material.h
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
/*******************************************************************************
|
||||
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_Material_H__
|
||||
#define __PolyVox_Material_H__
|
||||
|
||||
#include "Impl/TypeDef.h"
|
||||
|
||||
#include "PolyVoxCore/DefaultIsQuadNeeded.h" //we'll specialise this function for this voxel type
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
///This class represents a voxel storing only a material.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Detailed description...
|
||||
///
|
||||
/// \sa Density, MaterialDensityPair
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// int32_t template parameter is a dummy, required as the compiler expects to be able to declare an
|
||||
// instance of VoxelType::DensityType without knowing that VoxelType doesn't actually have a density.
|
||||
template <typename Type>
|
||||
class Material
|
||||
{
|
||||
public:
|
||||
Material() : m_uMaterial(0) {}
|
||||
Material(Type uMaterial) : m_uMaterial(uMaterial) {}
|
||||
|
||||
bool operator==(const Material& rhs) const
|
||||
{
|
||||
return (m_uMaterial == rhs.m_uMaterial);
|
||||
};
|
||||
|
||||
bool operator!=(const Material& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
/// \return The current material value of the voxel
|
||||
Type getMaterial() const { return m_uMaterial; }
|
||||
/**
|
||||
* Set the material value of the voxel
|
||||
*
|
||||
* \param uMaterial The material to set to
|
||||
*/
|
||||
void setMaterial(Type uMaterial) { m_uMaterial = uMaterial; }
|
||||
|
||||
private:
|
||||
Type m_uMaterial;
|
||||
};
|
||||
|
||||
typedef Material<uint8_t> Material8;
|
||||
typedef Material<uint16_t> Material16;
|
||||
|
||||
template<typename Type>
|
||||
class DefaultIsQuadNeeded< Material<Type> >
|
||||
{
|
||||
public:
|
||||
bool operator()(Material<Type> back, Material<Type> front, uint32_t& materialToUse)
|
||||
{
|
||||
if((back.getMaterial() > 0) && (front.getMaterial() == 0))
|
||||
{
|
||||
materialToUse = static_cast<uint32_t>(back.getMaterial());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif //__PolyVox_Material_H__
|
148
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/MaterialDensityPair.h
vendored
Normal file
148
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/MaterialDensityPair.h
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
/*******************************************************************************
|
||||
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_MaterialDensityPair_H__
|
||||
#define __PolyVox_MaterialDensityPair_H__
|
||||
|
||||
#include "PolyVoxCore/DefaultIsQuadNeeded.h" //we'll specialise this function for this voxel type
|
||||
#include "PolyVoxCore/DefaultMarchingCubesController.h" //We'll specialise the controller contained in here
|
||||
|
||||
#include "Impl/TypeDef.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/// This class represents a voxel storing only a density.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Detailed description...
|
||||
///
|
||||
/// \sa Density, Material
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename Type, uint8_t NoOfMaterialBits, uint8_t NoOfDensityBits>
|
||||
class MaterialDensityPair
|
||||
{
|
||||
public:
|
||||
MaterialDensityPair() : m_uMaterial(0), m_uDensity(0) {}
|
||||
MaterialDensityPair(Type uMaterial, Type uDensity) : m_uMaterial(uMaterial), m_uDensity(uDensity) {}
|
||||
|
||||
bool operator==(const MaterialDensityPair& rhs) const
|
||||
{
|
||||
return (m_uMaterial == rhs.m_uMaterial) && (m_uDensity == rhs.m_uDensity);
|
||||
};
|
||||
|
||||
bool operator!=(const MaterialDensityPair& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits>& operator+=(const MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits>& rhs)
|
||||
{
|
||||
m_uDensity += rhs.m_uDensity;
|
||||
|
||||
// What should we do with the material? Conceptually the idea of adding materials makes no sense, but for our
|
||||
// purposes we consider the 'sum' of two materials to just be the max. At least this way it is commutative.
|
||||
m_uMaterial = (std::max)(m_uMaterial, rhs.m_uMaterial);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits>& operator/=(uint32_t rhs)
|
||||
{
|
||||
// There's nothing sensible we can do with the material, so this function only affects the density.
|
||||
m_uDensity /= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Type getDensity() const { return m_uDensity; }
|
||||
Type getMaterial() const { return m_uMaterial; }
|
||||
|
||||
void setDensity(Type uDensity) { m_uDensity = uDensity; }
|
||||
void setMaterial(Type uMaterial) { m_uMaterial = uMaterial; }
|
||||
|
||||
static Type getMaxDensity() { return (0x01 << NoOfDensityBits) - 1; }
|
||||
static Type getMinDensity() { return 0; }
|
||||
|
||||
private:
|
||||
Type m_uMaterial : NoOfMaterialBits;
|
||||
Type m_uDensity : NoOfDensityBits;
|
||||
};
|
||||
|
||||
template<typename Type, uint8_t NoOfMaterialBits, uint8_t NoOfDensityBits>
|
||||
class DefaultIsQuadNeeded< MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> >
|
||||
{
|
||||
public:
|
||||
bool operator()(MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> back, MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> front, uint32_t& materialToUse)
|
||||
{
|
||||
if((back.getMaterial() > 0) && (front.getMaterial() == 0))
|
||||
{
|
||||
materialToUse = static_cast<uint32_t>(back.getMaterial());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Type, uint8_t NoOfMaterialBits, uint8_t NoOfDensityBits>
|
||||
class DefaultMarchingCubesController< MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> >
|
||||
{
|
||||
public:
|
||||
typedef Type DensityType;
|
||||
typedef Type MaterialType;
|
||||
|
||||
DefaultMarchingCubesController(void)
|
||||
{
|
||||
// Default to a threshold value halfway between the min and max possible values.
|
||||
m_tThreshold = (MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits>::getMinDensity() + MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits>::getMaxDensity()) / 2;
|
||||
}
|
||||
|
||||
DefaultMarchingCubesController(DensityType tThreshold)
|
||||
{
|
||||
m_tThreshold = tThreshold;
|
||||
}
|
||||
|
||||
DensityType convertToDensity(MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> voxel)
|
||||
{
|
||||
return voxel.getDensity();
|
||||
}
|
||||
|
||||
MaterialType convertToMaterial(MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> voxel)
|
||||
{
|
||||
return voxel.getMaterial();
|
||||
}
|
||||
|
||||
DensityType getThreshold(void)
|
||||
{
|
||||
return m_tThreshold;
|
||||
}
|
||||
|
||||
private:
|
||||
DensityType m_tThreshold;
|
||||
};
|
||||
|
||||
typedef MaterialDensityPair<uint8_t, 4, 4> MaterialDensityPair44;
|
||||
typedef MaterialDensityPair<uint16_t, 8, 8> MaterialDensityPair88;
|
||||
}
|
||||
|
||||
#endif
|
187
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/MeshDecimator.h
vendored
Normal file
187
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/MeshDecimator.h
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
/*******************************************************************************
|
||||
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_MeshDecimator_H__
|
||||
#define __PolyVox_MeshDecimator_H__
|
||||
|
||||
#include "PolyVoxCore/SurfaceMesh.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
#include "PolyVoxCore/VertexTypes.h"
|
||||
|
||||
#include <bitset>
|
||||
#include <vector>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/// The MeshDecimator reduces the number of triangles in a mesh.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Meshes generated by the PolyVox surface extractors typically have a very high
|
||||
/// number of triangles in them. This can pose difficulties both for the rendering
|
||||
/// storage of such meshes. The MeshDecimator provides a way of reducing the triangle
|
||||
/// count with minimal visual effect.
|
||||
///
|
||||
/// The MeshDecimator is based on the principle of edge collapse, and currently works
|
||||
/// with meshes generated by the MarchingCubesSurfaceExtractor or CubicSurfaceExtractor. It does
|
||||
/// not work with meshes generated by the CubicSurfaceExtractorWithNormals, although
|
||||
/// this may be addressed in the future. The algorithm iterates over each pair of
|
||||
/// connected vertices in the mesh and attemps to determine if they can be collapsed
|
||||
/// into a single vertex.
|
||||
///
|
||||
/// The main criteria used in deciding whether two vertices can collapse is whether
|
||||
/// they have the same normal. In the case of the cubic surfaces the normals must be
|
||||
/// exactly the same, whereas in the case of the Marching Cubes surfaces a threshold
|
||||
/// is used to determine whether two normals are 'close enough'. Additional constraints
|
||||
/// apply to vertices which lie on the edges of regions or on the boundary between two
|
||||
/// regions - these vertices are much less likely to be collapsed.
|
||||
///
|
||||
/// Given a mesh called 'mesh', you can create a decimated version as follows:
|
||||
/// \code
|
||||
/// SurfaceMesh<PositionMaterial> decimatedMesh;
|
||||
/// MeshDecimator<PositionMaterial> decimator(&mesh, &decimatedMesh);
|
||||
/// decimator.execute();
|
||||
/// \endcode
|
||||
///
|
||||
/// The above applies for a cubic mesh, for a Marching Cubes mesh you need to parametise
|
||||
/// the MeshDecimator and resulting SurfaceMesh on the 'PositionMaterialNormal' type
|
||||
/// instead of the 'PositionMaterial' type.
|
||||
///
|
||||
/// \deprecated
|
||||
template <typename VertexType>
|
||||
class MeshDecimator
|
||||
{
|
||||
//Used to keep track of when a vertex is
|
||||
//on one or more faces of the region
|
||||
enum RegionFaceFlags
|
||||
{
|
||||
RFF_ON_REGION_FACE_NEG_X,
|
||||
RFF_ON_REGION_FACE_POS_X ,
|
||||
RFF_ON_REGION_FACE_NEG_Y ,
|
||||
RFF_ON_REGION_FACE_POS_Y ,
|
||||
RFF_ON_REGION_FACE_NEG_Z ,
|
||||
RFF_ON_REGION_FACE_POS_Z,
|
||||
RFF_NO_OF_REGION_FACE_FLAGS
|
||||
};
|
||||
|
||||
//Data about the initial mesh - this
|
||||
//will be fill in once at the start
|
||||
struct InitialVertexMetadata
|
||||
{
|
||||
Vector3DFloat normal;
|
||||
bool isOnMaterialEdge;
|
||||
std::bitset<RFF_NO_OF_REGION_FACE_FLAGS> isOnRegionFace;
|
||||
};
|
||||
|
||||
//Representing a triangle for decimation purposes.
|
||||
struct Triangle
|
||||
{
|
||||
uint32_t v0;
|
||||
uint32_t v1;
|
||||
uint32_t v2;
|
||||
Vector3DFloat normal;
|
||||
};
|
||||
|
||||
struct IntVertex
|
||||
{
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t z;
|
||||
uint32_t index;
|
||||
|
||||
IntVertex(int32_t xVal, int32_t yVal, int32_t zVal, uint32_t indexVal)
|
||||
:x(xVal)
|
||||
,y(yVal)
|
||||
,z(zVal)
|
||||
,index(indexVal)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const IntVertex& rhs) const
|
||||
{
|
||||
return (x == rhs.x) && (y == rhs.y) && (z == rhs.z);
|
||||
}
|
||||
|
||||
bool operator<(const IntVertex& rhs) const
|
||||
{
|
||||
if (z < rhs.z)
|
||||
return true;
|
||||
if (rhs.z < z)
|
||||
return false;
|
||||
|
||||
if (y < rhs.y)
|
||||
return true;
|
||||
if (rhs.y < y)
|
||||
return false;
|
||||
|
||||
if (x < rhs.x)
|
||||
return true;
|
||||
if (rhs.x < x)
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
///Constructor
|
||||
POLYVOX_DEPRECATED MeshDecimator(const SurfaceMesh<VertexType>* pInputMesh, SurfaceMesh<VertexType>* pOutputMesh, float fEdgeCollapseThreshold = 0.95f);
|
||||
|
||||
///Performs the decimation.
|
||||
POLYVOX_DEPRECATED void execute();
|
||||
|
||||
private:
|
||||
|
||||
void fillInitialVertexMetadata(std::vector<InitialVertexMetadata>& vecInitialVertexMetadata);
|
||||
|
||||
void buildConnectivityData(void);
|
||||
|
||||
bool attemptEdgeCollapse(uint32_t uSrc, uint32_t uDst);
|
||||
|
||||
const SurfaceMesh<VertexType>* m_pInputMesh;
|
||||
SurfaceMesh<VertexType>* m_pOutputMesh;
|
||||
|
||||
uint32_t performDecimationPass(float m_fMinDotProductForCollapse);
|
||||
bool isSubset(std::bitset<RFF_NO_OF_REGION_FACE_FLAGS> a, std::bitset<RFF_NO_OF_REGION_FACE_FLAGS> b);
|
||||
|
||||
bool canCollapseEdge(uint32_t uSrc, uint32_t uDst);
|
||||
bool canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst);
|
||||
bool canCollapseRegionEdge(uint32_t uSrc, uint32_t uDst);
|
||||
bool canCollapseMaterialEdge(uint32_t uSrc, uint32_t uDst);
|
||||
bool collapseChangesFaceNormals(uint32_t uSrc, uint32_t uDst, float fThreshold);
|
||||
|
||||
//Data structures used during decimation
|
||||
|
||||
std::vector<bool> vertexLocked;
|
||||
std::vector<uint32_t> vertexMapper;
|
||||
|
||||
std::vector<Triangle> m_vecTriangles;
|
||||
std::vector< std::vector<uint32_t> > trianglesUsingVertex; //Should probably use vector of vectors, and resise in advance.
|
||||
|
||||
std::vector<InitialVertexMetadata> m_vecInitialVertexMetadata;
|
||||
|
||||
float m_fMinDotProductForCollapse;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/MeshDecimator.inl"
|
||||
|
||||
#endif //__PolyVox_MeshDecimator_H__
|
347
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/MeshDecimator.inl
vendored
Normal file
347
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/MeshDecimator.inl
vendored
Normal file
@ -0,0 +1,347 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Builds a MeshDecimator.
|
||||
/// \param pInputMesh A pointer to the mesh to be decimated.
|
||||
/// \param[out] pOutputMesh A pointer to where the result should be stored. Any existing
|
||||
/// contents will be deleted.
|
||||
/// \param fEdgeCollapseThreshold This is only use in the case of a Marching Cubes
|
||||
/// surface and controls how close two normals must be to collapse. The dot product
|
||||
/// between the normals is computed and compared to this threshold. A threshold of
|
||||
/// 1.0 means nothing will collapse, a threshold of 0.0 means everything will collapse.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VertexType>
|
||||
MeshDecimator<VertexType>::MeshDecimator(const SurfaceMesh<VertexType>* pInputMesh, SurfaceMesh<VertexType>* pOutputMesh, float fEdgeCollapseThreshold)
|
||||
:m_pInputMesh(pInputMesh)
|
||||
,m_pOutputMesh(pOutputMesh)
|
||||
,m_fMinDotProductForCollapse(fEdgeCollapseThreshold)
|
||||
{
|
||||
*m_pOutputMesh = *m_pInputMesh;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void MeshDecimator<VertexType>::execute()
|
||||
{
|
||||
//Sanity check.
|
||||
if((m_pOutputMesh->m_vecVertices.empty()) || (m_pOutputMesh->m_vecTriangleIndices.empty()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
buildConnectivityData();
|
||||
fillInitialVertexMetadata(m_vecInitialVertexMetadata);
|
||||
|
||||
uint32_t noOfEdgesCollapsed;
|
||||
do
|
||||
{
|
||||
noOfEdgesCollapsed = performDecimationPass(m_fMinDotProductForCollapse);
|
||||
m_pOutputMesh->removeDegenerateTris();
|
||||
if(noOfEdgesCollapsed > 0)
|
||||
{
|
||||
//Build the connectivity data for the next pass. If this is slow, then look
|
||||
//at adjusting it (based on vertex mapper?) rather than bulding from scratch.
|
||||
buildConnectivityData();
|
||||
}
|
||||
}while(noOfEdgesCollapsed > 0);
|
||||
|
||||
m_pOutputMesh->removeUnusedVertices();
|
||||
|
||||
//Decimation will have invalidated LOD levels.
|
||||
m_pOutputMesh->m_vecLodRecords.clear();
|
||||
LodRecord lodRecord;
|
||||
lodRecord.beginIndex = 0;
|
||||
lodRecord.endIndex = m_pOutputMesh->getNoOfIndices();
|
||||
m_pOutputMesh->m_vecLodRecords.push_back(lodRecord);
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void MeshDecimator<VertexType>::buildConnectivityData(void)
|
||||
{
|
||||
//Build a list of all the triangles, complete with face normals.
|
||||
m_vecTriangles.clear();
|
||||
m_vecTriangles.resize(m_pOutputMesh->m_vecTriangleIndices.size() / 3);
|
||||
for(uint32_t triCt = 0; triCt < m_vecTriangles.size(); triCt++)
|
||||
{
|
||||
m_vecTriangles[triCt].v0 = m_pOutputMesh->m_vecTriangleIndices[triCt * 3 + 0];
|
||||
m_vecTriangles[triCt].v1 = m_pOutputMesh->m_vecTriangleIndices[triCt * 3 + 1];
|
||||
m_vecTriangles[triCt].v2 = m_pOutputMesh->m_vecTriangleIndices[triCt * 3 + 2];
|
||||
|
||||
Vector3DFloat v0Pos = m_pOutputMesh->m_vecVertices[m_vecTriangles[triCt].v0].position;
|
||||
Vector3DFloat v1Pos = m_pOutputMesh->m_vecVertices[m_vecTriangles[triCt].v1].position;
|
||||
Vector3DFloat v2Pos = m_pOutputMesh->m_vecVertices[m_vecTriangles[triCt].v2].position;
|
||||
|
||||
Vector3DFloat v0v1 = v1Pos - v0Pos;
|
||||
Vector3DFloat v0v2 = v2Pos - v0Pos;
|
||||
Vector3DFloat normal = v0v1.cross(v0v2);
|
||||
normal.normalise();
|
||||
|
||||
m_vecTriangles[triCt].normal = normal;
|
||||
}
|
||||
|
||||
//For each vertex, determine which triangles are using it.
|
||||
trianglesUsingVertex.clear();
|
||||
trianglesUsingVertex.resize(m_pOutputMesh->m_vecVertices.size());
|
||||
for(uint32_t ct = 0; ct < trianglesUsingVertex.size(); ct++)
|
||||
{
|
||||
trianglesUsingVertex[ct].reserve(6);
|
||||
}
|
||||
for(uint32_t ct = 0; ct < m_vecTriangles.size(); ct++)
|
||||
{
|
||||
trianglesUsingVertex[m_vecTriangles[ct].v0].push_back(ct);
|
||||
trianglesUsingVertex[m_vecTriangles[ct].v1].push_back(ct);
|
||||
trianglesUsingVertex[m_vecTriangles[ct].v2].push_back(ct);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
uint32_t MeshDecimator<VertexType>::performDecimationPass(float /*m_fMinDotProductForCollapse*/)
|
||||
{
|
||||
// Count how many edges we have collapsed
|
||||
uint32_t noOfEdgesCollapsed = 0;
|
||||
|
||||
// The vertex mapper track whick vertices collapse onto which.
|
||||
vertexMapper.clear();
|
||||
vertexMapper.resize(m_pOutputMesh->m_vecVertices.size());
|
||||
|
||||
// Once a vertex is involved in a collapse (either because it
|
||||
// moves onto a different vertex, or because a different vertex
|
||||
// moves onto it) it is forbidden to take part in another collapse
|
||||
// this pass. We enforce this by setting the vertex locked flag.
|
||||
vertexLocked.clear();
|
||||
vertexLocked.resize(m_pOutputMesh->m_vecVertices.size());
|
||||
|
||||
// Initialise the vectors
|
||||
for(uint32_t ct = 0; ct < m_pOutputMesh->m_vecVertices.size(); ct++)
|
||||
{
|
||||
// Initiall all vertices points to themselves
|
||||
vertexMapper[ct] = ct;
|
||||
// All vertices are initially unlocked
|
||||
vertexLocked[ct] = false;
|
||||
}
|
||||
|
||||
//For each triangle...
|
||||
for(uint32_t ctIter = 0; ctIter < m_vecTriangles.size(); ctIter++)
|
||||
{
|
||||
if(attemptEdgeCollapse(m_vecTriangles[ctIter].v0, m_vecTriangles[ctIter].v1))
|
||||
{
|
||||
++noOfEdgesCollapsed;
|
||||
}
|
||||
|
||||
if(attemptEdgeCollapse(m_vecTriangles[ctIter].v1, m_vecTriangles[ctIter].v2))
|
||||
{
|
||||
++noOfEdgesCollapsed;
|
||||
}
|
||||
|
||||
if(attemptEdgeCollapse(m_vecTriangles[ctIter].v2, m_vecTriangles[ctIter].v0))
|
||||
{
|
||||
++noOfEdgesCollapsed;
|
||||
}
|
||||
}
|
||||
|
||||
if(noOfEdgesCollapsed > 0)
|
||||
{
|
||||
//Fix up the indices
|
||||
for(uint32_t triCt = 0; triCt < m_pOutputMesh->m_vecTriangleIndices.size(); triCt++)
|
||||
{
|
||||
uint32_t before = m_pOutputMesh->m_vecTriangleIndices[triCt];
|
||||
uint32_t after = vertexMapper[m_pOutputMesh->m_vecTriangleIndices[triCt]];
|
||||
if(before != after)
|
||||
{
|
||||
m_pOutputMesh->m_vecTriangleIndices[triCt] = vertexMapper[m_pOutputMesh->m_vecTriangleIndices[triCt]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return noOfEdgesCollapsed;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
bool MeshDecimator<VertexType>::attemptEdgeCollapse(uint32_t uSrc, uint32_t uDst)
|
||||
{
|
||||
//A vertex will be locked if it has already been involved in a collapse this pass.
|
||||
if(vertexLocked[uSrc] || vertexLocked[uDst])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(canCollapseEdge(uSrc, uDst))
|
||||
{
|
||||
//Move v0 onto v1
|
||||
vertexMapper[uSrc] = uDst; //vertexMapper[v1];
|
||||
vertexLocked[uSrc] = true;
|
||||
vertexLocked[uDst] = true;
|
||||
|
||||
//Increment the counter
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
bool MeshDecimator<VertexType>::canCollapseEdge(uint32_t uSrc, uint32_t uDst)
|
||||
{
|
||||
bool bCanCollapse = true;
|
||||
|
||||
if(m_vecInitialVertexMetadata[uSrc].isOnMaterialEdge)
|
||||
{
|
||||
bCanCollapse &= canCollapseMaterialEdge(uSrc, uDst);
|
||||
}
|
||||
|
||||
if(m_vecInitialVertexMetadata[uSrc].isOnRegionFace.any())
|
||||
{
|
||||
bCanCollapse &= canCollapseRegionEdge(uSrc, uDst);
|
||||
}
|
||||
|
||||
if(bCanCollapse) //Only bother with this if the earlier tests passed.
|
||||
{
|
||||
bCanCollapse &= canCollapseNormalEdge(uSrc, uDst);
|
||||
}
|
||||
|
||||
return bCanCollapse;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
bool MeshDecimator<VertexType>::canCollapseRegionEdge(uint32_t uSrc, uint32_t uDst)
|
||||
{
|
||||
// We can collapse normal vertices onto edge vertices, and edge vertices
|
||||
// onto corner vertices, but not vice-versa. Hence we check whether all
|
||||
// the edge flags in the source vertex are also set in the destination vertex.
|
||||
if(isSubset(m_vecInitialVertexMetadata[uSrc].isOnRegionFace, m_vecInitialVertexMetadata[uDst].isOnRegionFace) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// In general adjacent regions surface meshes may collapse differently
|
||||
// and this can cause cracks. We solve this by only allowing the collapse
|
||||
// is the normals are exactly the same. We do not use the user provided
|
||||
// tolerence here (but do allow for floating point error).
|
||||
if(m_vecInitialVertexMetadata[uSrc].normal.dot(m_vecInitialVertexMetadata[uDst].normal) < 0.999f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
bool MeshDecimator<VertexType>::canCollapseMaterialEdge(uint32_t /*uSrc*/, uint32_t /*uDst*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//This function should really use some work. For a start we already have the
|
||||
//faces normals for the input mesh yet we are computing them on the fly here.
|
||||
template <typename VertexType>
|
||||
bool MeshDecimator<VertexType>::collapseChangesFaceNormals(uint32_t uSrc, uint32_t uDst, float fThreshold)
|
||||
{
|
||||
bool faceFlipped = false;
|
||||
std::vector<uint32_t>& triangles = trianglesUsingVertex[uSrc];
|
||||
|
||||
for(std::vector<uint32_t>::iterator triIter = triangles.begin(); triIter != triangles.end(); triIter++)
|
||||
{
|
||||
uint32_t tri = *triIter;
|
||||
|
||||
const uint32_t& v0Old = m_pOutputMesh->m_vecTriangleIndices[tri * 3];
|
||||
const uint32_t& v1Old = m_pOutputMesh->m_vecTriangleIndices[tri * 3 + 1];
|
||||
const uint32_t& v2Old = m_pOutputMesh->m_vecTriangleIndices[tri * 3 + 2];
|
||||
|
||||
//Check if degenerate
|
||||
if((v0Old == v1Old) || (v1Old == v2Old) || (v2Old == v0Old))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t v0New = v0Old;
|
||||
uint32_t v1New = v1Old;
|
||||
uint32_t v2New = v2Old;
|
||||
|
||||
if(v0New == uSrc)
|
||||
v0New = uDst;
|
||||
if(v1New == uSrc)
|
||||
v1New = uDst;
|
||||
if(v2New == uSrc)
|
||||
v2New = uDst;
|
||||
|
||||
//Check if degenerate
|
||||
if((v0New == v1New) || (v1New == v2New) || (v2New == v0New))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const Vector3DFloat& v0OldPos = m_pOutputMesh->m_vecVertices[vertexMapper[v0Old]].getPosition(); //Note: we need the vertex mapper here. These neighbouring vertices may have been moved.
|
||||
const Vector3DFloat& v1OldPos = m_pOutputMesh->m_vecVertices[vertexMapper[v1Old]].getPosition();
|
||||
const Vector3DFloat& v2OldPos = m_pOutputMesh->m_vecVertices[vertexMapper[v2Old]].getPosition();
|
||||
|
||||
const Vector3DFloat& v0NewPos = m_pOutputMesh->m_vecVertices[vertexMapper[v0New]].getPosition();
|
||||
const Vector3DFloat& v1NewPos = m_pOutputMesh->m_vecVertices[vertexMapper[v1New]].getPosition();
|
||||
const Vector3DFloat& v2NewPos = m_pOutputMesh->m_vecVertices[vertexMapper[v2New]].getPosition();
|
||||
|
||||
Vector3DFloat OldNormal = (v1OldPos - v0OldPos).cross(v2OldPos - v1OldPos);
|
||||
Vector3DFloat NewNormal = (v1NewPos - v0NewPos).cross(v2NewPos - v1NewPos);
|
||||
|
||||
OldNormal.normalise();
|
||||
NewNormal.normalise();
|
||||
|
||||
float dotProduct = OldNormal.dot(NewNormal);
|
||||
//NOTE: I don't think we should be using the threshold here, we're just checking for a complete face flip
|
||||
if(dotProduct < fThreshold)
|
||||
{
|
||||
//cout << " Face flipped!!" << endl;
|
||||
|
||||
faceFlipped = true;
|
||||
|
||||
/*vertexLocked[v0] = true;
|
||||
vertexLocked[v1] = true;*/
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return faceFlipped;
|
||||
}
|
||||
|
||||
// Returns true if every bit which is set in 'a' is also set in 'b'. The reverse does not need to be true.
|
||||
template <typename VertexType>
|
||||
bool MeshDecimator<VertexType>::isSubset(std::bitset<RFF_NO_OF_REGION_FACE_FLAGS> a, std::bitset<RFF_NO_OF_REGION_FACE_FLAGS> b)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
for(int ct = 0; ct < RFF_NO_OF_REGION_FACE_FLAGS; ct++)
|
||||
{
|
||||
if(a.test(ct))
|
||||
{
|
||||
if(b.test(ct) == false)
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
153
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h
vendored
Normal file
153
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
/*******************************************************************************
|
||||
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_ForwardDeclarations_H__
|
||||
#define __PolyVox_ForwardDeclarations_H__
|
||||
|
||||
#include "Impl/TypeDef.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template<uint32_t dimensions, typename ElementType> class Array;
|
||||
|
||||
typedef Array<1,float> Array1DFloat;
|
||||
typedef Array<1,double> Array1DDouble;
|
||||
typedef Array<1,int8_t> Array1DInt8;
|
||||
typedef Array<1,uint8_t> Array1DUint8;
|
||||
typedef Array<1,int16_t> Array1DInt16;
|
||||
typedef Array<1,uint16_t> Array1DUint16;
|
||||
typedef Array<1,int32_t> Array1DInt32;
|
||||
typedef Array<1,uint32_t> Array1DUint32;
|
||||
|
||||
typedef Array<2,float> Array2DFloat;
|
||||
typedef Array<2,double> Array2DDouble;
|
||||
typedef Array<2,int8_t> Array2DInt8;
|
||||
typedef Array<2,uint8_t> Array2DUint8;
|
||||
typedef Array<2,int16_t> Array2DInt16;
|
||||
typedef Array<2,uint16_t> Array2DUint16;
|
||||
typedef Array<2,int32_t> Array2DInt32;
|
||||
typedef Array<2,uint32_t> Array2DUint32;
|
||||
|
||||
typedef Array<3,float> Array3DFloat;
|
||||
typedef Array<3,double> Array3DDouble;
|
||||
typedef Array<3,int8_t> Array3DInt8;
|
||||
typedef Array<3,uint8_t> Array3DUint8;
|
||||
typedef Array<3,int16_t> Array3DInt16;
|
||||
typedef Array<3,uint16_t> Array3DUint16;
|
||||
typedef Array<3,int32_t> Array3DInt32;
|
||||
typedef Array<3,uint32_t> Array3DUint32;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// CubicSurfaceExtractor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template< typename VolumeType> class CubicSurfaceExtractor;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Density
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename Type> class Density;
|
||||
|
||||
typedef Density<int8_t> DensityI8;
|
||||
typedef Density<uint8_t> DensityU8;
|
||||
typedef Density<int16_t> DensityI16;
|
||||
typedef Density<uint16_t> DensityU16;
|
||||
typedef Density<float> DensityFloat;
|
||||
typedef Density<double> DensityDouble;
|
||||
|
||||
typedef DensityU8 Density8; //Backwards compatibility
|
||||
typedef DensityU16 Density16; //Backwards compatibility
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// LargeVolume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType> class LargeVolume;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Material
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename Type> class Material;
|
||||
|
||||
typedef Material<uint8_t> MaterialU8;
|
||||
typedef Material<uint16_t> MaterialU16;
|
||||
typedef Material<uint32_t> MaterialU32;
|
||||
|
||||
typedef MaterialU8 Material8;
|
||||
typedef MaterialU16 Material16;
|
||||
typedef MaterialU32 Material32;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// MaterialDensityPair
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename Type, uint8_t NoOfMaterialBits, uint8_t NoOfDensityBits> class MaterialDensityPair;
|
||||
|
||||
typedef MaterialDensityPair<uint8_t, 4, 4> MaterialDensityPair44;
|
||||
typedef MaterialDensityPair<uint16_t, 8, 8> MaterialDensityPair88;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PositionMaterial
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class PositionMaterial;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PositionMaterialNormal
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class PositionMaterialNormal;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// RawVolume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType> class RawVolume;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Region
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class Region;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// MarchingCubesSurfaceExtractor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template<typename VolumeType, typename Controller> class MarchingCubesSurfaceExtractor;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SurfaceMesh
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VertexType> class SurfaceMesh;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Vector
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <uint32_t Size, typename Type> class Vector;
|
||||
typedef Vector<3,float> Vector3DFloat;
|
||||
typedef Vector<3,double> Vector3DDouble;
|
||||
typedef Vector<3,int8_t> Vector3DInt8;
|
||||
typedef Vector<3,uint8_t> Vector3DUint8;
|
||||
typedef Vector<3,int16_t> Vector3DInt16;
|
||||
typedef Vector<3,uint16_t> Vector3DUint16;
|
||||
typedef Vector<3,int32_t> Vector3DInt32;
|
||||
typedef Vector<3,uint32_t> Vector3DUint32;
|
||||
}
|
||||
|
||||
#endif
|
163
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/RawVolume.h
vendored
Normal file
163
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/RawVolume.h
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
/*******************************************************************************
|
||||
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_RawVolume_H__
|
||||
#define __PolyVox_RawVolume_H__
|
||||
|
||||
#include "PolyVoxCore/BaseVolume.h"
|
||||
#include "PolyVoxCore/Log.h"
|
||||
#include "PolyVoxCore/Region.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib> //For abort()
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <stdexcept> //For invalid_argument
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
class RawVolume : public BaseVolume<VoxelType>
|
||||
{
|
||||
public:
|
||||
#ifndef SWIG
|
||||
//There seems to be some descrepency between Visual Studio and GCC about how the following class should be declared.
|
||||
//There is a work around (see also See http://goo.gl/qu1wn) given below which appears to work on VS2010 and GCC, but
|
||||
//which seems to cause internal compiler errors on VS2008 when building with the /Gm 'Enable Minimal Rebuild' compiler
|
||||
//option. For now it seems best to 'fix' it with the preprocessor insstead, but maybe the workaround can be reinstated
|
||||
//in the future
|
||||
//typedef Volume<VoxelType> VolumeOfVoxelType; //Workaround for GCC/VS2010 differences.
|
||||
//class Sampler : public VolumeOfVoxelType::template Sampler< RawVolume<VoxelType> >
|
||||
#if defined(_MSC_VER)
|
||||
class Sampler : public BaseVolume<VoxelType>::Sampler< RawVolume<VoxelType> > //This line works on VS2010
|
||||
#else
|
||||
class Sampler : public BaseVolume<VoxelType>::template Sampler< RawVolume<VoxelType> > //This line works on GCC
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
Sampler(RawVolume<VoxelType>* volume);
|
||||
~Sampler();
|
||||
|
||||
inline VoxelType getVoxel(void) const;
|
||||
|
||||
void setPosition(const Vector3DInt32& v3dNewPos);
|
||||
void setPosition(int32_t xPos, int32_t yPos, int32_t zPos);
|
||||
inline bool setVoxel(VoxelType tValue);
|
||||
|
||||
void movePositiveX(void);
|
||||
void movePositiveY(void);
|
||||
void movePositiveZ(void);
|
||||
|
||||
void moveNegativeX(void);
|
||||
void moveNegativeY(void);
|
||||
void moveNegativeZ(void);
|
||||
|
||||
inline VoxelType peekVoxel1nx1ny1nz(void) const;
|
||||
inline VoxelType peekVoxel1nx1ny0pz(void) const;
|
||||
inline VoxelType peekVoxel1nx1ny1pz(void) const;
|
||||
inline VoxelType peekVoxel1nx0py1nz(void) const;
|
||||
inline VoxelType peekVoxel1nx0py0pz(void) const;
|
||||
inline VoxelType peekVoxel1nx0py1pz(void) const;
|
||||
inline VoxelType peekVoxel1nx1py1nz(void) const;
|
||||
inline VoxelType peekVoxel1nx1py0pz(void) const;
|
||||
inline VoxelType peekVoxel1nx1py1pz(void) const;
|
||||
|
||||
inline VoxelType peekVoxel0px1ny1nz(void) const;
|
||||
inline VoxelType peekVoxel0px1ny0pz(void) const;
|
||||
inline VoxelType peekVoxel0px1ny1pz(void) const;
|
||||
inline VoxelType peekVoxel0px0py1nz(void) const;
|
||||
inline VoxelType peekVoxel0px0py0pz(void) const;
|
||||
inline VoxelType peekVoxel0px0py1pz(void) const;
|
||||
inline VoxelType peekVoxel0px1py1nz(void) const;
|
||||
inline VoxelType peekVoxel0px1py0pz(void) const;
|
||||
inline VoxelType peekVoxel0px1py1pz(void) const;
|
||||
|
||||
inline VoxelType peekVoxel1px1ny1nz(void) const;
|
||||
inline VoxelType peekVoxel1px1ny0pz(void) const;
|
||||
inline VoxelType peekVoxel1px1ny1pz(void) const;
|
||||
inline VoxelType peekVoxel1px0py1nz(void) const;
|
||||
inline VoxelType peekVoxel1px0py0pz(void) const;
|
||||
inline VoxelType peekVoxel1px0py1pz(void) const;
|
||||
inline VoxelType peekVoxel1px1py1nz(void) const;
|
||||
inline VoxelType peekVoxel1px1py0pz(void) const;
|
||||
inline VoxelType peekVoxel1px1py1pz(void) const;
|
||||
|
||||
private:
|
||||
//Other current position information
|
||||
VoxelType* mCurrentVoxel;
|
||||
|
||||
//Whether the current position is inside the volume
|
||||
//FIXME - Replace these with flags
|
||||
bool m_bIsCurrentPositionValidInX;
|
||||
bool m_bIsCurrentPositionValidInY;
|
||||
bool m_bIsCurrentPositionValidInZ;
|
||||
};
|
||||
#endif
|
||||
|
||||
public:
|
||||
/// Constructor for creating a fixed size volume.
|
||||
RawVolume(const Region& regValid);
|
||||
|
||||
/// Destructor
|
||||
~RawVolume();
|
||||
|
||||
/// Gets the value used for voxels which are outside the volume
|
||||
VoxelType getBorderValue(void) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
|
||||
|
||||
/// Sets the value used for voxels which are outside the volume
|
||||
void setBorderValue(const VoxelType& tBorder);
|
||||
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue);
|
||||
/// Sets the voxel at the position given by a 3D vector
|
||||
bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue);
|
||||
|
||||
/// Calculates approximatly how many bytes of memory the volume is currently using.
|
||||
uint32_t calculateSizeInBytes(void);
|
||||
|
||||
protected:
|
||||
/// Copy constructor
|
||||
RawVolume(const RawVolume& rhs);
|
||||
|
||||
/// Assignment operator
|
||||
RawVolume& operator=(const RawVolume& rhs);
|
||||
|
||||
private:
|
||||
void initialise(const Region& regValidRegion);
|
||||
|
||||
//The block data
|
||||
VoxelType* m_pData;
|
||||
|
||||
//The border value
|
||||
VoxelType m_tBorderValue;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/RawVolume.inl"
|
||||
#include "PolyVoxCore/RawVolumeSampler.inl"
|
||||
|
||||
#endif //__PolyVox_RawVolume_H__
|
211
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/RawVolume.inl
vendored
Normal file
211
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/RawVolume.inl
vendored
Normal file
@ -0,0 +1,211 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This constructor creates a volume with a fixed size which is specified as a parameter.
|
||||
/// \param regValid Specifies the minimum and maximum valid voxel positions.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
RawVolume<VoxelType>::RawVolume(const Region& regValid)
|
||||
:BaseVolume<VoxelType>(regValid)
|
||||
{
|
||||
setBorderValue(VoxelType());
|
||||
|
||||
//Create a volume of the right size.
|
||||
initialise(regValid);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This function should never be called. Copying volumes by value would be expensive, and we want to prevent users from doing
|
||||
/// it by accident (such as when passing them as paramenters to functions). That said, there are times when you really do want to
|
||||
/// make a copy of a volume and in this case you should look at the Volumeresampler.
|
||||
///
|
||||
/// \sa VolumeResampler
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
RawVolume<VoxelType>::RawVolume(const RawVolume<VoxelType>& /*rhs*/)
|
||||
{
|
||||
assert(false); // See function comment above.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Destroys the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
RawVolume<VoxelType>::~RawVolume()
|
||||
{
|
||||
delete[] m_pData;
|
||||
m_pData = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This function should never be called. Copying volumes by value would be expensive, and we want to prevent users from doing
|
||||
/// it by accident (such as when passing them as paramenters to functions). That said, there are times when you really do want to
|
||||
/// make a copy of a volume and in this case you should look at the Volumeresampler.
|
||||
///
|
||||
/// \sa VolumeResampler
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
RawVolume<VoxelType>& RawVolume<VoxelType>::operator=(const RawVolume<VoxelType>& /*rhs*/)
|
||||
{
|
||||
assert(false); // See function comment above.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// The border value is returned whenever an attempt is made to read a voxel which
|
||||
/// is outside the extents of the volume.
|
||||
/// \return The value used for voxels outside of the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::getBorderValue(void) const
|
||||
{
|
||||
return m_tBorderValue;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param uXPos The \c x position of the voxel
|
||||
/// \param uYPos The \c y position of the voxel
|
||||
/// \param uZPos The \c z position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
|
||||
{
|
||||
if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)))
|
||||
{
|
||||
const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner();
|
||||
int32_t iLocalXPos = uXPos - v3dLowerCorner.getX();
|
||||
int32_t iLocalYPos = uYPos - v3dLowerCorner.getY();
|
||||
int32_t iLocalZPos = uZPos - v3dLowerCorner.getZ();
|
||||
|
||||
return m_pData
|
||||
[
|
||||
iLocalXPos +
|
||||
iLocalYPos * this->getWidth() +
|
||||
iLocalZPos * this->getWidth() * this->getHeight()
|
||||
];
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->getBorderValue();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos The 3D position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::getVoxelAt(const Vector3DInt32& v3dPos) const
|
||||
{
|
||||
return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param tBorder The value to use for voxels outside the volume.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::setBorderValue(const VoxelType& tBorder)
|
||||
{
|
||||
m_tBorderValue = tBorder;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param uXPos the \c x position of the voxel
|
||||
/// \param uYPos the \c y position of the voxel
|
||||
/// \param uZPos the \c z position of the voxel
|
||||
/// \param tValue the value to which the voxel will be set
|
||||
/// \return whether the requested position is inside the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
bool RawVolume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue)
|
||||
{
|
||||
if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)))
|
||||
{
|
||||
const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner();
|
||||
int32_t iLocalXPos = uXPos - v3dLowerCorner.getX();
|
||||
int32_t iLocalYPos = uYPos - v3dLowerCorner.getY();
|
||||
int32_t iLocalZPos = uZPos - v3dLowerCorner.getZ();
|
||||
|
||||
m_pData
|
||||
[
|
||||
iLocalXPos +
|
||||
iLocalYPos * this->getWidth() +
|
||||
iLocalZPos * this->getWidth() * this->getHeight()
|
||||
] = tValue;
|
||||
|
||||
//Return true to indicate that we modified a voxel.
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos the 3D position of the voxel
|
||||
/// \param tValue the value to which the voxel will be set
|
||||
/// \return whether the requested position is inside the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
bool RawVolume<VoxelType>::setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue)
|
||||
{
|
||||
return setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This function should probably be made internal...
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::initialise(const Region& regValidRegion)
|
||||
{
|
||||
this->m_regValidRegion = regValidRegion;
|
||||
|
||||
//Ensure dimensions of the specified Region are valid
|
||||
assert(this->getWidth() > 0);
|
||||
assert(this->getHeight() > 0);
|
||||
assert(this->getDepth() > 0);
|
||||
|
||||
//Create the data
|
||||
m_pData = new VoxelType[this->getWidth() * this->getHeight()* this->getDepth()];
|
||||
|
||||
//Other properties we might find useful later
|
||||
this->m_uLongestSideLength = (std::max)((std::max)(this->getWidth(),this->getHeight()),this->getDepth());
|
||||
this->m_uShortestSideLength = (std::min)((std::min)(this->getWidth(),this->getHeight()),this->getDepth());
|
||||
this->m_fDiagonalLength = sqrtf(static_cast<float>(this->getWidth() * this->getWidth() + this->getHeight() * this->getHeight() + this->getDepth() * this->getDepth()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Note: This function needs reviewing for accuracy...
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
uint32_t RawVolume<VoxelType>::calculateSizeInBytes(void)
|
||||
{
|
||||
return this->getWidth() * this->getHeight() * this->getDepth() * sizeof(VoxelType);
|
||||
}
|
||||
|
||||
}
|
||||
|
422
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/RawVolumeSampler.inl
vendored
Normal file
422
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/RawVolumeSampler.inl
vendored
Normal file
@ -0,0 +1,422 @@
|
||||
/*******************************************************************************
|
||||
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.
|
||||
*******************************************************************************/
|
||||
|
||||
#define BORDER_LOWX(val) (val > this->mVolume->getEnclosingRegion().getLowerCorner().getX())
|
||||
#define BORDER_HIGHX(val) (val < this->mVolume->getEnclosingRegion().getUpperCorner().getX())
|
||||
#define BORDER_LOWY(val) (val > this->mVolume->getEnclosingRegion().getLowerCorner().getY())
|
||||
#define BORDER_HIGHY(val) (val < this->mVolume->getEnclosingRegion().getUpperCorner().getY())
|
||||
#define BORDER_LOWZ(val) (val > this->mVolume->getEnclosingRegion().getLowerCorner().getZ())
|
||||
#define BORDER_HIGHZ(val) (val < this->mVolume->getEnclosingRegion().getUpperCorner().getZ())
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
RawVolume<VoxelType>::Sampler::Sampler(RawVolume<VoxelType>* volume)
|
||||
:BaseVolume<VoxelType>::template Sampler< RawVolume<VoxelType> >(volume)
|
||||
,mCurrentVoxel(0)
|
||||
,m_bIsCurrentPositionValidInX(false)
|
||||
,m_bIsCurrentPositionValidInY(false)
|
||||
,m_bIsCurrentPositionValidInZ(false)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
RawVolume<VoxelType>::Sampler::~Sampler()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::getVoxel(void) const
|
||||
{
|
||||
return (m_bIsCurrentPositionValidInX && m_bIsCurrentPositionValidInY && m_bIsCurrentPositionValidInZ) ? *mCurrentVoxel : this->mVolume->getBorderValue();
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::Sampler::setPosition(const Vector3DInt32& v3dNewPos)
|
||||
{
|
||||
setPosition(v3dNewPos.getX(), v3dNewPos.getY(), v3dNewPos.getZ());
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::Sampler::setPosition(int32_t xPos, int32_t yPos, int32_t zPos)
|
||||
{
|
||||
this->mXPosInVolume = xPos;
|
||||
this->mYPosInVolume = yPos;
|
||||
this->mZPosInVolume = zPos;
|
||||
|
||||
const Vector3DInt32& v3dLowerCorner = this->mVolume->m_regValidRegion.getLowerCorner();
|
||||
int32_t iLocalXPos = xPos - v3dLowerCorner.getX();
|
||||
int32_t iLocalYPos = yPos - v3dLowerCorner.getY();
|
||||
int32_t iLocalZPos = zPos - v3dLowerCorner.getZ();
|
||||
|
||||
const int32_t uVoxelIndex = iLocalXPos +
|
||||
iLocalYPos * this->mVolume->getWidth() +
|
||||
iLocalZPos * this->mVolume->getWidth() * this->mVolume->getHeight();
|
||||
|
||||
mCurrentVoxel = this->mVolume->m_pData + uVoxelIndex;
|
||||
|
||||
m_bIsCurrentPositionValidInX = this->mVolume->getEnclosingRegion().containsPointInX(xPos);
|
||||
m_bIsCurrentPositionValidInY = this->mVolume->getEnclosingRegion().containsPointInY(yPos);
|
||||
m_bIsCurrentPositionValidInZ = this->mVolume->getEnclosingRegion().containsPointInZ(zPos);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
bool RawVolume<VoxelType>::Sampler::setVoxel(VoxelType tValue)
|
||||
{
|
||||
//return m_bIsCurrentPositionValid ? *mCurrentVoxel : this->mVolume->getBorderValue();
|
||||
if(m_bIsCurrentPositionValidInX && m_bIsCurrentPositionValidInY && m_bIsCurrentPositionValidInZ)
|
||||
{
|
||||
*mCurrentVoxel = tValue;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::Sampler::movePositiveX(void)
|
||||
{
|
||||
this->mXPosInVolume++;
|
||||
++mCurrentVoxel;
|
||||
m_bIsCurrentPositionValidInX = this->mVolume->getEnclosingRegion().containsPointInX(this->mXPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::Sampler::movePositiveY(void)
|
||||
{
|
||||
this->mYPosInVolume++;
|
||||
mCurrentVoxel += this->mVolume->getWidth();
|
||||
m_bIsCurrentPositionValidInY = this->mVolume->getEnclosingRegion().containsPointInY(this->mYPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::Sampler::movePositiveZ(void)
|
||||
{
|
||||
this->mZPosInVolume++;
|
||||
mCurrentVoxel += this->mVolume->getWidth() * this->mVolume->getHeight();
|
||||
m_bIsCurrentPositionValidInZ = this->mVolume->getEnclosingRegion().containsPointInZ(this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::Sampler::moveNegativeX(void)
|
||||
{
|
||||
this->mXPosInVolume--;
|
||||
--mCurrentVoxel;
|
||||
m_bIsCurrentPositionValidInX = this->mVolume->getEnclosingRegion().containsPointInX(this->mXPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::Sampler::moveNegativeY(void)
|
||||
{
|
||||
this->mYPosInVolume--;
|
||||
mCurrentVoxel -= this->mVolume->getWidth();
|
||||
m_bIsCurrentPositionValidInY = this->mVolume->getEnclosingRegion().containsPointInY(this->mYPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void RawVolume<VoxelType>::Sampler::moveNegativeZ(void)
|
||||
{
|
||||
this->mZPosInVolume--;
|
||||
mCurrentVoxel -= this->mVolume->getWidth() * this->mVolume->getHeight();
|
||||
m_bIsCurrentPositionValidInZ = this->mVolume->getEnclosingRegion().containsPointInZ(this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_LOWY(this->mYPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_LOWY(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->getWidth());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_LOWY(this->mYPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx0py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx0py0pz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx0py1pz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx1py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_HIGHY(this->mYPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx1py0pz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_HIGHY(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->getWidth());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1nx1py1pz(void) const
|
||||
{
|
||||
if( BORDER_LOWX(this->mXPosInVolume) && BORDER_HIGHY(this->mYPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_LOWY(this->mYPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_LOWY(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->getWidth());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_LOWY(this->mYPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px0py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOWZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px0py0pz(void) const
|
||||
{
|
||||
return *mCurrentVoxel;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px0py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px1py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGHY(this->mYPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px1py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHY(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->getWidth());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel0px1py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHY(this->mYPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_LOWY(this->mYPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_LOWY(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->getWidth());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_LOWY(this->mYPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px0py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px0py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px0py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px1py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_HIGHY(this->mYPosInVolume) && BORDER_LOWZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px1py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_HIGHY(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->getWidth());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType RawVolume<VoxelType>::Sampler::peekVoxel1px1py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGHX(this->mXPosInVolume) && BORDER_HIGHY(this->mYPosInVolume) && BORDER_HIGHZ(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight());
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
}
|
||||
}
|
||||
|
||||
#undef BORDER_LOWX
|
||||
#undef BORDER_HIGHX
|
||||
#undef BORDER_LOWY
|
||||
#undef BORDER_HIGHY
|
||||
#undef BORDER_LOWZ
|
||||
#undef BORDER_HIGHZ
|
103
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Raycast.h
vendored
Normal file
103
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Raycast.h
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
/*******************************************************************************
|
||||
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_Raycast_H__
|
||||
#define __PolyVox_Raycast_H__
|
||||
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
namespace RaycastResults
|
||||
{
|
||||
/**
|
||||
* The results of a raycast
|
||||
*/
|
||||
enum RaycastResult
|
||||
{
|
||||
Completed, ///< If the ray passed through the volume without being interupted
|
||||
Interupted ///< If the ray was interupted while travelling
|
||||
};
|
||||
}
|
||||
typedef RaycastResults::RaycastResult RaycastResult;
|
||||
|
||||
/// OUT OF DATE SINCE UNCLASSING
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file Raycast.h
|
||||
///
|
||||
/// The principle behind raycasting is to fire a 'ray' through the volume and determine
|
||||
/// what (if anything) that ray hits. This simple test can be used for the purpose of
|
||||
/// picking, visibility checks, lighting calculations, or numerous other applications.
|
||||
///
|
||||
/// A ray is a stright line in space define by a start point and a direction vector.
|
||||
/// The length of the direction vector represents the length of the ray. When you call a
|
||||
/// Raycast object's execute() method it will iterate over each voxel which lies on the ray,
|
||||
/// starting from the defined start point. It will examine each voxel and terminate
|
||||
/// either when it encounters a solid voxel or when it reaches the end of the ray. If a
|
||||
/// solid voxel is encountered then its position is stored in the intersectionVoxel field
|
||||
/// of the RaycastResult structure and the intersectionFound flag is set to true, otherwise
|
||||
/// the intersectionFound flag is set to false.
|
||||
///
|
||||
/// **Important Note:** These has been confusion in the past with people not realising
|
||||
/// that the length of the direction vector is important. Most graphics API can provide
|
||||
/// a camera position and view direction for picking purposes, but the view direction is
|
||||
/// usually normalised (i.e. of length one). If you use this view direction directly you
|
||||
/// will only iterate over a single voxel and won't find what you are looking for. Instead
|
||||
/// you must scale the direction vector so that it's length represents the maximum distance
|
||||
/// over which you want the ray to be cast.
|
||||
///
|
||||
/// The following code snippet shows how the class is used:
|
||||
/// \code
|
||||
/// Vector3DFloat start(rayOrigin.x(), rayOrigin.y(), rayOrigin.z());
|
||||
/// Vector3DFloat direction(rayDir.x(), rayDir.y(), rayDir.z());
|
||||
/// direction.normalise();
|
||||
/// direction *= 1000.0f; //Casts ray of length 1000
|
||||
///
|
||||
/// RaycastResult raycastResult;
|
||||
/// Raycast<Material8> raycast(m_pPolyVoxVolume, start, direction, raycastResult);
|
||||
/// raycast.execute();
|
||||
///
|
||||
/// if(raycastResult.foundIntersection)
|
||||
/// {
|
||||
/// //...
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// Some further notes, the Raycast uses full 26-connectivity, which basically means it
|
||||
/// will examine every voxel the ray touches, even if it just passes through the corner.
|
||||
/// Also, it peforms a simple binary test against a voxel's threshold, rather than making
|
||||
/// use of it's density. Therefore it will work best in conjunction with one of the 'cubic'
|
||||
/// surace extractors. It's behaviour with the Marching Cubes surface extractor has not
|
||||
/// been tested yet.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename VolumeType, typename Callback>
|
||||
RaycastResult raycastWithEndpoints(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dEnd, Callback& callback);
|
||||
|
||||
template<typename VolumeType, typename Callback>
|
||||
RaycastResult raycastWithDirection(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirectionAndLength, Callback& callback);
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/Raycast.inl"
|
||||
|
||||
#endif //__PolyVox_Raycast_H__
|
178
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Raycast.inl
vendored
Normal file
178
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Raycast.inl
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
// This function is based on Christer Ericson's code and description of the 'Uniform Grid Intersection Test' in
|
||||
// 'Real Time Collision Detection'. The following information from the errata on the book website is also relevent:
|
||||
//
|
||||
// pages 326-327. In the function VisitCellsOverlapped() the two lines calculating tx and ty are incorrect.
|
||||
// The less-than sign in each line should be a greater-than sign. That is, the two lines should read:
|
||||
//
|
||||
// float tx = ((x1 > x2) ? (x1 - minx) : (maxx - x1)) / Abs(x2 - x1);
|
||||
// float ty = ((y1 > y2) ? (y1 - miny) : (maxy - y1)) / Abs(y2 - y1);
|
||||
//
|
||||
// Thanks to Jetro Lauha of Fathammer in Helsinki, Finland for reporting this error.
|
||||
//
|
||||
// Jetro also points out that the computations of i, j, iend, and jend are incorrectly rounded if the line
|
||||
// coordinates are allowed to go negative. While that was not really the intent of the code -- that is, I
|
||||
// assumed grids to be numbered from (0, 0) to (m, n) -- I'm at fault for not making my assumption clear.
|
||||
// Where it is important to handle negative line coordinates the computation of these variables should be
|
||||
// changed to something like this:
|
||||
//
|
||||
// // Determine start grid cell coordinates (i, j)
|
||||
// int i = (int)floorf(x1 / CELL_SIDE);
|
||||
// int j = (int)floorf(y1 / CELL_SIDE);
|
||||
//
|
||||
// // Determine end grid cell coordinates (iend, jend)
|
||||
// int iend = (int)floorf(x2 / CELL_SIDE);
|
||||
// int jend = (int)floorf(y2 / CELL_SIDE);
|
||||
//
|
||||
// page 328. The if-statement that reads "if (ty <= tx && ty <= tz)" has a superfluous condition.
|
||||
// It should simply read "if (ty <= tz)".
|
||||
//
|
||||
// This error was reported by Joey Hammer (PixelActive).
|
||||
|
||||
/**
|
||||
* Cast a ray through a volume by specifying the start and end positions
|
||||
*
|
||||
* The ray will move from \a v3dStart to \a v3dEnd, calling \a callback for each
|
||||
* voxel it passes through until \a callback returns \a false. In this case it
|
||||
* returns a RaycastResults::Interupted. If it passes from start to end
|
||||
* without \a callback returning \a false, it returns RaycastResults::Completed.
|
||||
*
|
||||
* \param volData The volume to pass the ray though
|
||||
* \param v3dStart The start position in the volume
|
||||
* \param v3dEnd The end position in the volume
|
||||
* \param callback The callback to call for each voxel
|
||||
*
|
||||
* \return A RaycastResults designating whether the ray hit anything or not
|
||||
*/
|
||||
template<typename VolumeType, typename Callback>
|
||||
RaycastResult raycastWithEndpoints(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dEnd, Callback& callback)
|
||||
{
|
||||
typename VolumeType::Sampler sampler(volData);
|
||||
|
||||
//The doRaycast function is assuming that it is iterating over the areas defined between
|
||||
//voxels. We actually want to define the areas as being centered on voxels (as this is
|
||||
//what the CubicSurfaceExtractor generates). We add 0.5 here to adjust for this.
|
||||
float x1 = v3dStart.getX() + 0.5f;
|
||||
float y1 = v3dStart.getY() + 0.5f;
|
||||
float z1 = v3dStart.getZ() + 0.5f;
|
||||
float x2 = v3dEnd.getX() + 0.5f;
|
||||
float y2 = v3dEnd.getY() + 0.5f;
|
||||
float z2 = v3dEnd.getZ() + 0.5f;
|
||||
|
||||
int i = (int)floorf(x1);
|
||||
int j = (int)floorf(y1);
|
||||
int k = (int)floorf(z1);
|
||||
|
||||
int iend = (int)floorf(x2);
|
||||
int jend = (int)floorf(y2);
|
||||
int kend = (int)floorf(z2);
|
||||
|
||||
int di = ((x1 < x2) ? 1 : ((x1 > x2) ? -1 : 0));
|
||||
int dj = ((y1 < y2) ? 1 : ((y1 > y2) ? -1 : 0));
|
||||
int dk = ((z1 < z2) ? 1 : ((z1 > z2) ? -1 : 0));
|
||||
|
||||
float deltatx = 1.0f / std::abs(x2 - x1);
|
||||
float deltaty = 1.0f / std::abs(y2 - y1);
|
||||
float deltatz = 1.0f / std::abs(z2 - z1);
|
||||
|
||||
float minx = floorf(x1), maxx = minx + 1.0f;
|
||||
float tx = ((x1 > x2) ? (x1 - minx) : (maxx - x1)) * deltatx;
|
||||
float miny = floorf(y1), maxy = miny + 1.0f;
|
||||
float ty = ((y1 > y2) ? (y1 - miny) : (maxy - y1)) * deltaty;
|
||||
float minz = floorf(z1), maxz = minz + 1.0f;
|
||||
float tz = ((z1 > z2) ? (z1 - minz) : (maxz - z1)) * deltatz;
|
||||
|
||||
sampler.setPosition(i,j,k);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(!callback(sampler))
|
||||
{
|
||||
return RaycastResults::Interupted;
|
||||
}
|
||||
|
||||
if(tx <= ty && tx <= tz)
|
||||
{
|
||||
if(i == iend) break;
|
||||
tx += deltatx;
|
||||
i += di;
|
||||
|
||||
if(di == 1) sampler.movePositiveX();
|
||||
if(di == -1) sampler.moveNegativeX();
|
||||
} else if (ty <= tz)
|
||||
{
|
||||
if(j == jend) break;
|
||||
ty += deltaty;
|
||||
j += dj;
|
||||
|
||||
if(dj == 1) sampler.movePositiveY();
|
||||
if(dj == -1) sampler.moveNegativeY();
|
||||
} else
|
||||
{
|
||||
if(k == kend) break;
|
||||
tz += deltatz;
|
||||
k += dk;
|
||||
|
||||
if(dk == 1) sampler.movePositiveZ();
|
||||
if(dk == -1) sampler.moveNegativeZ();
|
||||
}
|
||||
}
|
||||
|
||||
return RaycastResults::Completed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast a ray through a volume by specifying the start and a direction
|
||||
*
|
||||
* The ray will move from \a v3dStart along \a v3dDirectionAndLength, calling
|
||||
* \a callback for each voxel it passes through until \a callback returns
|
||||
* \a false. In this case it returns a RaycastResults::Interupted. If it
|
||||
* passes from start to end without \a callback returning \a false, it
|
||||
* returns RaycastResults::Completed.
|
||||
*
|
||||
* \note These has been confusion in the past with people not realising
|
||||
* that the length of the direction vector is important. Most graphics API can provide
|
||||
* a camera position and view direction for picking purposes, but the view direction is
|
||||
* usually normalised (i.e. of length one). If you use this view direction directly you
|
||||
* will only iterate over a single voxel and won't find what you are looking for. Instead
|
||||
* you must scale the direction vector so that it's length represents the maximum distance
|
||||
* over which you want the ray to be cast.
|
||||
*
|
||||
* \param volData The volume to pass the ray though
|
||||
* \param v3dStart The start position in the volume
|
||||
* \param v3dDirectionAndLength The direction and length of the ray
|
||||
* \param callback The callback to call for each voxel
|
||||
*
|
||||
* \return A RaycastResults designating whether the ray hit anything or not
|
||||
*/
|
||||
template<typename VolumeType, typename Callback>
|
||||
RaycastResult raycastWithDirection(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirectionAndLength, Callback& callback)
|
||||
{
|
||||
Vector3DFloat v3dEnd = v3dStart + v3dDirectionAndLength;
|
||||
return raycastWithEndpoints<VolumeType, Callback>(volData, v3dStart, v3dEnd, callback);
|
||||
}
|
||||
}
|
126
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Region.h
vendored
Normal file
126
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Region.h
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
/*******************************************************************************
|
||||
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_Region_H__
|
||||
#define __PolyVox_Region_H__
|
||||
|
||||
#include "Impl/TypeDef.h"
|
||||
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/**
|
||||
Represents a part of a Volume.
|
||||
|
||||
Many operations in PolyVox are constrained to only part of a volume. For example, when running the surface extractors
|
||||
it is unlikely that you will want to run it on the whole volume at once, as this will give a very large mesh which may
|
||||
be too much to render. Instead you will probably want to run a surface extractor a number of times on different parts
|
||||
of the volume, there by giving a number of meshes which can be culled and rendered seperately.
|
||||
|
||||
The Region class is used to define these parts (regions) of the volume. Essentially it consists of an upper and lower
|
||||
bound which specify the range of voxels positions considered to be part of the region. Note that these bounds are
|
||||
<em>inclusive</em>. The class also provides functions for modifying the regions in a variety of ways.
|
||||
|
||||
\Note The dimensions of a region can be measured either in voxels or in cells. See the manual for more information
|
||||
about these definitions.
|
||||
*/
|
||||
#ifdef SWIG
|
||||
class Region
|
||||
#else
|
||||
class POLYVOX_API Region
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
|
||||
static const Region MaxRegion;
|
||||
|
||||
Region();
|
||||
Region(const Vector3DInt32& v3dLowerCorner, const Vector3DInt32& v3dUpperCorner);
|
||||
Region(int32_t iLowerX, int32_t iLowerY, int32_t iLowerZ, int32_t iUpperX, int32_t iUpperY, int32_t iUpperZ);
|
||||
|
||||
///Equality Operator.
|
||||
bool operator==(const Region& rhs) const;
|
||||
///Inequality Operator.
|
||||
bool operator!=(const Region& rhs) const;
|
||||
|
||||
const Vector3DInt32& getLowerCorner(void) const;
|
||||
const Vector3DInt32& getUpperCorner(void) const;
|
||||
|
||||
/// Gets the width of the region measured in voxels
|
||||
int32_t getWidthInVoxels(void) const;
|
||||
/// Gets the height of the region measured in voxels
|
||||
int32_t getHeightInVoxels(void) const;
|
||||
/// Gets the depth of the region measured in voxels
|
||||
int32_t getDepthInVoxels(void) const;
|
||||
/// Gets the dimensions of the region measured in voxels
|
||||
Vector3DInt32 getDimensionsInVoxels(void) const;
|
||||
|
||||
/// Gets the width of the region measured in cells
|
||||
int32_t getWidthInCells(void) const;
|
||||
/// Gets the height of the region measured in cells
|
||||
int32_t getHeightInCells(void) const;
|
||||
/// Gets the depth of the region measured in cells
|
||||
int32_t getDepthInCells(void) const;
|
||||
/// Gets the dimensions of the region measured in cells
|
||||
Vector3DInt32 getDimensionsInCells(void) const;
|
||||
|
||||
void setLowerCorner(const Vector3DInt32& v3dLowerCorner);
|
||||
void setUpperCorner(const Vector3DInt32& v3dUpperCorner);
|
||||
|
||||
bool containsPoint(const Vector3DFloat& pos, float boundary = 0.0f) const;
|
||||
bool containsPoint(const Vector3DInt32& pos, uint8_t boundary = 0) const;
|
||||
//FIXME - Don't like these. Make containsPoint take flags indicating which axes to check?
|
||||
bool containsPointInX(float pos, float boundary = 0.0f) const;
|
||||
bool containsPointInX(int32_t pos, uint8_t boundary = 0) const;
|
||||
bool containsPointInY(float pos, float boundary = 0.0f) const;
|
||||
bool containsPointInY(int32_t pos, uint8_t boundary = 0) const;
|
||||
bool containsPointInZ(float pos, float boundary = 0.0f) const;
|
||||
bool containsPointInZ(int32_t pos, uint8_t boundary = 0) const;
|
||||
void cropTo(const Region& other);
|
||||
/// Deprecated and misleading
|
||||
POLYVOX_DEPRECATED int32_t depth(void) const;
|
||||
/// Deprecated and misleading
|
||||
POLYVOX_DEPRECATED int32_t height(void) const;
|
||||
void shift(const Vector3DInt32& amount);
|
||||
void shiftLowerCorner(const Vector3DInt32& amount);
|
||||
void shiftUpperCorner(const Vector3DInt32& amount);
|
||||
//FIXME - Add dilate and erode functions?
|
||||
/// Deprecated and misleading
|
||||
POLYVOX_DEPRECATED Vector3DInt32 dimensions(void);
|
||||
/// Deprecated and misleading
|
||||
POLYVOX_DEPRECATED int32_t width(void) const;
|
||||
|
||||
private:
|
||||
Vector3DInt32 m_v3dLowerCorner;
|
||||
Vector3DInt32 m_v3dUpperCorner;
|
||||
|
||||
//FIXME - This variable is unused, but without it the OpenGL example crashes in release mode
|
||||
//when the volume size is 128^3 and the level of detail is 2. Very strange, but consistant.
|
||||
//Presubablly some kind of alignment issue? It started after this class was changed to use
|
||||
//int16's rather than int32's. To be investigated.
|
||||
uint8_t dummy;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
46
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/SimpleInterface.h
vendored
Normal file
46
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/SimpleInterface.h
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/*******************************************************************************
|
||||
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_SimpleInterface_H__
|
||||
#define __PolyVox_SimpleInterface_H__
|
||||
|
||||
#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.h"
|
||||
#include "PolyVoxCore/MaterialDensityPair.h"
|
||||
#include "PolyVoxCore/SimpleVolume.h"
|
||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
//The PolyVox simple interface only exposes one voxel type and one volume type. But if you like you can
|
||||
//adjust these typedefs and rebuild the library in order to modify which one volume and voxel is exposed.
|
||||
typedef SimpleVolume<MaterialDensityPair88> Volume;
|
||||
typedef SurfaceMesh<PositionMaterialNormal> Mesh;
|
||||
|
||||
/// \deprecated
|
||||
POLYVOX_DEPRECATED void extractCubicMesh(Volume& volume, const Region& region, Mesh& resultMesh);
|
||||
/// \deprecated
|
||||
POLYVOX_DEPRECATED void extractSmoothMesh(Volume& volume, const Region& region, Mesh& resultMesh);
|
||||
|
||||
}
|
||||
|
||||
#endif //__PolyVox_SimpleInterface_H__
|
218
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/SimpleVolume.h
vendored
Normal file
218
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/SimpleVolume.h
vendored
Normal file
@ -0,0 +1,218 @@
|
||||
/*******************************************************************************
|
||||
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_SimpleVolume_H__
|
||||
#define __PolyVox_SimpleVolume_H__
|
||||
|
||||
#include "Impl/Utility.h"
|
||||
|
||||
#include "PolyVoxCore/BaseVolume.h"
|
||||
#include "PolyVoxCore/Log.h"
|
||||
#include "PolyVoxCore/Region.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib> //For abort()
|
||||
#include <cstring> //For memcpy
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <stdexcept> //For invalid_argument
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
class SimpleVolume : public BaseVolume<VoxelType>
|
||||
{
|
||||
public:
|
||||
#ifndef SWIG
|
||||
//Could be made private?
|
||||
class Block
|
||||
{
|
||||
public:
|
||||
Block(uint16_t uSideLength = 0);
|
||||
~Block();
|
||||
|
||||
uint16_t getSideLength(void) const;
|
||||
VoxelType getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const;
|
||||
VoxelType getVoxelAt(const Vector3DUint16& v3dPos) const;
|
||||
|
||||
void setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue);
|
||||
void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue);
|
||||
|
||||
void fill(VoxelType tValue);
|
||||
void initialise(uint16_t uSideLength);
|
||||
uint32_t calculateSizeInBytes(void);
|
||||
|
||||
public:
|
||||
VoxelType* m_tUncompressedData;
|
||||
uint16_t m_uSideLength;
|
||||
uint8_t m_uSideLengthPower;
|
||||
};
|
||||
|
||||
//There seems to be some descrepency between Visual Studio and GCC about how the following class should be declared.
|
||||
//There is a work around (see also See http://goo.gl/qu1wn) given below which appears to work on VS2010 and GCC, but
|
||||
//which seems to cause internal compiler errors on VS2008 when building with the /Gm 'Enable Minimal Rebuild' compiler
|
||||
//option. For now it seems best to 'fix' it with the preprocessor insstead, but maybe the workaround can be reinstated
|
||||
//in the future
|
||||
//typedef Volume<VoxelType> VolumeOfVoxelType; //Workaround for GCC/VS2010 differences.
|
||||
//class Sampler : public VolumeOfVoxelType::template Sampler< SimpleVolume<VoxelType> >
|
||||
#if defined(_MSC_VER)
|
||||
class Sampler : public BaseVolume<VoxelType>::Sampler< SimpleVolume<VoxelType> > //This line works on VS2010
|
||||
#else
|
||||
class Sampler : public BaseVolume<VoxelType>::template Sampler< SimpleVolume<VoxelType> > //This line works on GCC
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
/// Construct a new Sampler
|
||||
Sampler(SimpleVolume<VoxelType>* volume);
|
||||
~Sampler();
|
||||
|
||||
Sampler& operator=(const Sampler& rhs);
|
||||
|
||||
VoxelType getSubSampledVoxel(uint8_t uLevel) const;
|
||||
/// Get the value of the current voxel
|
||||
inline VoxelType getVoxel(void) const;
|
||||
|
||||
/// Set the current voxel position
|
||||
void setPosition(const Vector3DInt32& v3dNewPos);
|
||||
/// Set the current voxel position
|
||||
void setPosition(int32_t xPos, int32_t yPos, int32_t zPos);
|
||||
/// Set the value of the current voxel
|
||||
inline bool setVoxel(VoxelType tValue);
|
||||
|
||||
/// Increase the \a x position by \a 1
|
||||
void movePositiveX(void);
|
||||
/// Increase the \a y position by \a 1
|
||||
void movePositiveY(void);
|
||||
/// Increase the \a z position by \a 1
|
||||
void movePositiveZ(void);
|
||||
|
||||
/// Decrease the \a x position by \a 1
|
||||
void moveNegativeX(void);
|
||||
/// Decrease the \a y position by \a 1
|
||||
void moveNegativeY(void);
|
||||
/// Decrease the \a z position by \a 1
|
||||
void moveNegativeZ(void);
|
||||
|
||||
inline VoxelType peekVoxel1nx1ny1nz(void) const;
|
||||
inline VoxelType peekVoxel1nx1ny0pz(void) const;
|
||||
inline VoxelType peekVoxel1nx1ny1pz(void) const;
|
||||
inline VoxelType peekVoxel1nx0py1nz(void) const;
|
||||
inline VoxelType peekVoxel1nx0py0pz(void) const;
|
||||
inline VoxelType peekVoxel1nx0py1pz(void) const;
|
||||
inline VoxelType peekVoxel1nx1py1nz(void) const;
|
||||
inline VoxelType peekVoxel1nx1py0pz(void) const;
|
||||
inline VoxelType peekVoxel1nx1py1pz(void) const;
|
||||
|
||||
inline VoxelType peekVoxel0px1ny1nz(void) const;
|
||||
inline VoxelType peekVoxel0px1ny0pz(void) const;
|
||||
inline VoxelType peekVoxel0px1ny1pz(void) const;
|
||||
inline VoxelType peekVoxel0px0py1nz(void) const;
|
||||
inline VoxelType peekVoxel0px0py0pz(void) const;
|
||||
inline VoxelType peekVoxel0px0py1pz(void) const;
|
||||
inline VoxelType peekVoxel0px1py1nz(void) const;
|
||||
inline VoxelType peekVoxel0px1py0pz(void) const;
|
||||
inline VoxelType peekVoxel0px1py1pz(void) const;
|
||||
|
||||
inline VoxelType peekVoxel1px1ny1nz(void) const;
|
||||
inline VoxelType peekVoxel1px1ny0pz(void) const;
|
||||
inline VoxelType peekVoxel1px1ny1pz(void) const;
|
||||
inline VoxelType peekVoxel1px0py1nz(void) const;
|
||||
inline VoxelType peekVoxel1px0py0pz(void) const;
|
||||
inline VoxelType peekVoxel1px0py1pz(void) const;
|
||||
inline VoxelType peekVoxel1px1py1nz(void) const;
|
||||
inline VoxelType peekVoxel1px1py0pz(void) const;
|
||||
inline VoxelType peekVoxel1px1py1pz(void) const;
|
||||
|
||||
private:
|
||||
//Other current position information
|
||||
VoxelType* mCurrentVoxel;
|
||||
};
|
||||
#endif
|
||||
|
||||
public:
|
||||
/// Constructor for creating a fixed size volume.
|
||||
SimpleVolume(const Region& regValid, uint16_t uBlockSideLength = 32);
|
||||
|
||||
/// Destructor
|
||||
~SimpleVolume();
|
||||
|
||||
/// Gets the value used for voxels which are outside the volume
|
||||
VoxelType getBorderValue(void) const;
|
||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||
/// Gets a voxel at the position given by a 3D vector
|
||||
VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
|
||||
|
||||
/// Sets the value used for voxels which are outside the volume
|
||||
void setBorderValue(const VoxelType& tBorder);
|
||||
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||
bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue);
|
||||
/// Sets the voxel at the position given by a 3D vector
|
||||
bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue);
|
||||
|
||||
/// Calculates approximatly how many bytes of memory the volume is currently using.
|
||||
uint32_t calculateSizeInBytes(void);
|
||||
|
||||
protected:
|
||||
/// Copy constructor
|
||||
SimpleVolume(const SimpleVolume& rhs);
|
||||
|
||||
/// Assignment operator
|
||||
SimpleVolume& operator=(const SimpleVolume& rhs);
|
||||
|
||||
private:
|
||||
void initialise(const Region& regValidRegion, uint16_t uBlockSideLength);
|
||||
|
||||
Block* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const;
|
||||
|
||||
//The block data
|
||||
Block* m_pBlocks;
|
||||
|
||||
//We don't store an actual Block for the border, just the uncompressed data. This is partly because the border
|
||||
//block does not have a position (so can't be passed to getUncompressedBlock()) and partly because there's a
|
||||
//good chance we'll often hit it anyway. It's a chunk of homogenous data (rather than a single value) so that
|
||||
//the VolumeIterator can do it's usual pointer arithmetic without needing to know it's gone outside the volume.
|
||||
VoxelType* m_pUncompressedBorderData;
|
||||
|
||||
//The size of the volume in vlocks
|
||||
Region m_regValidRegionInBlocks;
|
||||
|
||||
//Volume size measured in blocks.
|
||||
uint32_t m_uNoOfBlocksInVolume;
|
||||
uint16_t m_uWidthInBlocks;
|
||||
uint16_t m_uHeightInBlocks;
|
||||
uint16_t m_uDepthInBlocks;
|
||||
|
||||
//The size of the blocks
|
||||
uint32_t m_uNoOfVoxelsPerBlock;
|
||||
uint16_t m_uBlockSideLength;
|
||||
uint8_t m_uBlockSideLengthPower;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/SimpleVolumeBlock.inl"
|
||||
#include "PolyVoxCore/SimpleVolume.inl"
|
||||
#include "PolyVoxCore/SimpleVolumeSampler.inl"
|
||||
|
||||
#endif //__PolyVox_SimpleVolume_H__
|
284
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/SimpleVolume.inl
vendored
Normal file
284
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/SimpleVolume.inl
vendored
Normal file
@ -0,0 +1,284 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This constructor creates a volume with a fixed size which is specified as a parameter.
|
||||
/// \param regValid Specifies the minimum and maximum valid voxel positions.
|
||||
/// \param uBlockSideLength The size of the block to use within the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
SimpleVolume<VoxelType>::SimpleVolume(const Region& regValid, uint16_t uBlockSideLength)
|
||||
:BaseVolume<VoxelType>(regValid)
|
||||
{
|
||||
//Create a volume of the right size.
|
||||
initialise(regValid,uBlockSideLength);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This function should never be called. Copying volumes by value would be expensive, and we want to prevent users from doing
|
||||
/// it by accident (such as when passing them as paramenters to functions). That said, there are times when you really do want to
|
||||
/// make a copy of a volume and in this case you should look at the Volumeresampler.
|
||||
///
|
||||
/// \sa VolumeResampler
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
SimpleVolume<VoxelType>::SimpleVolume(const SimpleVolume<VoxelType>& /*rhs*/)
|
||||
{
|
||||
assert(false); // See function comment above.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Destroys the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
SimpleVolume<VoxelType>::~SimpleVolume()
|
||||
{
|
||||
delete[] m_pBlocks;
|
||||
delete[] m_pUncompressedBorderData;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This function should never be called. Copying volumes by value would be expensive, and we want to prevent users from doing
|
||||
/// it by accident (such as when passing them as paramenters to functions). That said, there are times when you really do want to
|
||||
/// make a copy of a volume and in this case you should look at the Volumeresampler.
|
||||
///
|
||||
/// \sa VolumeResampler
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
SimpleVolume<VoxelType>& SimpleVolume<VoxelType>::operator=(const SimpleVolume<VoxelType>& /*rhs*/)
|
||||
{
|
||||
assert(false); // See function comment above.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// The border value is returned whenever an attempt is made to read a voxel which
|
||||
/// is outside the extents of the volume.
|
||||
/// \return The value used for voxels outside of the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::getBorderValue(void) const
|
||||
{
|
||||
return *m_pUncompressedBorderData;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param uXPos The \c x position of the voxel
|
||||
/// \param uYPos The \c y position of the voxel
|
||||
/// \param uZPos The \c z position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
|
||||
{
|
||||
if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)))
|
||||
{
|
||||
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
|
||||
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
|
||||
const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
|
||||
|
||||
const uint16_t xOffset = static_cast<uint16_t>(uXPos - (blockX << m_uBlockSideLengthPower));
|
||||
const uint16_t yOffset = static_cast<uint16_t>(uYPos - (blockY << m_uBlockSideLengthPower));
|
||||
const uint16_t zOffset = static_cast<uint16_t>(uZPos - (blockZ << m_uBlockSideLengthPower));
|
||||
|
||||
typename SimpleVolume<VoxelType>::Block* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||
|
||||
return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return getBorderValue();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos The 3D position of the voxel
|
||||
/// \return The voxel value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::getVoxelAt(const Vector3DInt32& v3dPos) const
|
||||
{
|
||||
return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param tBorder The value to use for voxels outside the volume.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::setBorderValue(const VoxelType& tBorder)
|
||||
{
|
||||
/*Block<VoxelType>* pUncompressedBorderBlock = getUncompressedBlock(&m_pBorderBlock);
|
||||
return pUncompressedBorderBlock->fill(tBorder);*/
|
||||
std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uNoOfVoxelsPerBlock, tBorder);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param uXPos the \c x position of the voxel
|
||||
/// \param uYPos the \c y position of the voxel
|
||||
/// \param uZPos the \c z position of the voxel
|
||||
/// \param tValue the value to which the voxel will be set
|
||||
/// \return whether the requested position is inside the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
bool SimpleVolume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue)
|
||||
{
|
||||
assert(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
|
||||
|
||||
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
|
||||
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
|
||||
const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
|
||||
|
||||
const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
|
||||
const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
|
||||
const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
|
||||
|
||||
typename SimpleVolume<VoxelType>::Block* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||
|
||||
pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
|
||||
|
||||
//Return true to indicate that we modified a voxel.
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \param v3dPos the 3D position of the voxel
|
||||
/// \param tValue the value to which the voxel will be set
|
||||
/// \return whether the requested position is inside the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
bool SimpleVolume<VoxelType>::setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue)
|
||||
{
|
||||
return setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This function should probably be made internal...
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::initialise(const Region& regValidRegion, uint16_t uBlockSideLength)
|
||||
{
|
||||
//Debug mode validation
|
||||
assert(uBlockSideLength >= 8);
|
||||
assert(uBlockSideLength <= 256);
|
||||
assert(isPowerOf2(uBlockSideLength));
|
||||
|
||||
//Release mode validation
|
||||
if(uBlockSideLength < 8)
|
||||
{
|
||||
throw std::invalid_argument("Block side length should be at least 8");
|
||||
}
|
||||
if(uBlockSideLength > 256)
|
||||
{
|
||||
throw std::invalid_argument("Block side length should not be more than 256");
|
||||
}
|
||||
if(!isPowerOf2(uBlockSideLength))
|
||||
{
|
||||
throw std::invalid_argument("Block side length must be a power of two.");
|
||||
}
|
||||
|
||||
//m_uBlockSideLength = uBlockSideLength;
|
||||
//m_uNoOfVoxelsPerBlock = m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength;
|
||||
m_pUncompressedBorderData = 0;
|
||||
|
||||
this->m_regValidRegion = regValidRegion;
|
||||
|
||||
//m_regValidRegionInBlocks.setLowerCorner(this->m_regValidRegion.getLowerCorner() / static_cast<int32_t>(uBlockSideLength));
|
||||
//m_regValidRegionInBlocks.setUpperCorner(this->m_regValidRegion.getUpperCorner() / static_cast<int32_t>(uBlockSideLength));
|
||||
|
||||
//Compute the block side length
|
||||
m_uBlockSideLength = uBlockSideLength;
|
||||
m_uBlockSideLengthPower = logBase2(m_uBlockSideLength);
|
||||
m_uNoOfVoxelsPerBlock = m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength;
|
||||
|
||||
//m_regValidRegionInBlocks.setLowerX(this->m_regValidRegion.getLowerX() >> m_uBlockSideLengthPower);
|
||||
//m_regValidRegionInBlocks.setLowerY(this->m_regValidRegion.getLowerY() >> m_uBlockSideLengthPower);
|
||||
//m_regValidRegionInBlocks.setLowerZ(this->m_regValidRegion.getLowerZ() >> m_uBlockSideLengthPower);
|
||||
m_regValidRegionInBlocks.setLowerCorner(Vector3DInt32(this->m_regValidRegion.getLowerCorner().getX() >> m_uBlockSideLengthPower, this->m_regValidRegion.getLowerCorner().getY() >> m_uBlockSideLengthPower, this->m_regValidRegion.getLowerCorner().getZ() >> m_uBlockSideLengthPower));
|
||||
//m_regValidRegionInBlocks.setUpperX(this->m_regValidRegion.getUpperX() >> m_uBlockSideLengthPower);
|
||||
//m_regValidRegionInBlocks.setUpperY(this->m_regValidRegion.getUpperY() >> m_uBlockSideLengthPower);
|
||||
//m_regValidRegionInBlocks.setUpperZ(this->m_regValidRegion.getUpperZ() >> m_uBlockSideLengthPower);
|
||||
m_regValidRegionInBlocks.setUpperCorner(Vector3DInt32(this->m_regValidRegion.getUpperCorner().getX() >> m_uBlockSideLengthPower, this->m_regValidRegion.getUpperCorner().getY() >> m_uBlockSideLengthPower, this->m_regValidRegion.getUpperCorner().getZ() >> m_uBlockSideLengthPower));
|
||||
|
||||
//Compute the size of the volume in blocks (and note +1 at the end)
|
||||
m_uWidthInBlocks = m_regValidRegionInBlocks.getUpperCorner().getX() - m_regValidRegionInBlocks.getLowerCorner().getX() + 1;
|
||||
m_uHeightInBlocks = m_regValidRegionInBlocks.getUpperCorner().getY() - m_regValidRegionInBlocks.getLowerCorner().getY() + 1;
|
||||
m_uDepthInBlocks = m_regValidRegionInBlocks.getUpperCorner().getZ() - m_regValidRegionInBlocks.getLowerCorner().getZ() + 1;
|
||||
m_uNoOfBlocksInVolume = m_uWidthInBlocks * m_uHeightInBlocks * m_uDepthInBlocks;
|
||||
|
||||
//Allocate the data
|
||||
m_pBlocks = new Block[m_uNoOfBlocksInVolume];
|
||||
for(uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i)
|
||||
{
|
||||
m_pBlocks[i].initialise(m_uBlockSideLength);
|
||||
}
|
||||
|
||||
//Create the border block
|
||||
m_pUncompressedBorderData = new VoxelType[m_uNoOfVoxelsPerBlock];
|
||||
std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uNoOfVoxelsPerBlock, VoxelType());
|
||||
|
||||
//Other properties we might find useful later
|
||||
this->m_uLongestSideLength = (std::max)((std::max)(this->getWidth(),this->getHeight()),this->getDepth());
|
||||
this->m_uShortestSideLength = (std::min)((std::min)(this->getWidth(),this->getHeight()),this->getDepth());
|
||||
this->m_fDiagonalLength = sqrtf(static_cast<float>(this->getWidth() * this->getWidth() + this->getHeight() * this->getHeight() + this->getDepth() * this->getDepth()));
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
typename SimpleVolume<VoxelType>::Block* SimpleVolume<VoxelType>::getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const
|
||||
{
|
||||
//The lower left corner of the volume could be
|
||||
//anywhere, but array indices need to start at zero.
|
||||
uBlockX -= m_regValidRegionInBlocks.getLowerCorner().getX();
|
||||
uBlockY -= m_regValidRegionInBlocks.getLowerCorner().getY();
|
||||
uBlockZ -= m_regValidRegionInBlocks.getLowerCorner().getZ();
|
||||
|
||||
//Compute the block index
|
||||
uint32_t uBlockIndex =
|
||||
uBlockX +
|
||||
uBlockY * m_uWidthInBlocks +
|
||||
uBlockZ * m_uWidthInBlocks * m_uHeightInBlocks;
|
||||
|
||||
//Return the block
|
||||
return &(m_pBlocks[uBlockIndex]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \todo This function needs reviewing for accuracy...
|
||||
///
|
||||
/// \return The number of bytes used
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
uint32_t SimpleVolume<VoxelType>::calculateSizeInBytes(void)
|
||||
{
|
||||
uint32_t uSizeInBytes = sizeof(SimpleVolume);
|
||||
|
||||
uint32_t uSizeOfBlockInBytes = m_uNoOfVoxelsPerBlock * sizeof(VoxelType);
|
||||
|
||||
//Memory used by the blocks ( + 1 is for border)
|
||||
uSizeInBytes += uSizeOfBlockInBytes * (m_uNoOfBlocksInVolume + 1);
|
||||
|
||||
return uSizeInBytes;
|
||||
}
|
||||
|
||||
}
|
||||
|
131
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/SimpleVolumeBlock.inl
vendored
Normal file
131
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/SimpleVolumeBlock.inl
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
SimpleVolume<VoxelType>::Block::Block(uint16_t uSideLength)
|
||||
:m_tUncompressedData(0)
|
||||
,m_uSideLength(0)
|
||||
,m_uSideLengthPower(0)
|
||||
{
|
||||
if(uSideLength != 0)
|
||||
{
|
||||
initialise(uSideLength);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
SimpleVolume<VoxelType>::Block::~Block()
|
||||
{
|
||||
delete[] m_tUncompressedData;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
uint16_t SimpleVolume<VoxelType>::Block::getSideLength(void) const
|
||||
{
|
||||
return m_uSideLength;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Block::getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const
|
||||
{
|
||||
assert(uXPos < m_uSideLength);
|
||||
assert(uYPos < m_uSideLength);
|
||||
assert(uZPos < m_uSideLength);
|
||||
|
||||
assert(m_tUncompressedData);
|
||||
|
||||
return m_tUncompressedData
|
||||
[
|
||||
uXPos +
|
||||
uYPos * m_uSideLength +
|
||||
uZPos * m_uSideLength * m_uSideLength
|
||||
];
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Block::getVoxelAt(const Vector3DUint16& v3dPos) const
|
||||
{
|
||||
return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Block::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue)
|
||||
{
|
||||
assert(uXPos < m_uSideLength);
|
||||
assert(uYPos < m_uSideLength);
|
||||
assert(uZPos < m_uSideLength);
|
||||
|
||||
assert(m_tUncompressedData);
|
||||
|
||||
m_tUncompressedData
|
||||
[
|
||||
uXPos +
|
||||
uYPos * m_uSideLength +
|
||||
uZPos * m_uSideLength * m_uSideLength
|
||||
] = tValue;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Block::setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue)
|
||||
{
|
||||
setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Block::fill(VoxelType tValue)
|
||||
{
|
||||
const uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength;
|
||||
std::fill(m_tUncompressedData, m_tUncompressedData + uNoOfVoxels, tValue);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Block::initialise(uint16_t uSideLength)
|
||||
{
|
||||
//Debug mode validation
|
||||
assert(isPowerOf2(uSideLength));
|
||||
|
||||
//Release mode validation
|
||||
if(!isPowerOf2(uSideLength))
|
||||
{
|
||||
throw std::invalid_argument("Block side length must be a power of two.");
|
||||
}
|
||||
|
||||
//Compute the side length
|
||||
m_uSideLength = uSideLength;
|
||||
m_uSideLengthPower = logBase2(uSideLength);
|
||||
|
||||
m_tUncompressedData = new VoxelType[m_uSideLength * m_uSideLength * m_uSideLength];
|
||||
|
||||
SimpleVolume<VoxelType>::Block::fill(VoxelType());
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
uint32_t SimpleVolume<VoxelType>::Block::calculateSizeInBytes(void)
|
||||
{
|
||||
uint32_t uSizeInBytes = sizeof(Block);
|
||||
uSizeInBytes += sizeof(VoxelType) * m_uSideLength * m_uSideLength * m_uSideLength;
|
||||
return uSizeInBytes;
|
||||
}
|
||||
}
|
546
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/SimpleVolumeSampler.inl
vendored
Normal file
546
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/SimpleVolumeSampler.inl
vendored
Normal file
@ -0,0 +1,546 @@
|
||||
/*******************************************************************************
|
||||
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.
|
||||
*******************************************************************************/
|
||||
|
||||
#define BORDER_LOW(x) ((( x >> this->mVolume->m_uBlockSideLengthPower) << this->mVolume->m_uBlockSideLengthPower) != x)
|
||||
#define BORDER_HIGH(x) ((( (x+1) >> this->mVolume->m_uBlockSideLengthPower) << this->mVolume->m_uBlockSideLengthPower) != (x+1))
|
||||
//#define BORDER_LOW(x) (( x % this->mVolume->m_uBlockSideLength) != 0)
|
||||
//#define BORDER_HIGH(x) (( x % this->mVolume->m_uBlockSideLength) != this->mVolume->m_uBlockSideLength - 1)
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/**
|
||||
* \param volume The SimpleVolume you want to sample
|
||||
*/
|
||||
template <typename VoxelType>
|
||||
SimpleVolume<VoxelType>::Sampler::Sampler(SimpleVolume<VoxelType>* volume)
|
||||
:BaseVolume<VoxelType>::template Sampler< SimpleVolume<VoxelType> >(volume)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
SimpleVolume<VoxelType>::Sampler::~Sampler()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
typename SimpleVolume<VoxelType>::Sampler& SimpleVolume<VoxelType>::Sampler::operator=(const typename SimpleVolume<VoxelType>::Sampler& rhs)
|
||||
{
|
||||
if(this == &rhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
this->mVolume = rhs.mVolume;
|
||||
this->mXPosInVolume = rhs.mXPosInVolume;
|
||||
this->mYPosInVolume = rhs.mYPosInVolume;
|
||||
this->mZPosInVolume = rhs.mZPosInVolume;
|
||||
mCurrentVoxel = rhs.mCurrentVoxel;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::getSubSampledVoxel(uint8_t uLevel) const
|
||||
{
|
||||
if(uLevel == 0)
|
||||
{
|
||||
return getVoxel();
|
||||
}
|
||||
else if(uLevel == 1)
|
||||
{
|
||||
VoxelType tValue = getVoxel();
|
||||
tValue = (std::min)(tValue, peekVoxel1px0py0pz());
|
||||
tValue = (std::min)(tValue, peekVoxel0px1py0pz());
|
||||
tValue = (std::min)(tValue, peekVoxel1px1py0pz());
|
||||
tValue = (std::min)(tValue, peekVoxel0px0py1pz());
|
||||
tValue = (std::min)(tValue, peekVoxel1px0py1pz());
|
||||
tValue = (std::min)(tValue, peekVoxel0px1py1pz());
|
||||
tValue = (std::min)(tValue, peekVoxel1px1py1pz());
|
||||
return tValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t uSize = 1 << uLevel;
|
||||
|
||||
VoxelType tValue = (std::numeric_limits<VoxelType>::max)();
|
||||
for(uint8_t z = 0; z < uSize; ++z)
|
||||
{
|
||||
for(uint8_t y = 0; y < uSize; ++y)
|
||||
{
|
||||
for(uint8_t x = 0; x < uSize; ++x)
|
||||
{
|
||||
tValue = (std::min)(tValue, this->mVolume->getVoxelAt(this->mXPosInVolume + x, this->mYPosInVolume + y, this->mZPosInVolume + z));
|
||||
}
|
||||
}
|
||||
}
|
||||
return tValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The current voxel
|
||||
*/
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::getVoxel(void) const
|
||||
{
|
||||
return *mCurrentVoxel;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param v3dNewPos The position to set to
|
||||
*/
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Sampler::setPosition(const Vector3DInt32& v3dNewPos)
|
||||
{
|
||||
setPosition(v3dNewPos.getX(), v3dNewPos.getY(), v3dNewPos.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* \param xPos The \a x position to set to
|
||||
* \param yPos The \a y position to set to
|
||||
* \param zPos The \a z position to set to
|
||||
*/
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Sampler::setPosition(int32_t xPos, int32_t yPos, int32_t zPos)
|
||||
{
|
||||
this->mXPosInVolume = xPos;
|
||||
this->mYPosInVolume = yPos;
|
||||
this->mZPosInVolume = zPos;
|
||||
|
||||
const int32_t uXBlock = this->mXPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
const int32_t uYBlock = this->mYPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
const int32_t uZBlock = this->mZPosInVolume >> this->mVolume->m_uBlockSideLengthPower;
|
||||
|
||||
const uint16_t uXPosInBlock = static_cast<uint16_t>(this->mXPosInVolume - (uXBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
const uint16_t uYPosInBlock = static_cast<uint16_t>(this->mYPosInVolume - (uYBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
const uint16_t uZPosInBlock = static_cast<uint16_t>(this->mZPosInVolume - (uZBlock << this->mVolume->m_uBlockSideLengthPower));
|
||||
|
||||
const uint32_t uVoxelIndexInBlock = uXPosInBlock +
|
||||
uYPosInBlock * this->mVolume->m_uBlockSideLength +
|
||||
uZPosInBlock * this->mVolume->m_uBlockSideLength * this->mVolume->m_uBlockSideLength;
|
||||
|
||||
if(this->mVolume->m_regValidRegionInBlocks.containsPoint(Vector3DInt32(uXBlock, uYBlock, uZBlock)))
|
||||
{
|
||||
Block* pUncompressedCurrentBlock = this->mVolume->getUncompressedBlock(uXBlock, uYBlock, uZBlock);
|
||||
|
||||
mCurrentVoxel = pUncompressedCurrentBlock->m_tUncompressedData + uVoxelIndexInBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentVoxel = this->mVolume->m_pUncompressedBorderData + uVoxelIndexInBlock;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \details
|
||||
*
|
||||
* This function checks that the current voxel position that you're trying
|
||||
* to set is not outside the volume. If it is, this function returns
|
||||
* \a false, otherwise it will return \a true.
|
||||
*
|
||||
* \param tValue The value to set to voxel to
|
||||
*/
|
||||
template <typename VoxelType>
|
||||
bool SimpleVolume<VoxelType>::Sampler::setVoxel(VoxelType tValue)
|
||||
{
|
||||
VoxelType* pBorderDataEndPlusOne = this->mVolume->m_pUncompressedBorderData + this->mVolume->m_uNoOfVoxelsPerBlock;
|
||||
|
||||
//Make sure we're not trying to write to the border data
|
||||
if((mCurrentVoxel < this->mVolume->m_pUncompressedBorderData) || (mCurrentVoxel >= pBorderDataEndPlusOne))
|
||||
{
|
||||
*mCurrentVoxel = tValue;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Sampler::movePositiveX(void)
|
||||
{
|
||||
//Note the *pre* increament here
|
||||
if((++this->mXPosInVolume) % this->mVolume->m_uBlockSideLength != 0)
|
||||
{
|
||||
//No need to compute new block.
|
||||
++mCurrentVoxel;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this.
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Sampler::movePositiveY(void)
|
||||
{
|
||||
//Note the *pre* increament here
|
||||
if((++this->mYPosInVolume) % this->mVolume->m_uBlockSideLength != 0)
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel += this->mVolume->m_uBlockSideLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this.
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Sampler::movePositiveZ(void)
|
||||
{
|
||||
//Note the *pre* increament here
|
||||
if((++this->mZPosInVolume) % this->mVolume->m_uBlockSideLength != 0)
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel += this->mVolume->m_uBlockSideLength * this->mVolume->m_uBlockSideLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this.
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Sampler::moveNegativeX(void)
|
||||
{
|
||||
//Note the *post* decreament here
|
||||
if((this->mXPosInVolume--) % this->mVolume->m_uBlockSideLength != 0)
|
||||
{
|
||||
//No need to compute new block.
|
||||
--mCurrentVoxel;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this.
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Sampler::moveNegativeY(void)
|
||||
{
|
||||
//Note the *post* decreament here
|
||||
if((this->mYPosInVolume--) % this->mVolume->m_uBlockSideLength != 0)
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel -= this->mVolume->m_uBlockSideLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this.
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void SimpleVolume<VoxelType>::Sampler::moveNegativeZ(void)
|
||||
{
|
||||
//Note the *post* decreament here
|
||||
if((this->mZPosInVolume--) % this->mVolume->m_uBlockSideLength != 0)
|
||||
{
|
||||
//No need to compute new block.
|
||||
mCurrentVoxel -= this->mVolume->m_uBlockSideLength * this->mVolume->m_uBlockSideLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We've hit the block boundary. Just calling setPosition() is the easiest way to resolve this.
|
||||
setPosition(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx0py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx0py0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx0py1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx1py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx1py0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1nx1py1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - 1 + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px0py1nz(void) const
|
||||
{
|
||||
if( BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px0py0pz(void) const
|
||||
{
|
||||
return *mCurrentVoxel;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px0py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px1py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px1py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel0px1py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px1ny1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px1ny0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px1ny1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px0py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px0py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px0py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px1py1nz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_LOW(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength - this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px1py0pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType SimpleVolume<VoxelType>::Sampler::peekVoxel1px1py1pz(void) const
|
||||
{
|
||||
if( BORDER_HIGH(this->mXPosInVolume) && BORDER_HIGH(this->mYPosInVolume) && BORDER_HIGH(this->mZPosInVolume) )
|
||||
{
|
||||
return *(mCurrentVoxel + 1 + this->mVolume->m_uBlockSideLength + this->mVolume->m_uBlockSideLength*this->mVolume->m_uBlockSideLength);
|
||||
}
|
||||
return this->mVolume->getVoxelAt(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1);
|
||||
}
|
||||
}
|
||||
|
||||
#undef BORDER_LOW
|
||||
#undef BORDER_HIGH
|
104
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/SurfaceMesh.h
vendored
Normal file
104
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/SurfaceMesh.h
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __PolyVox_SurfaceMesh_H__
|
||||
#define __PolyVox_SurfaceMesh_H__
|
||||
|
||||
#include "Impl/TypeDef.h"
|
||||
|
||||
#include "PolyVoxCore/Region.h"
|
||||
#include "PolyVoxCore/VertexTypes.h" //Should probably do away with this on in the future...
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
class LodRecord
|
||||
{
|
||||
public:
|
||||
int beginIndex;
|
||||
int endIndex; //Let's put it just past the end STL style
|
||||
};
|
||||
|
||||
template <typename VertexType>
|
||||
class SurfaceMesh
|
||||
{
|
||||
public:
|
||||
SurfaceMesh();
|
||||
~SurfaceMesh();
|
||||
|
||||
const std::vector<uint32_t>& getIndices(void) const;
|
||||
uint32_t getNoOfIndices(void) const;
|
||||
uint32_t getNoOfNonUniformTrianges(void) const;
|
||||
uint32_t getNoOfUniformTrianges(void) const;
|
||||
uint32_t getNoOfVertices(void) const;
|
||||
std::vector<VertexType>& getRawVertexData(void); //FIXME - this should be removed
|
||||
const std::vector<VertexType>& getVertices(void) const;
|
||||
|
||||
void addTriangle(uint32_t index0, uint32_t index1, uint32_t index2);
|
||||
void addTriangleCubic(uint32_t index0, uint32_t index1, uint32_t index2);
|
||||
uint32_t addVertex(const VertexType& vertex);
|
||||
void clear(void);
|
||||
bool isEmpty(void) const;
|
||||
|
||||
void scaleVertices(float amount);
|
||||
void translateVertices(const Vector3DFloat& amount);
|
||||
|
||||
//THESE FUNCTIONS TO BE REMOVED IN THE FUTURE. OR AT LEAST MOVED OUT OF THIS CLASS INTO FREE FUNCTIONS.
|
||||
//THEY ARE CAUSING PROBLEMS WITH THE SWIG BINDINGS. THE FUNCTIONS REGARDING NORMALS MAKE NO SENSE WHEN
|
||||
//A VERTEX MIGHT NOT HAVE NORMALS. THE EXTRACT SUBSET FUNCTION SHOULD MAYBE BE APPLICATION CODE, AT ANY
|
||||
//RATE THE STD::SET CAUSES PROBLEMS WITH SWIG. IF YOU UNCOMMENT ANY OF THESE FUNCTIONS, PLEASE POST ON
|
||||
//THE FORUM SO WE CAN KNOW THE FUNCTIONALITY IS STILL NEEDED IN SOME FORM.
|
||||
//void sumNearbyNormals(bool bNormaliseResult = true);
|
||||
//polyvox_shared_ptr< SurfaceMesh<VertexType> > extractSubset(std::set<uint8_t> setMaterials);
|
||||
//void generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices = false);
|
||||
|
||||
int noOfDegenerateTris(void);
|
||||
void removeDegenerateTris(void);
|
||||
void removeUnusedVertices(void);
|
||||
|
||||
Region m_Region;
|
||||
|
||||
int32_t m_iTimeStamp;
|
||||
|
||||
int32_t m_iNoOfLod0Tris;
|
||||
|
||||
public:
|
||||
std::vector<uint32_t> m_vecTriangleIndices;
|
||||
std::vector<VertexType> m_vecVertices;
|
||||
|
||||
std::vector<LodRecord> m_vecLodRecords;
|
||||
};
|
||||
|
||||
template <typename VertexType>
|
||||
polyvox_shared_ptr< SurfaceMesh<VertexType> > extractSubset(SurfaceMesh<VertexType>& inputMesh, std::set<uint8_t> setMaterials);
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/SurfaceMesh.inl"
|
||||
|
||||
#endif /* __SurfaceMesh_H__ */
|
488
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/SurfaceMesh.inl
vendored
Normal file
488
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/SurfaceMesh.inl
vendored
Normal file
@ -0,0 +1,488 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VertexType>
|
||||
SurfaceMesh<VertexType>::SurfaceMesh()
|
||||
{
|
||||
m_iTimeStamp = -1;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
SurfaceMesh<VertexType>::~SurfaceMesh()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
const std::vector<uint32_t>& SurfaceMesh<VertexType>::getIndices(void) const
|
||||
{
|
||||
return m_vecTriangleIndices;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
uint32_t SurfaceMesh<VertexType>::getNoOfIndices(void) const
|
||||
{
|
||||
return m_vecTriangleIndices.size();
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
uint32_t SurfaceMesh<VertexType>::getNoOfNonUniformTrianges(void) const
|
||||
{
|
||||
uint32_t result = 0;
|
||||
for(uint32_t i = 0; i < m_vecTriangleIndices.size() - 2; i += 3)
|
||||
{
|
||||
if((m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+1]].getMaterial())
|
||||
&& (m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+2]].getMaterial()))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
uint32_t SurfaceMesh<VertexType>::getNoOfUniformTrianges(void) const
|
||||
{
|
||||
uint32_t result = 0;
|
||||
for(uint32_t i = 0; i < m_vecTriangleIndices.size() - 2; i += 3)
|
||||
{
|
||||
if((m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+1]].getMaterial())
|
||||
&& (m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+2]].getMaterial()))
|
||||
{
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
uint32_t SurfaceMesh<VertexType>::getNoOfVertices(void) const
|
||||
{
|
||||
return m_vecVertices.size();
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
std::vector<VertexType>& SurfaceMesh<VertexType>::getRawVertexData(void)
|
||||
{
|
||||
return m_vecVertices;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
const std::vector<VertexType>& SurfaceMesh<VertexType>::getVertices(void) const
|
||||
{
|
||||
return m_vecVertices;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::addTriangle(uint32_t index0, uint32_t index1, uint32_t index2)
|
||||
{
|
||||
//Make sure the specified indices correspond to valid vertices.
|
||||
assert(index0 < m_vecVertices.size());
|
||||
assert(index1 < m_vecVertices.size());
|
||||
assert(index2 < m_vecVertices.size());
|
||||
|
||||
m_vecTriangleIndices.push_back(index0);
|
||||
m_vecTriangleIndices.push_back(index1);
|
||||
m_vecTriangleIndices.push_back(index2);
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::addTriangleCubic(uint32_t index0, uint32_t index1, uint32_t index2)
|
||||
{
|
||||
//Make sure the specified indices correspond to valid vertices.
|
||||
assert(index0 < m_vecVertices.size());
|
||||
assert(index1 < m_vecVertices.size());
|
||||
assert(index2 < m_vecVertices.size());
|
||||
|
||||
m_vecTriangleIndices.push_back(index0);
|
||||
m_vecTriangleIndices.push_back(index1);
|
||||
m_vecTriangleIndices.push_back(index2);
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
uint32_t SurfaceMesh<VertexType>::addVertex(const VertexType& vertex)
|
||||
{
|
||||
m_vecVertices.push_back(vertex);
|
||||
return m_vecVertices.size() - 1;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::clear(void)
|
||||
{
|
||||
m_vecVertices.clear();
|
||||
m_vecTriangleIndices.clear();
|
||||
m_vecLodRecords.clear();
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
bool SurfaceMesh<VertexType>::isEmpty(void) const
|
||||
{
|
||||
return (getNoOfVertices() == 0) || (getNoOfIndices() == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This function can help improve the visual appearance of a surface patch by
|
||||
/// smoothing normals with other nearby normals. It iterates over each triangle
|
||||
/// in the surface patch and determines the sum of its corners normals. For any
|
||||
/// given vertex, these sums are in turn summed for any triangles which use the
|
||||
/// vertex. Usually, the resulting normals should be renormalised afterwards.
|
||||
/// Note: This function can cause lighting discontinuities accross region boundaries.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/*template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::sumNearbyNormals(bool bNormaliseResult)
|
||||
{
|
||||
if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise...
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<Vector3DFloat> summedNormals(m_vecVertices.size());
|
||||
|
||||
//Initialise all normals to zero. Should be ok as the vector should store all elements contiguously.
|
||||
memset(&summedNormals[0], 0, summedNormals.size() * sizeof(Vector3DFloat));
|
||||
|
||||
for(vector<uint32_t>::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();)
|
||||
{
|
||||
PositionMaterialNormal& v0 = m_vecVertices[*iterIndex];
|
||||
Vector3DFloat& v0New = summedNormals[*iterIndex];
|
||||
iterIndex++;
|
||||
PositionMaterialNormal& v1 = m_vecVertices[*iterIndex];
|
||||
Vector3DFloat& v1New = summedNormals[*iterIndex];
|
||||
iterIndex++;
|
||||
PositionMaterialNormal& v2 = m_vecVertices[*iterIndex];
|
||||
Vector3DFloat& v2New = summedNormals[*iterIndex];
|
||||
iterIndex++;
|
||||
|
||||
Vector3DFloat sumOfNormals = v0.getNormal() + v1.getNormal() + v2.getNormal();
|
||||
|
||||
v0New += sumOfNormals;
|
||||
v1New += sumOfNormals;
|
||||
v2New += sumOfNormals;
|
||||
}
|
||||
|
||||
for(uint32_t uIndex = 0; uIndex < summedNormals.size(); uIndex++)
|
||||
{
|
||||
if(bNormaliseResult)
|
||||
{
|
||||
summedNormals[uIndex].normalise();
|
||||
}
|
||||
m_vecVertices[uIndex].setNormal(summedNormals[uIndex]);
|
||||
}
|
||||
}*/
|
||||
|
||||
/*template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices)
|
||||
{
|
||||
Vector3DFloat offset = static_cast<Vector3DFloat>(m_Region.getLowerCorner());
|
||||
|
||||
//Initially zero the normals
|
||||
for(vector<PositionMaterialNormal>::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++)
|
||||
{
|
||||
if(m_Region.containsPoint(iterVertex->getPosition() + offset, 0.001))
|
||||
{
|
||||
iterVertex->setNormal(Vector3DFloat(0.0f,0.0f,0.0f));
|
||||
}
|
||||
}
|
||||
|
||||
for(vector<uint32_t>::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();)
|
||||
{
|
||||
PositionMaterialNormal& v0 = m_vecVertices[*iterIndex];
|
||||
iterIndex++;
|
||||
PositionMaterialNormal& v1 = m_vecVertices[*iterIndex];
|
||||
iterIndex++;
|
||||
PositionMaterialNormal& v2 = m_vecVertices[*iterIndex];
|
||||
iterIndex++;
|
||||
|
||||
Vector3DFloat triangleNormal = (v1.getPosition()-v0.getPosition()).cross(v2.getPosition()-v0.getPosition());
|
||||
|
||||
if(m_Region.containsPoint(v0.getPosition() + offset, 0.001))
|
||||
{
|
||||
v0.setNormal(v0.getNormal() + triangleNormal);
|
||||
}
|
||||
if(m_Region.containsPoint(v1.getPosition() + offset, 0.001))
|
||||
{
|
||||
v1.setNormal(v1.getNormal() + triangleNormal);
|
||||
}
|
||||
if(m_Region.containsPoint(v2.getPosition() + offset, 0.001))
|
||||
{
|
||||
v2.setNormal(v2.getNormal() + triangleNormal);
|
||||
}
|
||||
}
|
||||
|
||||
if(bNormalise)
|
||||
{
|
||||
for(vector<PositionMaterialNormal>::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++)
|
||||
{
|
||||
Vector3DFloat normal = iterVertex->getNormal();
|
||||
normal.normalise();
|
||||
iterVertex->setNormal(normal);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/*template <typename VertexType>
|
||||
polyvox_shared_ptr< SurfaceMesh<VertexType> > SurfaceMesh<VertexType>::extractSubset(std::set<uint8_t> setMaterials)
|
||||
{
|
||||
polyvox_shared_ptr< SurfaceMesh<VertexType> > result(new SurfaceMesh<VertexType>);
|
||||
|
||||
if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise...
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
assert(m_vecLodRecords.size() == 1);
|
||||
if(m_vecLodRecords.size() != 1)
|
||||
{
|
||||
//If we have done progressive LOD then it's too late to split into subsets.
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<int32_t> indexMap(m_vecVertices.size());
|
||||
std::fill(indexMap.begin(), indexMap.end(), -1);
|
||||
|
||||
for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size(); triCt += 3)
|
||||
{
|
||||
|
||||
PositionMaterialNormal& v0 = m_vecVertices[m_vecTriangleIndices[triCt]];
|
||||
PositionMaterialNormal& v1 = m_vecVertices[m_vecTriangleIndices[triCt + 1]];
|
||||
PositionMaterialNormal& v2 = m_vecVertices[m_vecTriangleIndices[triCt + 2]];
|
||||
|
||||
if(
|
||||
(setMaterials.find(v0.getMaterial()) != setMaterials.end()) ||
|
||||
(setMaterials.find(v1.getMaterial()) != setMaterials.end()) ||
|
||||
(setMaterials.find(v2.getMaterial()) != setMaterials.end()))
|
||||
{
|
||||
uint32_t i0;
|
||||
if(indexMap[m_vecTriangleIndices[triCt]] == -1)
|
||||
{
|
||||
indexMap[m_vecTriangleIndices[triCt]] = result->addVertex(v0);
|
||||
}
|
||||
i0 = indexMap[m_vecTriangleIndices[triCt]];
|
||||
|
||||
uint32_t i1;
|
||||
if(indexMap[m_vecTriangleIndices[triCt+1]] == -1)
|
||||
{
|
||||
indexMap[m_vecTriangleIndices[triCt+1]] = result->addVertex(v1);
|
||||
}
|
||||
i1 = indexMap[m_vecTriangleIndices[triCt+1]];
|
||||
|
||||
uint32_t i2;
|
||||
if(indexMap[m_vecTriangleIndices[triCt+2]] == -1)
|
||||
{
|
||||
indexMap[m_vecTriangleIndices[triCt+2]] = result->addVertex(v2);
|
||||
}
|
||||
i2 = indexMap[m_vecTriangleIndices[triCt+2]];
|
||||
|
||||
result->addTriangle(i0,i1,i2);
|
||||
}
|
||||
}
|
||||
|
||||
result->m_vecLodRecords.clear();
|
||||
LodRecord lodRecord;
|
||||
lodRecord.beginIndex = 0;
|
||||
lodRecord.endIndex = result->getNoOfIndices();
|
||||
result->m_vecLodRecords.push_back(lodRecord);
|
||||
|
||||
return result;
|
||||
}*/
|
||||
|
||||
template <typename VertexType>
|
||||
int SurfaceMesh<VertexType>::noOfDegenerateTris(void)
|
||||
{
|
||||
int count = 0;
|
||||
for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size();)
|
||||
{
|
||||
int v0 = m_vecTriangleIndices[triCt];
|
||||
triCt++;
|
||||
int v1 = m_vecTriangleIndices[triCt];
|
||||
triCt++;
|
||||
int v2 = m_vecTriangleIndices[triCt];
|
||||
triCt++;
|
||||
|
||||
if((v0 == v1) || (v1 == v2) || (v2 == v0))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::removeDegenerateTris(void)
|
||||
{
|
||||
int noOfNonDegenerate = 0;
|
||||
int targetCt = 0;
|
||||
for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size();)
|
||||
{
|
||||
int v0 = m_vecTriangleIndices[triCt];
|
||||
triCt++;
|
||||
int v1 = m_vecTriangleIndices[triCt];
|
||||
triCt++;
|
||||
int v2 = m_vecTriangleIndices[triCt];
|
||||
triCt++;
|
||||
|
||||
if((v0 != v1) && (v1 != v2) & (v2 != v0))
|
||||
{
|
||||
m_vecTriangleIndices[targetCt] = v0;
|
||||
targetCt++;
|
||||
m_vecTriangleIndices[targetCt] = v1;
|
||||
targetCt++;
|
||||
m_vecTriangleIndices[targetCt] = v2;
|
||||
targetCt++;
|
||||
|
||||
noOfNonDegenerate++;
|
||||
}
|
||||
}
|
||||
|
||||
m_vecTriangleIndices.resize(noOfNonDegenerate * 3);
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::removeUnusedVertices(void)
|
||||
{
|
||||
std::vector<bool> isVertexUsed(m_vecVertices.size());
|
||||
fill(isVertexUsed.begin(), isVertexUsed.end(), false);
|
||||
|
||||
for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size(); triCt++)
|
||||
{
|
||||
int v = m_vecTriangleIndices[triCt];
|
||||
isVertexUsed[v] = true;
|
||||
}
|
||||
|
||||
int noOfUsedVertices = 0;
|
||||
std::vector<uint32_t> newPos(m_vecVertices.size());
|
||||
for(uint32_t vertCt = 0; vertCt < m_vecVertices.size(); vertCt++)
|
||||
{
|
||||
if(isVertexUsed[vertCt])
|
||||
{
|
||||
m_vecVertices[noOfUsedVertices] = m_vecVertices[vertCt];
|
||||
newPos[vertCt] = noOfUsedVertices;
|
||||
noOfUsedVertices++;
|
||||
}
|
||||
}
|
||||
|
||||
m_vecVertices.resize(noOfUsedVertices);
|
||||
|
||||
for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size(); triCt++)
|
||||
{
|
||||
m_vecTriangleIndices[triCt] = newPos[m_vecTriangleIndices[triCt]];
|
||||
}
|
||||
}
|
||||
|
||||
//Currently a free function - think where this needs to go.
|
||||
template <typename VertexType>
|
||||
polyvox_shared_ptr< SurfaceMesh<VertexType> > extractSubset(SurfaceMesh<VertexType>& inputMesh, std::set<uint8_t> setMaterials)
|
||||
{
|
||||
polyvox_shared_ptr< SurfaceMesh<VertexType> > result(new SurfaceMesh<VertexType>);
|
||||
|
||||
result->m_Region = inputMesh.m_Region;
|
||||
|
||||
if(inputMesh.m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise...
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
assert(inputMesh.m_vecLodRecords.size() == 1);
|
||||
if(inputMesh.m_vecLodRecords.size() != 1)
|
||||
{
|
||||
//If we have done progressive LOD then it's too late to split into subsets.
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<int32_t> indexMap(inputMesh.m_vecVertices.size());
|
||||
std::fill(indexMap.begin(), indexMap.end(), -1);
|
||||
|
||||
for(uint32_t triCt = 0; triCt < inputMesh.m_vecTriangleIndices.size(); triCt += 3)
|
||||
{
|
||||
|
||||
VertexType& v0 = inputMesh.m_vecVertices[inputMesh.m_vecTriangleIndices[triCt]];
|
||||
VertexType& v1 = inputMesh.m_vecVertices[inputMesh.m_vecTriangleIndices[triCt + 1]];
|
||||
VertexType& v2 = inputMesh.m_vecVertices[inputMesh.m_vecTriangleIndices[triCt + 2]];
|
||||
|
||||
if(
|
||||
(setMaterials.find(v0.getMaterial()) != setMaterials.end()) ||
|
||||
(setMaterials.find(v1.getMaterial()) != setMaterials.end()) ||
|
||||
(setMaterials.find(v2.getMaterial()) != setMaterials.end()))
|
||||
{
|
||||
uint32_t i0;
|
||||
if(indexMap[inputMesh.m_vecTriangleIndices[triCt]] == -1)
|
||||
{
|
||||
indexMap[inputMesh.m_vecTriangleIndices[triCt]] = result->addVertex(v0);
|
||||
}
|
||||
i0 = indexMap[inputMesh.m_vecTriangleIndices[triCt]];
|
||||
|
||||
uint32_t i1;
|
||||
if(indexMap[inputMesh.m_vecTriangleIndices[triCt+1]] == -1)
|
||||
{
|
||||
indexMap[inputMesh.m_vecTriangleIndices[triCt+1]] = result->addVertex(v1);
|
||||
}
|
||||
i1 = indexMap[inputMesh.m_vecTriangleIndices[triCt+1]];
|
||||
|
||||
uint32_t i2;
|
||||
if(indexMap[inputMesh.m_vecTriangleIndices[triCt+2]] == -1)
|
||||
{
|
||||
indexMap[inputMesh.m_vecTriangleIndices[triCt+2]] = result->addVertex(v2);
|
||||
}
|
||||
i2 = indexMap[inputMesh.m_vecTriangleIndices[triCt+2]];
|
||||
|
||||
result->addTriangle(i0,i1,i2);
|
||||
}
|
||||
}
|
||||
|
||||
result->m_vecLodRecords.clear();
|
||||
LodRecord lodRecord;
|
||||
lodRecord.beginIndex = 0;
|
||||
lodRecord.endIndex = result->getNoOfIndices();
|
||||
result->m_vecLodRecords.push_back(lodRecord);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::scaleVertices(float amount)
|
||||
{
|
||||
for(uint32_t ct = 0; ct < m_vecVertices.size(); ct++)
|
||||
{
|
||||
//TODO: Should rethink accessors here to provide faster access
|
||||
Vector3DFloat position = m_vecVertices[ct].getPosition();
|
||||
position *= amount;
|
||||
m_vecVertices[ct].setPosition(position);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::translateVertices(const Vector3DFloat& amount)
|
||||
{
|
||||
for(uint32_t ct = 0; ct < m_vecVertices.size(); ct++)
|
||||
{
|
||||
//TODO: Should rethink accessors here to provide faster access
|
||||
Vector3DFloat position = m_vecVertices[ct].getPosition();
|
||||
position += amount;
|
||||
m_vecVertices[ct].setPosition(position);
|
||||
}
|
||||
}
|
||||
}
|
195
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Vector.h
vendored
Normal file
195
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Vector.h
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
/*******************************************************************************
|
||||
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_Vector_H__
|
||||
#define __PolyVox_Vector_H__
|
||||
|
||||
#include "Impl/TypeDef.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/**
|
||||
Represents a vector in space.
|
||||
|
||||
This Vector class is templated on both size and data type. It is designed to be
|
||||
generic but so far had only been tested with vectors of size 2 and 3. Also note
|
||||
that some of the operations do not make sense with integer types, for example it
|
||||
does not make conceptual sense to try and normalise an integer Vector.
|
||||
|
||||
The elements of the Vector are accessed via the overloaded () operator which takes
|
||||
an index indicating the element to fetch. They are set using the set() function which
|
||||
takes an index indicating the element to set and a new value for that element. For
|
||||
convienience, the functions getX(), setX(), getY(), setY(), getZ(), setZ(), getw() and setW()
|
||||
do the same thing for the first 4 elements of the Vector.
|
||||
|
||||
A variety of overloaded operators are also provided for comparison and arithmetic
|
||||
operations. For most of these arithmetic operators only the unary versions are
|
||||
documented below - however often binary versions are also generated by std::operators.
|
||||
|
||||
Lastly, note that for convienience a set of typedefs are included for 2 and 3 dimensional
|
||||
vectors with type float, double, int32_t, and uint32_t. They are used as follows:
|
||||
|
||||
\code
|
||||
Vector2DInt4 test(1,2); //Declares a 2 dimensional Vector of type int4.
|
||||
\endcode
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
class Vector
|
||||
{
|
||||
public:
|
||||
///Constructor.
|
||||
Vector(Type x, Type y);
|
||||
///Constructor.
|
||||
Vector(Type x, Type y, Type z);
|
||||
///Constructor.
|
||||
Vector(Type x, Type y, Type z, Type w);
|
||||
///Constructor
|
||||
Vector(void);
|
||||
///Copy Constructor.
|
||||
Vector(const Vector<Size,Type>& vector);
|
||||
///Copy Constructor which performs casting.
|
||||
template <typename CastType> explicit Vector(const Vector<Size,CastType>& vector);
|
||||
///Destructor.
|
||||
~Vector(void);
|
||||
|
||||
///Assignment Operator.
|
||||
Vector<Size,Type>& operator=(const Vector<Size,Type>& rhs);
|
||||
///Equality Operator.
|
||||
bool operator==(const Vector<Size,Type>& rhs) const;
|
||||
///Inequality Operator.
|
||||
bool operator!=(const Vector<Size,Type>& rhs) const;
|
||||
///Comparison Operator.
|
||||
bool operator<(const Vector<Size,Type>& rhs) const;
|
||||
///Addition and Assignment Operator.
|
||||
Vector<Size,Type>& operator+=(const Vector<Size,Type> &rhs);
|
||||
///Subtraction and Assignment Operator.
|
||||
Vector<Size,Type>& operator-=(const Vector<Size,Type> &rhs);
|
||||
///Multiplication and Assignment Operator.
|
||||
Vector<Size,Type>& operator*=(const Vector<Size,Type> &rhs);
|
||||
///Division and Assignment Operator.
|
||||
Vector<Size,Type>& operator/=(const Vector<Size,Type> &rhs);
|
||||
///Multiplication and Assignment Operator.
|
||||
Vector<Size,Type>& operator*=(const Type& rhs);
|
||||
///Division and Assignment Operator.
|
||||
Vector<Size,Type>& operator/=(const Type& rhs);
|
||||
|
||||
///Element Access.
|
||||
Type getElement(uint32_t index) const;
|
||||
///Get the x component of the vector.
|
||||
Type getX(void) const;
|
||||
///Get the y component of the vector.
|
||||
Type getY(void) const;
|
||||
///Get the z component of the vector.
|
||||
Type getZ(void) const;
|
||||
///Get the w component of the vector.
|
||||
Type getW(void) const;
|
||||
|
||||
///Element Access.
|
||||
void setElement(uint32_t index, Type tValue);
|
||||
///Element Access.
|
||||
void setElements(Type x, Type y);
|
||||
///Element Access.
|
||||
void setElements(Type x, Type y, Type z);
|
||||
///Element Access.
|
||||
void setElements(Type x, Type y, Type z, Type w);
|
||||
///Set the x component of the vector.
|
||||
void setX(Type tX);
|
||||
///Set the y component of the vector.
|
||||
void setY(Type tY);
|
||||
///Set the z component of the vector.
|
||||
void setZ(Type tZ);
|
||||
///Set the w component of the vector.
|
||||
void setW(Type tW);
|
||||
|
||||
///Get the length of the vector.
|
||||
double length(void) const;
|
||||
///Get the squared length of the vector.
|
||||
double lengthSquared(void) const;
|
||||
///Find the angle between this vector and that which is passed as a parameter.
|
||||
double angleTo(const Vector<Size,Type>& vector) const;
|
||||
///Find the cross product between this vector and the vector passed as a parameter.
|
||||
Vector<Size,Type> cross(const Vector<Size,Type>& vector) const;
|
||||
///Find the dot product between this vector and the vector passed as a parameter.
|
||||
Type dot(const Vector<Size,Type>& rhs) const;
|
||||
///Normalise the vector.
|
||||
void normalise(void);
|
||||
|
||||
private:
|
||||
//Values for the vector
|
||||
Type m_tElements[Size];
|
||||
};
|
||||
|
||||
//Non-member overloaded operators.
|
||||
///Addition operator.
|
||||
template <uint32_t Size,typename Type>
|
||||
Vector<Size,Type> operator+(const Vector<Size,Type>& lhs, const Vector<Size,Type>& rhs);
|
||||
///Subtraction operator.
|
||||
template <uint32_t Size,typename Type>
|
||||
Vector<Size,Type> operator-(const Vector<Size,Type>& lhs, const Vector<Size,Type>& rhs);
|
||||
///Multiplication operator.
|
||||
template <uint32_t Size,typename Type>
|
||||
Vector<Size,Type> operator*(const Vector<Size,Type>& lhs, const Vector<Size,Type>& rhs);
|
||||
///Division operator.
|
||||
template <uint32_t Size,typename Type>
|
||||
Vector<Size,Type> operator/(const Vector<Size,Type>& lhs, const Vector<Size,Type>& rhs);
|
||||
///Multiplication operator.
|
||||
template <uint32_t Size,typename Type>
|
||||
Vector<Size,Type> operator*(const Vector<Size,Type>& lhs, const Type& rhs);
|
||||
///Division operator.
|
||||
template <uint32_t Size,typename Type>
|
||||
Vector<Size,Type> operator/(const Vector<Size,Type>& lhs, const Type& rhs);
|
||||
///Stream insertion operator.
|
||||
template <uint32_t Size, typename Type>
|
||||
std::ostream& operator<<(std::ostream& os, const Vector<Size,Type>& vector);
|
||||
|
||||
//Some handy typedefs
|
||||
///A 3D Vector of floats.
|
||||
typedef Vector<3,float> Vector3DFloat;
|
||||
///A 3D Vector of doubles.
|
||||
typedef Vector<3,double> Vector3DDouble;
|
||||
///A 3D Vector of signed 8-bit values.
|
||||
typedef Vector<3,int8_t> Vector3DInt8;
|
||||
///A 3D Vector of unsigned 8-bit values.
|
||||
typedef Vector<3,uint8_t> Vector3DUint8;
|
||||
///A 3D Vector of signed 16-bit values.
|
||||
typedef Vector<3,int16_t> Vector3DInt16;
|
||||
///A 3D Vector of unsigned 16-bit values.
|
||||
typedef Vector<3,uint16_t> Vector3DUint16;
|
||||
///A 3D Vector of signed 32-bit values.
|
||||
typedef Vector<3,int32_t> Vector3DInt32;
|
||||
///A 3D Vector of unsigned 32-bit values.
|
||||
typedef Vector<3,uint32_t> Vector3DUint32;
|
||||
|
||||
|
||||
|
||||
}//namespace PolyVox
|
||||
|
||||
#include "PolyVoxCore/Vector.inl"
|
||||
|
||||
#endif
|
||||
|
615
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Vector.inl
vendored
Normal file
615
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/Vector.inl
vendored
Normal file
@ -0,0 +1,615 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
//-------------------------- Constructors, etc ---------------------------------
|
||||
/**
|
||||
Creates a Vector object and initialises it with given values.
|
||||
\param x x component to set.
|
||||
\param y y component to set.
|
||||
*/
|
||||
template <uint32_t Size,typename Type>
|
||||
Vector<Size,Type>::Vector(Type x, Type y)
|
||||
{
|
||||
m_tElements[0] = x;
|
||||
m_tElements[1] = y;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a Vector3D object and initialises it with given values.
|
||||
\param x x component to set.
|
||||
\param y y component to set.
|
||||
\param z z component to set.
|
||||
*/
|
||||
template <uint32_t Size,typename Type>
|
||||
Vector<Size,Type>::Vector(Type x, Type y, Type z)
|
||||
{
|
||||
m_tElements[0] = x;
|
||||
m_tElements[1] = y;
|
||||
m_tElements[2] = z;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a Vector3D object and initialises it with given values.
|
||||
\param x x component to set.
|
||||
\param y y component to set.
|
||||
\param z z component to set.
|
||||
\param w w component to set.
|
||||
*/
|
||||
template <uint32_t Size,typename Type>
|
||||
Vector<Size,Type>::Vector(Type x, Type y, Type z, Type w)
|
||||
{
|
||||
m_tElements[0] = x;
|
||||
m_tElements[1] = y;
|
||||
m_tElements[2] = z;
|
||||
m_tElements[3] = w;
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a Vector object but does not initialise it.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
Vector<Size, Type>::Vector(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Copy constructor builds object based on object passed as parameter.
|
||||
\param vector A reference to the Vector to be copied.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
Vector<Size, Type>::Vector(const Vector<Size, Type>& vector)
|
||||
{
|
||||
std::memcpy(m_tElements, vector.m_tElements, sizeof(Type) * Size);
|
||||
}
|
||||
|
||||
/**
|
||||
This copy constructor allows casting between vectors with different data types.
|
||||
It is now possible to use code such as:
|
||||
|
||||
Vector3DDouble v3dDouble(1.0,2.0,3.0);
|
||||
Vector3DFloat v3dFloat = static_cast<Vector3DFloat>(v3dDouble); //Casting
|
||||
|
||||
\param vector A reference to the Vector to be copied.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
template <typename CastType>
|
||||
Vector<Size, Type>::Vector(const Vector<Size, CastType>& vector)
|
||||
{
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
m_tElements[ct] = static_cast<Type>(vector.getElement(ct));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Destroys the Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
Vector<Size, Type>::~Vector(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Assignment operator copies each element of first Vector to the second.
|
||||
\param rhs Vector to assign to.
|
||||
\return A reference to the result to allow chaining.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
Vector<Size, Type>& Vector<Size, Type>::operator=(const Vector<Size, Type>& rhs)
|
||||
{
|
||||
if(this == &rhs)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
std::memcpy(m_tElements, rhs.m_tElements, sizeof(Type) * Size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Checks whether two Vectors are equal.
|
||||
\param rhs The Vector to compare to.
|
||||
\return true if the Vectors match.
|
||||
\see operator!=
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline bool Vector<Size, Type>::operator==(const Vector<Size, Type> &rhs) const
|
||||
{
|
||||
bool equal = true;
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
if(m_tElements[ct] != rhs.m_tElements[ct])
|
||||
{
|
||||
equal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return equal;
|
||||
}
|
||||
|
||||
/**
|
||||
Checks whether two Vectors are not equal.
|
||||
\param rhs The Vector to compare to.
|
||||
\return true if the Vectors do not match.
|
||||
\see operator==
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline bool Vector<Size, Type>::operator!=(const Vector<Size, Type> &rhs) const
|
||||
{
|
||||
return !(*this == rhs); //Just call equality operator and invert the result.
|
||||
}
|
||||
|
||||
/**
|
||||
Checks whether this vector is less than the parameter. The metric is
|
||||
meaningless but it allows Vectors to me used as key in sdt::map, etc.
|
||||
\param rhs The Vector to compare to.
|
||||
\return true if this is less than the parameter
|
||||
\see operator!=
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline bool Vector<Size, Type>::operator<(const Vector<Size, Type> &rhs) const
|
||||
{
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
if (m_tElements[ct] < rhs.m_tElements[ct])
|
||||
return true;
|
||||
if (rhs.m_tElements[ct] < m_tElements[ct])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
Addition operator adds corresponding elements of the two Vectors.
|
||||
\param rhs Vector to add
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline Vector<Size, Type>& Vector<Size, Type>::operator+=(const Vector<Size, Type>& rhs)
|
||||
{
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
m_tElements[ct] += rhs.m_tElements[ct];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Subtraction operator subtracts corresponding elements of one Vector from the other.
|
||||
\param rhs Vector to subtract
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline Vector<Size, Type>& Vector<Size, Type>::operator-=(const Vector<Size, Type>& rhs)
|
||||
{
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
m_tElements[ct] -= rhs.m_tElements[ct];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Multiplication operator multiplies corresponding elements of the two Vectors.
|
||||
\param rhs Vector to multiply by
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline Vector<Size, Type>& Vector<Size, Type>::operator*=(const Vector<Size, Type>& rhs)
|
||||
{
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
m_tElements[ct] *= rhs.m_tElements[ct];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Division operator divides corresponding elements of one Vector by the other.
|
||||
\param rhs Vector to divide by
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline Vector<Size, Type>& Vector<Size, Type>::operator/=(const Vector<Size, Type>& rhs)
|
||||
{
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
m_tElements[ct] /= rhs.m_tElements[ct];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Multiplication operator multiplies each element of the Vector by a number.
|
||||
\param rhs the number the Vector is multiplied by.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline Vector<Size, Type>& Vector<Size, Type>::operator*=(const Type& rhs)
|
||||
{
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
m_tElements[ct] *= rhs;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Division operator divides each element of the Vector by a number.
|
||||
\param rhs the number the Vector is divided by.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline Vector<Size, Type>& Vector<Size, Type>::operator/=(const Type& rhs)
|
||||
{
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
m_tElements[ct] /= rhs;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Addition operator adds corresponding elements of the two Vectors.
|
||||
\param lhs Vector to add to.
|
||||
\param rhs Vector to add.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size,typename Type>
|
||||
Vector<Size,Type> operator+(const Vector<Size,Type>& lhs, const Vector<Size,Type>& rhs)
|
||||
{
|
||||
Vector<Size,Type> result = lhs;
|
||||
result += rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Subtraction operator subtracts corresponding elements of one Vector from the other.
|
||||
\param lhs Vector to subtract from.
|
||||
\param rhs Vector to subtract.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size,typename Type>
|
||||
Vector<Size,Type> operator-(const Vector<Size,Type>& lhs, const Vector<Size,Type>& rhs)
|
||||
{
|
||||
Vector<Size,Type> result = lhs;
|
||||
result -= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Multiplication operator mulitplies corresponding elements of the two Vectors.
|
||||
\param lhs Vector to multiply.
|
||||
\param rhs Vector to multiply by.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size,typename Type>
|
||||
Vector<Size,Type> operator*(const Vector<Size,Type>& lhs, const Vector<Size,Type>& rhs)
|
||||
{
|
||||
Vector<Size,Type> result = lhs;
|
||||
result *= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Division operator divides corresponding elements of one Vector by the other.
|
||||
\param lhs Vector to divide.
|
||||
\param rhs Vector to divide by.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size,typename Type>
|
||||
Vector<Size,Type> operator/(const Vector<Size,Type>& lhs, const Vector<Size,Type>& rhs)
|
||||
{
|
||||
Vector<Size,Type> result = lhs;
|
||||
result /= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Multiplication operator multiplies each element of the Vector by a number.
|
||||
\param lhs the Vector to multiply.
|
||||
\param rhs the number the Vector is multiplied by.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size,typename Type>
|
||||
Vector<Size,Type> operator*(const Vector<Size,Type>& lhs, const Type& rhs)
|
||||
{
|
||||
Vector<Size,Type> result = lhs;
|
||||
result *= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Division operator divides each element of the Vector by a number.
|
||||
\param lhs the Vector to divide.
|
||||
\param rhs the number the Vector is divided by.
|
||||
\return The resulting Vector.
|
||||
*/
|
||||
template <uint32_t Size,typename Type>
|
||||
Vector<Size,Type> operator/(const Vector<Size,Type>& lhs, const Type& rhs)
|
||||
{
|
||||
Vector<Size,Type> result = lhs;
|
||||
result /= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Enables the Vector to be used intuitively with output streams such as cout.
|
||||
\param os The output stream to write to.
|
||||
\param vector The Vector to write to the stream.
|
||||
\return A reference to the output stream to allow chaining.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
std::ostream& operator<<(std::ostream& os, const Vector<Size, Type>& vector)
|
||||
{
|
||||
os << "(";
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
os << vector.getElement(ct);
|
||||
if(ct < (Size-1))
|
||||
{
|
||||
os << ",";
|
||||
}
|
||||
}
|
||||
os << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the element at the given position.
|
||||
\param index The index of the element to return.
|
||||
\return The element.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline Type Vector<Size, Type>::getElement(uint32_t index) const
|
||||
{
|
||||
return m_tElements[index];
|
||||
}
|
||||
|
||||
/**
|
||||
\return A const reference to the X component of a 1, 2, 3, or 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline Type Vector<Size, Type>::getX(void) const
|
||||
{
|
||||
return m_tElements[0];
|
||||
}
|
||||
|
||||
/**
|
||||
\return A const reference to the Y component of a 2, 3, or 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline Type Vector<Size, Type>::getY(void) const
|
||||
{
|
||||
return m_tElements[1];
|
||||
}
|
||||
|
||||
/**
|
||||
\return A const reference to the Z component of a 3 or 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline Type Vector<Size, Type>::getZ(void) const
|
||||
{
|
||||
return m_tElements[2];
|
||||
}
|
||||
|
||||
/**
|
||||
\return A const reference to the W component of a 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline Type Vector<Size, Type>::getW(void) const
|
||||
{
|
||||
return m_tElements[3];
|
||||
}
|
||||
|
||||
/**
|
||||
\param index The index of the element to set.
|
||||
\param tValue The new value for the element.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline void Vector<Size, Type>::setElement(uint32_t index, Type tValue)
|
||||
{
|
||||
m_tElements[index] = tValue;
|
||||
}
|
||||
|
||||
/**
|
||||
Sets several elements of a vector at once.
|
||||
\param x x component to set.
|
||||
\param y y component to set.
|
||||
*/
|
||||
template <uint32_t Size,typename Type>
|
||||
inline void Vector<Size,Type>::setElements(Type x, Type y)
|
||||
{
|
||||
m_tElements[0] = x;
|
||||
m_tElements[1] = y;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Sets several elements of a vector at once.
|
||||
\param x x component to set.
|
||||
\param y y component to set.
|
||||
\param z z component to set.
|
||||
*/
|
||||
template <uint32_t Size,typename Type>
|
||||
inline void Vector<Size,Type>::setElements(Type x, Type y, Type z)
|
||||
{
|
||||
m_tElements[0] = x;
|
||||
m_tElements[1] = y;
|
||||
m_tElements[2] = z;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Sets several elements of a vector at once.
|
||||
\param x x component to set.
|
||||
\param y y component to set.
|
||||
\param z z component to set.
|
||||
\param w w component to set.
|
||||
*/
|
||||
template <uint32_t Size,typename Type>
|
||||
inline void Vector<Size,Type>::setElements(Type x, Type y, Type z, Type w)
|
||||
{
|
||||
m_tElements[0] = x;
|
||||
m_tElements[1] = y;
|
||||
m_tElements[2] = z;
|
||||
m_tElements[3] = w;
|
||||
}
|
||||
|
||||
/**
|
||||
\param tX The new value for the X component of a 1, 2, 3, or 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline void Vector<Size, Type>::setX(Type tX)
|
||||
{
|
||||
m_tElements[0] = tX;
|
||||
}
|
||||
|
||||
/**
|
||||
\param tY The new value for the Y component of a 2, 3, or 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline void Vector<Size, Type>::setY(Type tY)
|
||||
{
|
||||
m_tElements[1] = tY;
|
||||
}
|
||||
|
||||
/**
|
||||
\param tZ The new value for the Z component of a 3 or 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline void Vector<Size, Type>::setZ(Type tZ)
|
||||
{
|
||||
m_tElements[2] = tZ;
|
||||
}
|
||||
|
||||
/**
|
||||
\param tW The new value for the W component of a 4 dimensional Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline void Vector<Size, Type>::setW(Type tW)
|
||||
{
|
||||
m_tElements[3] = tW;
|
||||
}
|
||||
|
||||
/**
|
||||
\note This function does not make much sense on integer Vectors.
|
||||
\return Length of the Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline double Vector<Size, Type>::length(void) const
|
||||
{
|
||||
return sqrt(lengthSquared());
|
||||
}
|
||||
|
||||
/**
|
||||
\return Squared length of the Vector.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline double Vector<Size, Type>::lengthSquared(void) const
|
||||
{
|
||||
double result = 0.0f;
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
result += m_tElements[ct] * m_tElements[ct];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
This function is commutative, such that a.angleTo(b) == b.angleTo(a). The angle
|
||||
returned is in radians and varies between 0 and 3.14(pi). It is always positive.
|
||||
|
||||
\note This function does not make much sense on integer Vectors.
|
||||
|
||||
\param vector The Vector to find the angle to.
|
||||
\return The angle between them in radians.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline double Vector<Size, Type>::angleTo(const Vector<Size, Type>& vector) const
|
||||
{
|
||||
return acos(dot(vector) / (vector.length() * this->length()));
|
||||
}
|
||||
|
||||
/**
|
||||
This function is used to calculate the cross product of two Vectors.
|
||||
The cross product is the Vector which is perpendicular to the two
|
||||
given Vectors. It is worth remembering that, unlike the dot product,
|
||||
it is not commutative. E.g a.b != b.a. The cross product obeys the
|
||||
right-hand rule such that if the two vectors are given by the index
|
||||
finger and middle finger respectively then the cross product is given
|
||||
by the thumb.
|
||||
\param vector The vector to cross with this
|
||||
\return The value of the cross product.
|
||||
\see dot()
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline Vector<Size, Type> Vector<Size, Type>::cross(const Vector<Size, Type>& vector) const
|
||||
{
|
||||
Type i = vector.getZ() * this->getY() - vector.getY() * this->getZ();
|
||||
Type j = vector.getX() * this->getZ() - vector.getZ() * this->getX();
|
||||
Type k = vector.getY() * this->getX() - vector.getX() * this->getY();
|
||||
return Vector<Size, Type>(i,j,k);
|
||||
}
|
||||
|
||||
/**
|
||||
Calculates the dot product of the Vector and the parameter.
|
||||
This function is commutative, such that a.dot(b) == b.dot(a).
|
||||
\param rhs The Vector to find the dot product with.
|
||||
\return The value of the dot product.
|
||||
\see cross()
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline Type Vector<Size, Type>::dot(const Vector<Size, Type>& rhs) const
|
||||
{
|
||||
Type dotProduct = static_cast<Type>(0);
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
dotProduct += m_tElements[ct] * rhs.m_tElements[ct];
|
||||
}
|
||||
return dotProduct;
|
||||
}
|
||||
|
||||
/**
|
||||
Divides the i, j, and k components by the length to give a Vector of length 1.0.
|
||||
|
||||
\note This function does not make much sense on integer Vectors.
|
||||
*/
|
||||
template <uint32_t Size, typename Type>
|
||||
inline void Vector<Size, Type>::normalise(void)
|
||||
{
|
||||
Type tLength = static_cast<Type>(this->length());
|
||||
//FIXME - throw div by zero exception?
|
||||
if(tLength < 0.0001f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for(uint32_t ct = 0; ct < Size; ++ct)
|
||||
{
|
||||
m_tElements[ct] /= tLength;
|
||||
}
|
||||
}
|
||||
}//namespace PolyVox
|
85
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h
vendored
Normal file
85
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __PolyVox_SurfaceVertex_H__
|
||||
#define __PolyVox_SurfaceVertex_H__
|
||||
|
||||
#include "Impl/TypeDef.h"
|
||||
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
#include <bitset>
|
||||
#include <vector>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
#ifdef SWIG
|
||||
class PositionMaterial
|
||||
#else
|
||||
class POLYVOX_API PositionMaterial
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
PositionMaterial();
|
||||
PositionMaterial(Vector3DFloat positionToSet, float materialToSet);
|
||||
|
||||
float getMaterial(void) const;
|
||||
const Vector3DFloat& getPosition(void) const;
|
||||
|
||||
void setMaterial(float materialToSet);
|
||||
void setPosition(const Vector3DFloat& positionToSet);
|
||||
public:
|
||||
//Nicely fits into four floats.
|
||||
Vector3DFloat position;
|
||||
float material;
|
||||
};
|
||||
|
||||
#ifdef SWIG
|
||||
class PositionMaterialNormal
|
||||
#else
|
||||
class POLYVOX_API PositionMaterialNormal
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
PositionMaterialNormal();
|
||||
PositionMaterialNormal(Vector3DFloat positionToSet, float materialToSet);
|
||||
PositionMaterialNormal(Vector3DFloat positionToSet, Vector3DFloat normalToSet, float materialToSet);
|
||||
|
||||
float getMaterial(void) const;
|
||||
const Vector3DFloat& getNormal(void) const;
|
||||
const Vector3DFloat& getPosition(void) const;
|
||||
|
||||
void setMaterial(float materialToSet);
|
||||
void setNormal(const Vector3DFloat& normalToSet);
|
||||
void setPosition(const Vector3DFloat& positionToSet);
|
||||
|
||||
public:
|
||||
//Nicely fits into seven floats, meaning we
|
||||
//can squeeze in one more for material blending.
|
||||
Vector3DFloat position;
|
||||
Vector3DFloat normal;
|
||||
float material; //FIXME: This shouldn't be float on CPU?
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
57
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/VolumeResampler.h
vendored
Normal file
57
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/VolumeResampler.h
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
/*******************************************************************************
|
||||
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_VolumeResampler_H__
|
||||
#define __PolyVox_VolumeResampler_H__
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template< typename SrcVolumeType, typename DstVolumeType>
|
||||
class VolumeResampler
|
||||
{
|
||||
public:
|
||||
VolumeResampler(SrcVolumeType* pVolSrc, Region regSrc, DstVolumeType* pVolDst, Region regDst);
|
||||
|
||||
void execute();
|
||||
|
||||
private:
|
||||
void resampleSameSize();
|
||||
void resampleArbitrary();
|
||||
|
||||
//Source data
|
||||
SrcVolumeType* m_pVolSrc;
|
||||
Region m_regSrc;
|
||||
|
||||
//Destination data
|
||||
DstVolumeType* m_pVolDst;
|
||||
Region m_regDst;
|
||||
};
|
||||
|
||||
}//namespace PolyVox
|
||||
|
||||
#include "PolyVoxCore/VolumeResampler.inl"
|
||||
|
||||
#endif
|
||||
|
136
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/VolumeResampler.inl
vendored
Normal file
136
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/VolumeResampler.inl
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
/*******************************************************************************
|
||||
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 "PolyVoxCore/Interpolation.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/**
|
||||
* \param pVolSrc
|
||||
* \param regSrc
|
||||
* \param[out] pVolDst
|
||||
* \param regDst
|
||||
*/
|
||||
template< typename SrcVolumeType, typename DstVolumeType>
|
||||
VolumeResampler<SrcVolumeType, DstVolumeType>::VolumeResampler(SrcVolumeType* pVolSrc, Region regSrc, DstVolumeType* pVolDst, Region regDst)
|
||||
:m_pVolSrc(pVolSrc)
|
||||
,m_regSrc(regSrc)
|
||||
,m_pVolDst(pVolDst)
|
||||
,m_regDst(regDst)
|
||||
{
|
||||
}
|
||||
|
||||
template< typename SrcVolumeType, typename DstVolumeType>
|
||||
void VolumeResampler<SrcVolumeType, DstVolumeType>::execute()
|
||||
{
|
||||
int32_t uSrcWidth = m_regSrc.getUpperCorner().getX() - m_regSrc.getLowerCorner().getX() + 1;
|
||||
int32_t uSrcHeight = m_regSrc.getUpperCorner().getY() - m_regSrc.getLowerCorner().getY() + 1;
|
||||
int32_t uSrcDepth = m_regSrc.getUpperCorner().getZ() - m_regSrc.getLowerCorner().getZ() + 1;
|
||||
|
||||
int32_t uDstWidth = m_regDst.getUpperCorner().getX() - m_regDst.getLowerCorner().getX() + 1;
|
||||
int32_t uDstHeight = m_regDst.getUpperCorner().getY() - m_regDst.getLowerCorner().getY() + 1;
|
||||
int32_t uDstDepth = m_regDst.getUpperCorner().getZ() - m_regDst.getLowerCorner().getZ() + 1;
|
||||
|
||||
if((uSrcWidth == uDstWidth) && (uSrcHeight == uDstHeight) && (uSrcDepth == uDstDepth))
|
||||
{
|
||||
resampleSameSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
resampleArbitrary();
|
||||
}
|
||||
}
|
||||
|
||||
template< typename SrcVolumeType, typename DstVolumeType>
|
||||
void VolumeResampler<SrcVolumeType, DstVolumeType>::resampleSameSize()
|
||||
{
|
||||
for(int32_t sz = m_regSrc.getLowerCorner().getZ(), dz = m_regDst.getLowerCorner().getZ(); dz <= m_regDst.getUpperCorner().getZ(); sz++, dz++)
|
||||
{
|
||||
for(int32_t sy = m_regSrc.getLowerCorner().getY(), dy = m_regDst.getLowerCorner().getY(); dy <= m_regDst.getUpperCorner().getY(); sy++, dy++)
|
||||
{
|
||||
for(int32_t sx = m_regSrc.getLowerCorner().getX(), dx = m_regDst.getLowerCorner().getX(); dx <= m_regDst.getUpperCorner().getX(); sx++,dx++)
|
||||
{
|
||||
const typename SrcVolumeType::VoxelType& tSrcVoxel = m_pVolSrc->getVoxelAt(sx,sy,sz);
|
||||
const typename DstVolumeType::VoxelType& tDstVoxel = static_cast<typename DstVolumeType::VoxelType>(tSrcVoxel);
|
||||
m_pVolDst->setVoxelAt(dx,dy,dz,tDstVoxel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template< typename SrcVolumeType, typename DstVolumeType>
|
||||
void VolumeResampler<SrcVolumeType, DstVolumeType>::resampleArbitrary()
|
||||
{
|
||||
float srcWidth = m_regSrc.getUpperCorner().getX() - m_regSrc.getLowerCorner().getX();
|
||||
float srcHeight = m_regSrc.getUpperCorner().getY() - m_regSrc.getLowerCorner().getY();
|
||||
float srcDepth = m_regSrc.getUpperCorner().getZ() - m_regSrc.getLowerCorner().getZ();
|
||||
|
||||
float dstWidth = m_regDst.getUpperCorner().getX() - m_regDst.getLowerCorner().getX();
|
||||
float dstHeight = m_regDst.getUpperCorner().getY() - m_regDst.getLowerCorner().getY();
|
||||
float dstDepth = m_regDst.getUpperCorner().getZ() - m_regDst.getLowerCorner().getZ();
|
||||
|
||||
float fScaleX = srcWidth / dstWidth;
|
||||
float fScaleY = srcHeight / dstHeight;
|
||||
float fScaleZ = srcDepth / dstDepth;
|
||||
|
||||
typename SrcVolumeType::Sampler sampler(m_pVolSrc);
|
||||
|
||||
for(int32_t dz = m_regDst.getLowerCorner().getZ(); dz <= m_regDst.getUpperCorner().getZ(); dz++)
|
||||
{
|
||||
for(int32_t dy = m_regDst.getLowerCorner().getY(); dy <= m_regDst.getUpperCorner().getY(); dy++)
|
||||
{
|
||||
for(int32_t dx = m_regDst.getLowerCorner().getX(); dx <= m_regDst.getUpperCorner().getX(); dx++)
|
||||
{
|
||||
float sx = (dx - m_regDst.getLowerCorner().getX()) * fScaleX;
|
||||
float sy = (dy - m_regDst.getLowerCorner().getY()) * fScaleY;
|
||||
float sz = (dz - m_regDst.getLowerCorner().getZ()) * fScaleZ;
|
||||
|
||||
sx += m_regSrc.getLowerCorner().getX();
|
||||
sy += m_regSrc.getLowerCorner().getY();
|
||||
sz += m_regSrc.getLowerCorner().getZ();
|
||||
|
||||
sampler.setPosition(sx,sy,sz);
|
||||
const typename SrcVolumeType::VoxelType& voxel000 = sampler.peekVoxel0px0py0pz();
|
||||
const typename SrcVolumeType::VoxelType& voxel001 = sampler.peekVoxel0px0py1pz();
|
||||
const typename SrcVolumeType::VoxelType& voxel010 = sampler.peekVoxel0px1py0pz();
|
||||
const typename SrcVolumeType::VoxelType& voxel011 = sampler.peekVoxel0px1py1pz();
|
||||
const typename SrcVolumeType::VoxelType& voxel100 = sampler.peekVoxel1px0py0pz();
|
||||
const typename SrcVolumeType::VoxelType& voxel101 = sampler.peekVoxel1px0py1pz();
|
||||
const typename SrcVolumeType::VoxelType& voxel110 = sampler.peekVoxel1px1py0pz();
|
||||
const typename SrcVolumeType::VoxelType& voxel111 = sampler.peekVoxel1px1py1pz();
|
||||
|
||||
//FIXME - should accept all float parameters, but GCC complains?
|
||||
double dummy;
|
||||
sx = modf(sx, &dummy);
|
||||
sy = modf(sy, &dummy);
|
||||
sz = modf(sz, &dummy);
|
||||
|
||||
typename SrcVolumeType::VoxelType tInterpolatedValue = trilerp<float>(voxel000,voxel100,voxel010,voxel110,voxel001,voxel101,voxel011,voxel111,sx,sy,sz);
|
||||
|
||||
typename DstVolumeType::VoxelType result = static_cast<typename DstVolumeType::VoxelType>(tInterpolatedValue);
|
||||
m_pVolDst->setVoxelAt(dx,dy,dz,result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
37
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/VoxelFilters.h
vendored
Normal file
37
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/VoxelFilters.h
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
/*******************************************************************************
|
||||
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_VoxelFilters_H__
|
||||
#define __PolyVox_VoxelFilters_H__
|
||||
|
||||
#include "Impl/TypeDef.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template< typename VolumeType >
|
||||
float computeSmoothedVoxel(typename VolumeType::Sampler& volIter);
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/VoxelFilters.inl"
|
||||
|
||||
#endif
|
64
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/VoxelFilters.inl
vendored
Normal file
64
3rdparty/polyvox/library/PolyVoxCore/include/PolyVoxCore/VoxelFilters.inl
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template< typename VolumeType >
|
||||
float computeSmoothedVoxel(typename VolumeType::Sampler& volIter)
|
||||
{
|
||||
float sum = 0.0;
|
||||
|
||||
if(volIter.peekVoxel1nx1ny1nz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1nx1ny0pz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1nx1ny1pz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1nx0py1nz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1nx0py0pz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1nx0py1pz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1nx1py1nz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1nx1py0pz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1nx1py1pz() != 0) sum += 1.0f;
|
||||
|
||||
if(volIter.peekVoxel0px1ny1nz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel0px1ny0pz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel0px1ny1pz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel0px0py1nz() != 0) sum += 1.0f;
|
||||
if(volIter.getVoxel() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel0px0py1pz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel0px1py1nz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel0px1py0pz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel0px1py1pz() != 0) sum += 1.0f;
|
||||
|
||||
if(volIter.peekVoxel1px1ny1nz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1px1ny0pz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1px1ny1pz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1px0py1nz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1px0py0pz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1px0py1pz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1px1py1nz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1px1py0pz() != 0) sum += 1.0f;
|
||||
if(volIter.peekVoxel1px1py1pz() != 0) sum += 1.0f;
|
||||
|
||||
sum /= 27.0f;
|
||||
return sum;
|
||||
}
|
||||
}
|
67
3rdparty/polyvox/library/PolyVoxCore/source/AStarPathfinder.cpp
vendored
Normal file
67
3rdparty/polyvox/library/PolyVoxCore/source/AStarPathfinder.cpp
vendored
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.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "PolyVoxCore/AStarPathfinder.h"
|
||||
|
||||
using namespace PolyVox;
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
const Vector3DInt32 arrayPathfinderFaces[6] =
|
||||
{
|
||||
Vector3DInt32(0, 0, -1),
|
||||
Vector3DInt32(0, 0, +1),
|
||||
Vector3DInt32(0, -1, 0),
|
||||
Vector3DInt32(0, +1, 0),
|
||||
Vector3DInt32(-1, 0, 0),
|
||||
Vector3DInt32(+1, 0, 0)
|
||||
};
|
||||
|
||||
const Vector3DInt32 arrayPathfinderEdges[12] =
|
||||
{
|
||||
Vector3DInt32(0, -1, -1),
|
||||
Vector3DInt32(0, -1, +1),
|
||||
Vector3DInt32(0, +1, -1),
|
||||
Vector3DInt32(0, +1, +1),
|
||||
Vector3DInt32(-1, 0, -1),
|
||||
Vector3DInt32(-1, 0, +1),
|
||||
Vector3DInt32(+1, 0, -1),
|
||||
Vector3DInt32(+1, 0, +1),
|
||||
Vector3DInt32(-1, -1, 0),
|
||||
Vector3DInt32(-1, +1, 0),
|
||||
Vector3DInt32(+1, -1, 0),
|
||||
Vector3DInt32(+1, +1, 0)
|
||||
};
|
||||
|
||||
const Vector3DInt32 arrayPathfinderCorners[8] =
|
||||
{
|
||||
Vector3DInt32(-1, -1, -1),
|
||||
Vector3DInt32(-1, -1, +1),
|
||||
Vector3DInt32(-1, +1, -1),
|
||||
Vector3DInt32(-1, +1, +1),
|
||||
Vector3DInt32(+1, -1, -1),
|
||||
Vector3DInt32(+1, -1, +1),
|
||||
Vector3DInt32(+1, +1, -1),
|
||||
Vector3DInt32(+1, +1, +1)
|
||||
};
|
||||
}
|
55
3rdparty/polyvox/library/PolyVoxCore/source/ArraySizes.cpp
vendored
Normal file
55
3rdparty/polyvox/library/PolyVoxCore/source/ArraySizes.cpp
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
/*******************************************************************************
|
||||
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 "PolyVoxCore/ArraySizes.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/**
|
||||
\param uSize The size of the first dimension.
|
||||
*/
|
||||
ArraySizes::ArraySizes(uint32_t uSize)
|
||||
{
|
||||
m_pSizes[0]=uSize;
|
||||
}
|
||||
|
||||
/**
|
||||
This class only directly implements one dimensional sizes. Higher numbers
|
||||
of dimensions are implemented via the ArraySisesImpl class. This function
|
||||
create an object of the next dimensionality up.
|
||||
\param uSize The size of the next dimension.
|
||||
\return A higher dimension version of this class.
|
||||
*/
|
||||
ArraySizesImpl<2> ArraySizes::operator () (uint32_t uSize)
|
||||
{
|
||||
return ArraySizesImpl<2>(m_pSizes, uSize);
|
||||
}
|
||||
|
||||
/**
|
||||
\return The array of integers corresponding to this object.
|
||||
*/
|
||||
ArraySizes::operator UIntArray1 () const
|
||||
{
|
||||
return m_pSizes;
|
||||
}
|
||||
}
|
328
3rdparty/polyvox/library/PolyVoxCore/source/Impl/MarchingCubesTables.cpp
vendored
Normal file
328
3rdparty/polyvox/library/PolyVoxCore/source/Impl/MarchingCubesTables.cpp
vendored
Normal file
@ -0,0 +1,328 @@
|
||||
/*******************************************************************************
|
||||
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.
|
||||
*******************************************************************************/
|
||||
|
||||
//These tables were based on the article "Polygonising a scalar field".
|
||||
//They have been optimised to allow a more efficient algorithm via bitwise operations.
|
||||
|
||||
// http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/index.html
|
||||
|
||||
#include "PolyVoxCore/Impl/MarchingCubesTables.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
const int edgeTable[256]=
|
||||
{
|
||||
0x000, 0x109, 0x203, 0x30a, 0x80c, 0x905, 0xa0f, 0xb06,
|
||||
0x406, 0x50f, 0x605, 0x70c, 0xc0a, 0xd03, 0xe09, 0xf00,
|
||||
0x190, 0x099, 0x393, 0x29a, 0x99c, 0x895, 0xb9f, 0xa96,
|
||||
0x596, 0x49f, 0x795, 0x69c, 0xd9a, 0xc93, 0xf99, 0xe90,
|
||||
0x230, 0x339, 0x033, 0x13a, 0xa3c, 0xb35, 0x83f, 0x936,
|
||||
0x636, 0x73f, 0x435, 0x53c, 0xe3a, 0xf33, 0xc39, 0xd30,
|
||||
0x3a0, 0x2a9, 0x1a3, 0x0aa, 0xbac, 0xaa5, 0x9af, 0x8a6,
|
||||
0x7a6, 0x6af, 0x5a5, 0x4ac, 0xfaa, 0xea3, 0xda9, 0xca0,
|
||||
0x8c0, 0x9c9, 0xac3, 0xbca, 0x0cc, 0x1c5, 0x2cf, 0x3c6,
|
||||
0xcc6, 0xdcf, 0xec5, 0xfcc, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
|
||||
0x950, 0x859, 0xb53, 0xa5a, 0x15c, 0x055, 0x35f, 0x256,
|
||||
0xd56, 0xc5f, 0xf55, 0xe5c, 0x55a, 0x453, 0x759, 0x650,
|
||||
0xaf0, 0xbf9, 0x8f3, 0x9fa, 0x2fc, 0x3f5, 0x0ff, 0x1f6,
|
||||
0xef6, 0xfff, 0xcf5, 0xdfc, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
|
||||
0xb60, 0xa69, 0x963, 0x86a, 0x36c, 0x265, 0x16f, 0x066,
|
||||
0xf66, 0xe6f, 0xd65, 0xc6c, 0x76a, 0x663, 0x569, 0x460,
|
||||
0x460, 0x569, 0x663, 0x76a, 0xc6c, 0xd65, 0xe6f, 0xf66,
|
||||
0x066, 0x16f, 0x265, 0x36c, 0x86a, 0x963, 0xa69, 0xb60,
|
||||
0x5f0, 0x4f9, 0x7f3, 0x6fa, 0xdfc, 0xcf5, 0xfff, 0xef6,
|
||||
0x1f6, 0x0ff, 0x3f5, 0x2fc, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
|
||||
0x650, 0x759, 0x453, 0x55a, 0xe5c, 0xf55, 0xc5f, 0xd56,
|
||||
0x256, 0x35f, 0x055, 0x15c, 0xa5a, 0xb53, 0x859, 0x950,
|
||||
0x7c0, 0x6c9, 0x5c3, 0x4ca, 0xfcc, 0xec5, 0xdcf, 0xcc6,
|
||||
0x3c6, 0x2cf, 0x1c5, 0x0cc, 0xbca, 0xac3, 0x9c9, 0x8c0,
|
||||
0xca0, 0xda9, 0xea3, 0xfaa, 0x4ac, 0x5a5, 0x6af, 0x7a6,
|
||||
0x8a6, 0x9af, 0xaa5, 0xbac, 0x0aa, 0x1a3, 0x2a9, 0x3a0,
|
||||
0xd30, 0xc39, 0xf33, 0xe3a, 0x53c, 0x435, 0x73f, 0x636,
|
||||
0x936, 0x83f, 0xb35, 0xa3c, 0x13a, 0x033, 0x339, 0x230,
|
||||
0xe90, 0xf99, 0xc93, 0xd9a, 0x69c, 0x795, 0x49f, 0x596,
|
||||
0xa96, 0xb9f, 0x895, 0x99c, 0x29a, 0x393, 0x099, 0x190,
|
||||
0xf00, 0xe09, 0xd03, 0xc0a, 0x70c, 0x605, 0x50f, 0x406,
|
||||
0xb06, 0xa0f, 0x905, 0x80c, 0x30a, 0x203, 0x109, 0x000
|
||||
};
|
||||
|
||||
const int triTable[256][16] =
|
||||
{
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1, },
|
||||
{ 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1, },
|
||||
{ 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1, },
|
||||
{ 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1, },
|
||||
{ 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1, },
|
||||
{ 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1, },
|
||||
{10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1, },
|
||||
{ 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1, },
|
||||
{ 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1, },
|
||||
{ 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1, },
|
||||
{11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1, },
|
||||
{ 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1, },
|
||||
{ 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1, },
|
||||
{ 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1, },
|
||||
{11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1, },
|
||||
{11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1, },
|
||||
{10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1, },
|
||||
{10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1, },
|
||||
{ 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1, },
|
||||
{ 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1, },
|
||||
{ 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1, },
|
||||
{ 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1, },
|
||||
{ 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1, },
|
||||
{10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1, },
|
||||
{ 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1, },
|
||||
{10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1, },
|
||||
{10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1, },
|
||||
{ 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1, },
|
||||
{ 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1, },
|
||||
{ 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1, },
|
||||
{ 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1, },
|
||||
{ 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1, },
|
||||
{ 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1, },
|
||||
{ 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1, },
|
||||
{ 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1, },
|
||||
{ 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1, },
|
||||
{ 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1, },
|
||||
{ 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1, },
|
||||
{ 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1, },
|
||||
{ 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1, },
|
||||
{ 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1, },
|
||||
{ 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1, },
|
||||
{ 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1, },
|
||||
{11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1, },
|
||||
{ 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1, },
|
||||
{ 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1, },
|
||||
{10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1, },
|
||||
{ 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1, },
|
||||
{ 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1, },
|
||||
{ 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1, },
|
||||
{ 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1, },
|
||||
{ 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1, },
|
||||
{ 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1, },
|
||||
{ 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, },
|
||||
{ 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1, },
|
||||
{ 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1, },
|
||||
{ 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1, },
|
||||
{ 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1, },
|
||||
{ 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1, },
|
||||
{ 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1, },
|
||||
{ 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1, },
|
||||
{ 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1, },
|
||||
{10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1, },
|
||||
{10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1, },
|
||||
{ 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1, },
|
||||
{ 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1, },
|
||||
{ 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1, },
|
||||
{ 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1, },
|
||||
{ 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1, },
|
||||
{ 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1, },
|
||||
{10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1, },
|
||||
{10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1, },
|
||||
{ 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1, },
|
||||
{ 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1, },
|
||||
{11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1, },
|
||||
{ 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1, },
|
||||
{ 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1, },
|
||||
{ 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1, },
|
||||
{ 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1, },
|
||||
{ 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1, },
|
||||
{ 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1, },
|
||||
{ 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1, },
|
||||
{ 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1, },
|
||||
{11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1, },
|
||||
{ 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1, },
|
||||
{ 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1, },
|
||||
{ 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1, },
|
||||
{ 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1, },
|
||||
{10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1, },
|
||||
{ 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1, },
|
||||
{ 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1, },
|
||||
{ 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1, },
|
||||
{ 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1, },
|
||||
{ 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1, },
|
||||
{ 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1, },
|
||||
{ 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1, },
|
||||
{ 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1, },
|
||||
{ 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1, },
|
||||
{ 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1, },
|
||||
{ 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1, },
|
||||
{ 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1, },
|
||||
{ 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1, },
|
||||
{ 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1, },
|
||||
{ 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1, },
|
||||
{11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1, },
|
||||
{ 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1, },
|
||||
{ 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1, },
|
||||
{ 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1, },
|
||||
{ 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{ 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }
|
||||
};
|
||||
}
|
1055
3rdparty/polyvox/library/PolyVoxCore/source/Impl/RandomUnitVectors.cpp
vendored
Normal file
1055
3rdparty/polyvox/library/PolyVoxCore/source/Impl/RandomUnitVectors.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1055
3rdparty/polyvox/library/PolyVoxCore/source/Impl/RandomVectors.cpp
vendored
Normal file
1055
3rdparty/polyvox/library/PolyVoxCore/source/Impl/RandomVectors.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
65
3rdparty/polyvox/library/PolyVoxCore/source/Impl/Utility.cpp
vendored
Normal file
65
3rdparty/polyvox/library/PolyVoxCore/source/Impl/Utility.cpp
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
/*******************************************************************************
|
||||
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 "PolyVoxCore/Impl/Utility.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
//Note: this function only works for inputs which are a power of two and not zero
|
||||
//If this is not the case then the output is undefined.
|
||||
uint8_t logBase2(uint32_t uInput)
|
||||
{
|
||||
//Debug mode validation
|
||||
assert(uInput != 0);
|
||||
assert(isPowerOf2(uInput));
|
||||
|
||||
//Release mode validation
|
||||
if(uInput == 0)
|
||||
{
|
||||
throw std::invalid_argument("Cannot compute the log of zero.");
|
||||
}
|
||||
if(!isPowerOf2(uInput))
|
||||
{
|
||||
throw std::invalid_argument("Input must be a power of two in order to compute the log.");
|
||||
}
|
||||
|
||||
uint32_t uResult = 0;
|
||||
while( (uInput >> uResult) != 0)
|
||||
{
|
||||
++uResult;
|
||||
}
|
||||
return static_cast<uint8_t>(uResult-1);
|
||||
}
|
||||
|
||||
|
||||
bool isPowerOf2(uint32_t uInput)
|
||||
{
|
||||
if(uInput == 0)
|
||||
return false;
|
||||
else
|
||||
return ((uInput & (uInput-1)) == 0);
|
||||
}
|
||||
}
|
29
3rdparty/polyvox/library/PolyVoxCore/source/Log.cpp
vendored
Normal file
29
3rdparty/polyvox/library/PolyVoxCore/source/Log.cpp
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
/*******************************************************************************
|
||||
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 "PolyVoxCore/Log.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
void (*logHandler)(std::string, int severity) = 0;
|
||||
}
|
181
3rdparty/polyvox/library/PolyVoxCore/source/MeshDecimator.cpp
vendored
Normal file
181
3rdparty/polyvox/library/PolyVoxCore/source/MeshDecimator.cpp
vendored
Normal file
@ -0,0 +1,181 @@
|
||||
/*******************************************************************************
|
||||
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 "PolyVoxCore/MeshDecimator.h"
|
||||
#include "PolyVoxCore/SurfaceMesh.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template<>
|
||||
POLYVOX_API void MeshDecimator<PositionMaterial>::fillInitialVertexMetadata(std::vector<InitialVertexMetadata>& vecVertexMetadata)
|
||||
{
|
||||
vecVertexMetadata.clear();
|
||||
vecVertexMetadata.resize(m_pOutputMesh->m_vecVertices.size());
|
||||
//Initialise the metadata
|
||||
for(uint32_t ct = 0; ct < vecVertexMetadata.size(); ct++)
|
||||
{
|
||||
vecVertexMetadata[ct].normal.setElements(0,0,0);
|
||||
vecVertexMetadata[ct].isOnMaterialEdge = false;
|
||||
vecVertexMetadata[ct].isOnRegionFace.reset();
|
||||
}
|
||||
|
||||
//Identify duplicate vertices, as they lie on the material edge. To do this we convert into integers and sort
|
||||
//(first on z, then y, then x). They should be mostly in order as this is the order they come out of the
|
||||
//CubicSurfaceExtractor in. Duplicates are now neighbours in the resulting list so just scan through for pairs.
|
||||
std::vector<IntVertex> intVertices;
|
||||
intVertices.reserve(m_pOutputMesh->m_vecVertices.size());
|
||||
for(uint32_t ct = 0; ct < m_pOutputMesh->m_vecVertices.size(); ct++)
|
||||
{
|
||||
const Vector3DFloat& floatPos = m_pOutputMesh->m_vecVertices[ct].position;
|
||||
IntVertex intVertex(static_cast<uint32_t>(floatPos.getX()), static_cast<uint32_t>(floatPos.getY()), static_cast<uint32_t>(floatPos.getZ()), ct);
|
||||
intVertices.push_back(intVertex);
|
||||
}
|
||||
|
||||
//Do the sorting so that duplicate become neighbours
|
||||
sort(intVertices.begin(), intVertices.end());
|
||||
|
||||
//Find neighbours which are duplicates.
|
||||
for(uint32_t ct = 0; ct < intVertices.size() - 1; ct++)
|
||||
{
|
||||
const IntVertex& v0 = intVertices[ct+0];
|
||||
const IntVertex& v1 = intVertices[ct+1];
|
||||
|
||||
if((v0.x == v1.x) && (v0.y == v1.y) && (v0.z == v1.z))
|
||||
{
|
||||
vecVertexMetadata[v0.index].isOnMaterialEdge = true;
|
||||
vecVertexMetadata[v1.index].isOnMaterialEdge = true;
|
||||
}
|
||||
}
|
||||
|
||||
//Compute an approcimation to the normal, used when deciding if an edge can collapse.
|
||||
for(uint32_t ct = 0; ct < m_pOutputMesh->m_vecVertices.size(); ct++)
|
||||
{
|
||||
Vector3DFloat sumOfNormals(0.0f,0.0f,0.0f);
|
||||
for(vector<uint32_t>::iterator iter = trianglesUsingVertex[ct].begin(); iter != trianglesUsingVertex[ct].end(); iter++)
|
||||
{
|
||||
sumOfNormals += m_vecTriangles[*iter].normal;
|
||||
}
|
||||
|
||||
vecVertexMetadata[ct].normal = sumOfNormals;
|
||||
vecVertexMetadata[ct].normal.normalise();
|
||||
}
|
||||
|
||||
//Identify those vertices on the edge of a region. Care will need to be taken when moving them.
|
||||
for(uint32_t ct = 0; ct < vecVertexMetadata.size(); ct++)
|
||||
{
|
||||
Region regTransformed = m_pOutputMesh->m_Region;
|
||||
regTransformed.shift(regTransformed.getLowerCorner() * static_cast<int32_t>(-1));
|
||||
|
||||
//Plus and minus X
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() < regTransformed.getLowerCorner().getX() + 0.001f);
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() > regTransformed.getUpperCorner().getX() - 0.001f);
|
||||
//Plus and minus Y
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() < regTransformed.getLowerCorner().getY() + 0.001f);
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() > regTransformed.getUpperCorner().getY() - 0.001f);
|
||||
//Plus and minus Z
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() < regTransformed.getLowerCorner().getZ() + 0.001f);
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() > regTransformed.getUpperCorner().getZ() - 0.001f);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
POLYVOX_API void MeshDecimator<PositionMaterialNormal>::fillInitialVertexMetadata(std::vector<InitialVertexMetadata>& vecVertexMetadata)
|
||||
{
|
||||
vecVertexMetadata.clear();
|
||||
vecVertexMetadata.resize(m_pOutputMesh->m_vecVertices.size());
|
||||
|
||||
//Initialise the metadata
|
||||
for(uint32_t ct = 0; ct < vecVertexMetadata.size(); ct++)
|
||||
{
|
||||
vecVertexMetadata[ct].isOnRegionFace.reset();
|
||||
vecVertexMetadata[ct].isOnMaterialEdge = false;
|
||||
vecVertexMetadata[ct].normal = m_pOutputMesh->m_vecVertices[ct].normal;
|
||||
}
|
||||
|
||||
//Identify those vertices on the edge of a region. Care will need to be taken when moving them.
|
||||
for(uint32_t ct = 0; ct < vecVertexMetadata.size(); ct++)
|
||||
{
|
||||
Region regTransformed = m_pOutputMesh->m_Region;
|
||||
regTransformed.shift(regTransformed.getLowerCorner() * static_cast<int32_t>(-1));
|
||||
|
||||
//Plus and minus X
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() < regTransformed.getLowerCorner().getX() + 0.001f);
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() > regTransformed.getUpperCorner().getX() - 0.001f);
|
||||
//Plus and minus Y
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() < regTransformed.getLowerCorner().getY() + 0.001f);
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() > regTransformed.getUpperCorner().getY() - 0.001f);
|
||||
//Plus and minus Z
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() < regTransformed.getLowerCorner().getZ() + 0.001f);
|
||||
vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() > regTransformed.getUpperCorner().getZ() - 0.001f);
|
||||
}
|
||||
|
||||
//If all three vertices have the same material then we are not on a material edge. If any vertex has a different
|
||||
//material then all three vertices are on a material edge. E.g. If one vertex has material 'a' and the other two
|
||||
//have material 'b', then the two 'b's are still on an edge (with 'a') even though they are the same as eachother.
|
||||
for(uint32_t ct = 0; ct < m_vecTriangles.size(); ct++)
|
||||
{
|
||||
uint32_t v0 = m_vecTriangles[ct].v0;
|
||||
uint32_t v1 = m_vecTriangles[ct].v1;
|
||||
uint32_t v2 = m_vecTriangles[ct].v2;
|
||||
|
||||
bool allMatch =
|
||||
(m_pOutputMesh->m_vecVertices[v0].material - m_pOutputMesh->m_vecVertices[v1].material < 0.001f) &&
|
||||
(m_pOutputMesh->m_vecVertices[v1].material - m_pOutputMesh->m_vecVertices[v2].material < 0.001f);
|
||||
|
||||
if(!allMatch)
|
||||
{
|
||||
vecVertexMetadata[v0].isOnMaterialEdge = true;
|
||||
vecVertexMetadata[v1].isOnMaterialEdge = true;
|
||||
vecVertexMetadata[v2].isOnMaterialEdge = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
POLYVOX_API bool MeshDecimator<PositionMaterialNormal>::canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst)
|
||||
{
|
||||
if(m_vecInitialVertexMetadata[uSrc].normal.dot(m_vecInitialVertexMetadata[uDst].normal) < m_fMinDotProductForCollapse)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//With the marching cubes surface we honour the user specified threshold
|
||||
return !collapseChangesFaceNormals(uSrc, uDst, m_fMinDotProductForCollapse);
|
||||
}
|
||||
|
||||
template<>
|
||||
POLYVOX_API bool MeshDecimator<PositionMaterial>::canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst)
|
||||
{
|
||||
//We don't actually use the normal here, because we want to allow face
|
||||
//vertices to collapse onto edge vertices. Simply checking whether anything
|
||||
//has flipped has proved to be the most robust approach, though rather slow.
|
||||
//It's not sufficient to just check the normals, there can be holes in the middle
|
||||
//of the mesh for example.
|
||||
|
||||
//User specified threshold is not used for cubic surface, any
|
||||
//movement is too much (but allow for floating point error).
|
||||
return !collapseChangesFaceNormals(uSrc, uDst, 0.999f);
|
||||
}
|
||||
}
|
258
3rdparty/polyvox/library/PolyVoxCore/source/Region.cpp
vendored
Normal file
258
3rdparty/polyvox/library/PolyVoxCore/source/Region.cpp
vendored
Normal file
@ -0,0 +1,258 @@
|
||||
/*******************************************************************************
|
||||
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 "PolyVoxCore/Region.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
const Region Region::MaxRegion
|
||||
(
|
||||
Vector3DInt32((std::numeric_limits<int32_t>::min)(), (std::numeric_limits<int32_t>::min)(), (std::numeric_limits<int32_t>::min)()),
|
||||
Vector3DInt32((std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)())
|
||||
);
|
||||
|
||||
|
||||
Region::Region()
|
||||
:m_v3dLowerCorner(0,0,0)
|
||||
,m_v3dUpperCorner(0,0,0)
|
||||
{
|
||||
}
|
||||
|
||||
Region::Region(const Vector3DInt32& v3dLowerCorner, const Vector3DInt32& v3dUpperCorner)
|
||||
:m_v3dLowerCorner(v3dLowerCorner)
|
||||
,m_v3dUpperCorner(v3dUpperCorner)
|
||||
{
|
||||
//Check the region is valid.
|
||||
assert(m_v3dUpperCorner.getX() >= m_v3dLowerCorner.getX());
|
||||
assert(m_v3dUpperCorner.getY() >= m_v3dLowerCorner.getY());
|
||||
assert(m_v3dUpperCorner.getZ() >= m_v3dLowerCorner.getZ());
|
||||
}
|
||||
|
||||
Region::Region(int32_t iLowerX, int32_t iLowerY, int32_t iLowerZ, int32_t iUpperX, int32_t iUpperY, int32_t iUpperZ)
|
||||
:m_v3dLowerCorner(iLowerX, iLowerY, iLowerZ)
|
||||
,m_v3dUpperCorner(iUpperX, iUpperY, iUpperZ)
|
||||
{
|
||||
//Check the region is valid.
|
||||
assert(m_v3dUpperCorner.getX() >= m_v3dLowerCorner.getX());
|
||||
assert(m_v3dUpperCorner.getY() >= m_v3dLowerCorner.getY());
|
||||
assert(m_v3dUpperCorner.getZ() >= m_v3dLowerCorner.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
Checks whether two Regions are equal.
|
||||
\param rhs The Region to compare to.
|
||||
\return true if the Regions match.
|
||||
\see operator!=
|
||||
*/
|
||||
bool Region::operator==(const Region& rhs) const
|
||||
{
|
||||
return ((m_v3dLowerCorner == rhs.m_v3dLowerCorner) && (m_v3dUpperCorner == rhs.m_v3dUpperCorner));
|
||||
}
|
||||
|
||||
/**
|
||||
Checks whether two Regions are not equal.
|
||||
\param rhs The Region to compare to.
|
||||
\return true if the Regions do not match.
|
||||
\see operator==
|
||||
*/
|
||||
bool Region::operator!=(const Region& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
const Vector3DInt32& Region::getLowerCorner(void) const
|
||||
{
|
||||
return m_v3dLowerCorner;
|
||||
}
|
||||
|
||||
const Vector3DInt32& Region::getUpperCorner(void) const
|
||||
{
|
||||
return m_v3dUpperCorner;
|
||||
}
|
||||
|
||||
int32_t Region::getWidthInVoxels(void) const
|
||||
{
|
||||
return getWidthInCells() + 1;
|
||||
}
|
||||
|
||||
int32_t Region::getHeightInVoxels(void) const
|
||||
{
|
||||
return getHeightInCells() + 1;
|
||||
}
|
||||
|
||||
int32_t Region::getDepthInVoxels(void) const
|
||||
{
|
||||
return getDepthInCells() + 1;
|
||||
}
|
||||
|
||||
Vector3DInt32 Region::getDimensionsInVoxels(void) const
|
||||
{
|
||||
return getDimensionsInCells() + Vector3DInt32(1, 1, 1);
|
||||
}
|
||||
|
||||
int32_t Region::getWidthInCells(void) const
|
||||
{
|
||||
return m_v3dUpperCorner.getX() - m_v3dLowerCorner.getX();
|
||||
}
|
||||
|
||||
int32_t Region::getHeightInCells(void) const
|
||||
{
|
||||
return m_v3dUpperCorner.getY() - m_v3dLowerCorner.getY();
|
||||
}
|
||||
|
||||
Vector3DInt32 Region::getDimensionsInCells(void) const
|
||||
{
|
||||
return m_v3dUpperCorner - m_v3dLowerCorner;
|
||||
}
|
||||
|
||||
int32_t Region::getDepthInCells(void) const
|
||||
{
|
||||
return m_v3dUpperCorner.getZ() - m_v3dLowerCorner.getZ();
|
||||
}
|
||||
|
||||
void Region::setLowerCorner(const Vector3DInt32& v3dLowerCorner)
|
||||
{
|
||||
m_v3dLowerCorner = v3dLowerCorner;
|
||||
}
|
||||
|
||||
void Region::setUpperCorner(const Vector3DInt32& v3dUpperCorner)
|
||||
{
|
||||
m_v3dUpperCorner = v3dUpperCorner;
|
||||
}
|
||||
|
||||
bool Region::containsPoint(const Vector3DFloat& pos, float boundary) const
|
||||
{
|
||||
return (pos.getX() <= m_v3dUpperCorner.getX() - boundary)
|
||||
&& (pos.getY() <= m_v3dUpperCorner.getY() - boundary)
|
||||
&& (pos.getZ() <= m_v3dUpperCorner.getZ() - boundary)
|
||||
&& (pos.getX() >= m_v3dLowerCorner.getX() + boundary)
|
||||
&& (pos.getY() >= m_v3dLowerCorner.getY() + boundary)
|
||||
&& (pos.getZ() >= m_v3dLowerCorner.getZ() + boundary);
|
||||
}
|
||||
|
||||
bool Region::containsPoint(const Vector3DInt32& pos, uint8_t boundary) const
|
||||
{
|
||||
return (pos.getX() <= m_v3dUpperCorner.getX() - boundary)
|
||||
&& (pos.getY() <= m_v3dUpperCorner.getY() - boundary)
|
||||
&& (pos.getZ() <= m_v3dUpperCorner.getZ() - boundary)
|
||||
&& (pos.getX() >= m_v3dLowerCorner.getX() + boundary)
|
||||
&& (pos.getY() >= m_v3dLowerCorner.getY() + boundary)
|
||||
&& (pos.getZ() >= m_v3dLowerCorner.getZ() + boundary);
|
||||
}
|
||||
|
||||
bool Region::containsPointInX(float pos, float boundary) const
|
||||
{
|
||||
return (pos <= m_v3dUpperCorner.getX() - boundary)
|
||||
&& (pos >= m_v3dLowerCorner.getX() + boundary);
|
||||
}
|
||||
|
||||
bool Region::containsPointInX(int32_t pos, uint8_t boundary) const
|
||||
{
|
||||
return (pos <= m_v3dUpperCorner.getX() - boundary)
|
||||
&& (pos >= m_v3dLowerCorner.getX() + boundary);
|
||||
}
|
||||
|
||||
bool Region::containsPointInY(float pos, float boundary) const
|
||||
{
|
||||
return (pos <= m_v3dUpperCorner.getY() - boundary)
|
||||
&& (pos >= m_v3dLowerCorner.getY() + boundary);
|
||||
}
|
||||
|
||||
bool Region::containsPointInY(int32_t pos, uint8_t boundary) const
|
||||
{
|
||||
return (pos <= m_v3dUpperCorner.getY() - boundary)
|
||||
&& (pos >= m_v3dLowerCorner.getY() + boundary);
|
||||
}
|
||||
|
||||
bool Region::containsPointInZ(float pos, float boundary) const
|
||||
{
|
||||
return (pos <= m_v3dUpperCorner.getZ() - boundary)
|
||||
&& (pos >= m_v3dLowerCorner.getZ() + boundary);
|
||||
}
|
||||
|
||||
bool Region::containsPointInZ(int32_t pos, uint8_t boundary) const
|
||||
{
|
||||
return (pos <= m_v3dUpperCorner.getZ() - boundary)
|
||||
&& (pos >= m_v3dLowerCorner.getZ() + boundary);
|
||||
}
|
||||
|
||||
void Region::cropTo(const Region& other)
|
||||
{
|
||||
m_v3dLowerCorner.setX((std::max)(m_v3dLowerCorner.getX(), other.m_v3dLowerCorner.getX()));
|
||||
m_v3dLowerCorner.setY((std::max)(m_v3dLowerCorner.getY(), other.m_v3dLowerCorner.getY()));
|
||||
m_v3dLowerCorner.setZ((std::max)(m_v3dLowerCorner.getZ(), other.m_v3dLowerCorner.getZ()));
|
||||
m_v3dUpperCorner.setX((std::min)(m_v3dUpperCorner.getX(), other.m_v3dUpperCorner.getX()));
|
||||
m_v3dUpperCorner.setY((std::min)(m_v3dUpperCorner.getY(), other.m_v3dUpperCorner.getY()));
|
||||
m_v3dUpperCorner.setZ((std::min)(m_v3dUpperCorner.getZ(), other.m_v3dUpperCorner.getZ()));
|
||||
}
|
||||
|
||||
/// \deprecated Use getDepthInVoxels() or getDepthInCells() instead
|
||||
int32_t Region::depth(void) const
|
||||
{
|
||||
//This function is deprecated and wrong.
|
||||
assert(false);
|
||||
return m_v3dUpperCorner.getZ() - m_v3dLowerCorner.getZ();
|
||||
}
|
||||
|
||||
/// \deprecated Use getHeightInVoxels() or getHeightInCells() instead
|
||||
int32_t Region::height(void) const
|
||||
{
|
||||
//This function is deprecated and wrong.
|
||||
assert(false);
|
||||
return m_v3dUpperCorner.getY() - m_v3dLowerCorner.getY();
|
||||
}
|
||||
|
||||
void Region::shift(const Vector3DInt32& amount)
|
||||
{
|
||||
m_v3dLowerCorner += amount;
|
||||
m_v3dUpperCorner += amount;
|
||||
}
|
||||
|
||||
void Region::shiftLowerCorner(const Vector3DInt32& amount)
|
||||
{
|
||||
m_v3dLowerCorner += amount;
|
||||
}
|
||||
|
||||
void Region::shiftUpperCorner(const Vector3DInt32& amount)
|
||||
{
|
||||
m_v3dUpperCorner += amount;
|
||||
}
|
||||
|
||||
/// \deprecated Use getDimensionsInVoxels() or getDimensionsInCells() instead
|
||||
Vector3DInt32 Region::dimensions(void)
|
||||
{
|
||||
//This function is deprecated and wrong.
|
||||
assert(false);
|
||||
return m_v3dUpperCorner - m_v3dLowerCorner;
|
||||
}
|
||||
|
||||
/// \deprecated Use getWidthInVoxels() or getWidthInCells() instead
|
||||
int32_t Region::width(void) const
|
||||
{
|
||||
//This function is deprecated and wrong.
|
||||
assert(false);
|
||||
return m_v3dUpperCorner.getX() - m_v3dLowerCorner.getX();
|
||||
}
|
||||
}
|
43
3rdparty/polyvox/library/PolyVoxCore/source/SimpleInterface.cpp
vendored
Normal file
43
3rdparty/polyvox/library/PolyVoxCore/source/SimpleInterface.cpp
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
/*******************************************************************************
|
||||
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 "PolyVoxCore/SimpleInterface.h"
|
||||
|
||||
//DOESN'T BELONG HERE - JUST FOR TESTING!!
|
||||
#include "PolyVoxCore/Density.h"
|
||||
#include "PolyVoxCore/MaterialDensityPair.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
void extractCubicMesh(Volume& volume, const Region& region, Mesh& resultMesh)
|
||||
{
|
||||
CubicSurfaceExtractorWithNormals< SimpleVolume<MaterialDensityPair88> > surfaceExtractor(&volume, region, &resultMesh);
|
||||
surfaceExtractor.execute();
|
||||
}
|
||||
|
||||
void extractSmoothMesh(Volume& volume, const Region& region, Mesh& resultMesh)
|
||||
{
|
||||
MarchingCubesSurfaceExtractor< SimpleVolume<MaterialDensityPair88> > surfaceExtractor(&volume, region, &resultMesh);
|
||||
surfaceExtractor.execute();
|
||||
}
|
||||
}
|
110
3rdparty/polyvox/library/PolyVoxCore/source/VertexTypes.cpp
vendored
Normal file
110
3rdparty/polyvox/library/PolyVoxCore/source/VertexTypes.cpp
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
/*******************************************************************************
|
||||
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 "PolyVoxCore/VertexTypes.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
PositionMaterialNormal::PositionMaterialNormal()
|
||||
{
|
||||
}
|
||||
|
||||
PositionMaterialNormal::PositionMaterialNormal(Vector3DFloat positionToSet, float materialToSet)
|
||||
:position(positionToSet)
|
||||
,material(materialToSet)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PositionMaterialNormal::PositionMaterialNormal(Vector3DFloat positionToSet, Vector3DFloat normalToSet, float materialToSet)
|
||||
:position(positionToSet)
|
||||
,normal(normalToSet)
|
||||
,material(materialToSet)
|
||||
{
|
||||
}
|
||||
|
||||
float PositionMaterialNormal::getMaterial(void) const
|
||||
{
|
||||
return material;
|
||||
}
|
||||
|
||||
const Vector3DFloat& PositionMaterialNormal::getNormal(void) const
|
||||
{
|
||||
return normal;
|
||||
}
|
||||
|
||||
const Vector3DFloat& PositionMaterialNormal::getPosition(void) const
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
void PositionMaterialNormal::setMaterial(float materialToSet)
|
||||
{
|
||||
material = materialToSet;
|
||||
}
|
||||
|
||||
void PositionMaterialNormal::setNormal(const Vector3DFloat& normalToSet)
|
||||
{
|
||||
normal = normalToSet;
|
||||
}
|
||||
|
||||
void PositionMaterialNormal::setPosition(const Vector3DFloat& positionToSet)
|
||||
{
|
||||
position = positionToSet;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PositionMaterial
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PositionMaterial::PositionMaterial()
|
||||
{
|
||||
}
|
||||
|
||||
PositionMaterial::PositionMaterial(Vector3DFloat positionToSet, float materialToSet)
|
||||
:position(positionToSet)
|
||||
,material(materialToSet)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
float PositionMaterial::getMaterial(void) const
|
||||
{
|
||||
return material;
|
||||
}
|
||||
|
||||
const Vector3DFloat& PositionMaterial::getPosition(void) const
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
void PositionMaterial::setMaterial(float materialToSet)
|
||||
{
|
||||
material = materialToSet;
|
||||
}
|
||||
|
||||
void PositionMaterial::setPosition(const Vector3DFloat& positionToSet)
|
||||
{
|
||||
position = positionToSet;
|
||||
}
|
||||
}
|
71
3rdparty/polyvox/library/PolyVoxUtil/CMakeLists.txt
vendored
Normal file
71
3rdparty/polyvox/library/PolyVoxUtil/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
# Copyright (c) 2008-2012 Matt Williams
|
||||
# Copyright (c) 2008-2012 David Williams
|
||||
#
|
||||
# This software is provided 'as-is', without any express or implied
|
||||
# warranty. In no event will the authors be held liable for any damages
|
||||
# arising from the use of this software.
|
||||
#
|
||||
# Permission is granted to anyone to use this software for any purpose,
|
||||
# including commercial applications, and to alter it and redistribute it
|
||||
# freely, subject to the following restrictions:
|
||||
#
|
||||
# 1. The origin of this software must not be misrepresented; you must not
|
||||
# claim that you wrote the original software. If you use this software
|
||||
# in a product, an acknowledgment in the product documentation would be
|
||||
# appreciated but is not required.
|
||||
#
|
||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||
# misrepresented as being the original software.
|
||||
#
|
||||
# 3. This notice may not be removed or altered from any source
|
||||
# distribution.
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
|
||||
PROJECT(PolyVoxUtil)
|
||||
|
||||
#Projects source files
|
||||
SET(UTIL_SRC_FILES
|
||||
source/Dummy.cpp
|
||||
)
|
||||
|
||||
#Projects headers files
|
||||
SET(UTIL_INC_FILES
|
||||
include/PolyVoxUtil/Serialization.h
|
||||
include/PolyVoxUtil/Serialization.inl
|
||||
include/PolyVoxUtil/VolumeChangeTracker.h
|
||||
include/PolyVoxUtil/VolumeChangeTracker.inl
|
||||
)
|
||||
|
||||
ADD_DEFINITIONS(-DPOLYVOX_SHARED_EXPORTS) #Export symbols in the .dll
|
||||
|
||||
#"Sources" and "Headers" are the group names in Visual Studio.
|
||||
#They may have other uses too...
|
||||
SOURCE_GROUP("Sources" FILES ${UTIL_SRC_FILES})
|
||||
SOURCE_GROUP("Headers" FILES ${UTIL_INC_FILES})
|
||||
|
||||
#Tell CMake the paths
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include)
|
||||
#There has to be a better way!
|
||||
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR}/debug ${PolyVoxCore_BINARY_DIR}/release ${PolyVoxCore_BINARY_DIR})
|
||||
|
||||
#Util
|
||||
#Build
|
||||
IF(LIBRARY_TYPE STREQUAL "STATIC")
|
||||
ADD_LIBRARY(PolyVoxUtil STATIC ${UTIL_SRC_FILES} ${UTIL_INC_FILES})
|
||||
IF(UNIX)
|
||||
SET_TARGET_PROPERTIES(PolyVoxCore PROPERTIES COMPILE_FLAGS -fPIC)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(LIBRARY_TYPE STREQUAL "DYNAMIC")
|
||||
ADD_LIBRARY(PolyVoxUtil SHARED ${UTIL_SRC_FILES} ${UTIL_INC_FILES})
|
||||
SET_TARGET_PROPERTIES(PolyVoxUtil PROPERTIES COMPILE_FLAGS "-DPOLYVOX_SHARED_EXPORTS")
|
||||
ENDIF()
|
||||
SET_PROPERTY(TARGET PolyVoxUtil PROPERTY FOLDER "Library")
|
||||
|
||||
TARGET_LINK_LIBRARIES(PolyVoxUtil PolyVoxCore)
|
||||
SET_TARGET_PROPERTIES(PolyVoxUtil PROPERTIES VERSION ${POLYVOX_VERSION} SOVERSION ${POLYVOX_VERSION_MAJOR})
|
||||
IF(MSVC)
|
||||
SET_TARGET_PROPERTIES(PolyVoxUtil PROPERTIES COMPILE_FLAGS "/W4 /wd4251 /wd4127") #Disable warning on STL exports
|
||||
ENDIF(MSVC)
|
||||
|
77
3rdparty/polyvox/library/PolyVoxUtil/include/PolyVoxUtil/Serialization.h
vendored
Normal file
77
3rdparty/polyvox/library/PolyVoxUtil/include/PolyVoxUtil/Serialization.h
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
/*******************************************************************************
|
||||
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_Serialization_H__
|
||||
#define __PolyVox_Serialization_H__
|
||||
|
||||
#include "PolyVoxCore/Impl/Utility.h"
|
||||
|
||||
#include "PolyVoxCore/Region.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/// \deprecated
|
||||
class POLYVOX_DEPRECATED VolumeSerializationProgressListener
|
||||
{
|
||||
public:
|
||||
virtual void onProgressUpdated(float fProgress) = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// THESE FUNCTIONS ARE DEPRECATED.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \deprecated
|
||||
template< typename VolumeType >
|
||||
POLYVOX_DEPRECATED polyvox_shared_ptr< VolumeType > loadVolumeRaw(std::istream& stream, VolumeSerializationProgressListener* progressListener = 0);
|
||||
/// \deprecated
|
||||
template< typename VolumeType >
|
||||
POLYVOX_DEPRECATED void saveVolumeRaw(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener = 0);
|
||||
|
||||
/// \deprecated
|
||||
template< typename VolumeType >
|
||||
POLYVOX_DEPRECATED polyvox_shared_ptr< VolumeType > loadVolumeRle(std::istream& stream, VolumeSerializationProgressListener* progressListener = 0);
|
||||
/// \deprecated
|
||||
template< typename VolumeType >
|
||||
POLYVOX_DEPRECATED void saveVolumeRle(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener = 0);
|
||||
|
||||
/// \deprecated
|
||||
template< typename VolumeType >
|
||||
POLYVOX_DEPRECATED bool loadVolume(std::istream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener = 0);
|
||||
/// \deprecated
|
||||
template< typename VolumeType >
|
||||
POLYVOX_DEPRECATED bool saveVolume(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener = 0);
|
||||
|
||||
/// \deprecated
|
||||
template< typename VolumeType >
|
||||
POLYVOX_DEPRECATED bool loadVersion0(std::istream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener = 0);
|
||||
/// \deprecated
|
||||
template< typename VolumeType >
|
||||
POLYVOX_DEPRECATED bool saveVersion0(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener = 0);
|
||||
}
|
||||
|
||||
#include "PolyVoxUtil/Serialization.inl"
|
||||
|
||||
#endif
|
433
3rdparty/polyvox/library/PolyVoxUtil/include/PolyVoxUtil/Serialization.inl
vendored
Normal file
433
3rdparty/polyvox/library/PolyVoxUtil/include/PolyVoxUtil/Serialization.inl
vendored
Normal file
@ -0,0 +1,433 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
//Note: we don't do much error handling in here - exceptions will simply be propergated up to the caller.
|
||||
//FIXME - think about pointer ownership issues. Or could return volume by value if the copy constructor is shallow
|
||||
template< typename VolumeType >
|
||||
polyvox_shared_ptr< VolumeType > loadVolumeRaw(std::istream& stream, VolumeSerializationProgressListener* progressListener)
|
||||
{
|
||||
assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'loadVolume()' ASAP.
|
||||
|
||||
//Read volume dimensions
|
||||
uint8_t volumeWidthPower = 0;
|
||||
uint8_t volumeHeightPower = 0;
|
||||
uint8_t volumeDepthPower = 0;
|
||||
stream.read(reinterpret_cast<char*>(&volumeWidthPower), sizeof(volumeWidthPower));
|
||||
stream.read(reinterpret_cast<char*>(&volumeHeightPower), sizeof(volumeHeightPower));
|
||||
stream.read(reinterpret_cast<char*>(&volumeDepthPower), sizeof(volumeDepthPower));
|
||||
|
||||
uint16_t volumeWidth = 0x0001 << volumeWidthPower;
|
||||
uint16_t volumeHeight = 0x0001 << volumeHeightPower;
|
||||
uint16_t volumeDepth = 0x0001 << volumeDepthPower;
|
||||
|
||||
//FIXME - need to support non cubic volumes
|
||||
polyvox_shared_ptr< VolumeType > volume(new LargeVolume<VolumeType::VoxelType>(volumeWidth, volumeHeight, volumeDepth));
|
||||
|
||||
//Read data
|
||||
for(uint16_t z = 0; z < volumeDepth; ++z)
|
||||
{
|
||||
//Update progress once per slice.
|
||||
if(progressListener)
|
||||
{
|
||||
float fProgress = static_cast<float>(z) / static_cast<float>(volumeDepth);
|
||||
progressListener->onProgressUpdated(fProgress);
|
||||
}
|
||||
|
||||
for(uint16_t y = 0; y < volumeHeight; ++y)
|
||||
{
|
||||
for(uint16_t x = 0; x < volumeWidth; ++x)
|
||||
{
|
||||
VolumeType::VoxelType value;
|
||||
stream.read(reinterpret_cast<char*>(&value), sizeof(value));
|
||||
|
||||
volume->setVoxelAt(x,y,z,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Finished
|
||||
if(progressListener)
|
||||
{
|
||||
progressListener->onProgressUpdated(1.0f);
|
||||
}
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
template< typename VolumeType >
|
||||
void saveVolumeRaw(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener)
|
||||
{
|
||||
assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'saveVolume()' ASAP.
|
||||
|
||||
//Write volume dimensions
|
||||
uint16_t volumeWidth = volume.getWidth();
|
||||
uint16_t volumeHeight = volume.getHeight();
|
||||
uint16_t volumeDepth = volume.getDepth();
|
||||
|
||||
uint8_t volumeWidthPower = logBase2(volumeWidth);
|
||||
uint8_t volumeHeightPower = logBase2(volumeHeight);
|
||||
uint8_t volumeDepthPower = logBase2(volumeDepth);
|
||||
|
||||
stream.write(reinterpret_cast<char*>(&volumeWidthPower), sizeof(volumeWidthPower));
|
||||
stream.write(reinterpret_cast<char*>(&volumeHeightPower), sizeof(volumeHeightPower));
|
||||
stream.write(reinterpret_cast<char*>(&volumeDepthPower), sizeof(volumeDepthPower));
|
||||
|
||||
//Write data
|
||||
VolumeType::Sampler volIter(&volume);
|
||||
for(uint16_t z = 0; z < volumeDepth; ++z)
|
||||
{
|
||||
//Update progress once per slice.
|
||||
if(progressListener)
|
||||
{
|
||||
float fProgress = static_cast<float>(z) / static_cast<float>(volumeDepth);
|
||||
progressListener->onProgressUpdated(fProgress);
|
||||
}
|
||||
|
||||
for(uint16_t y = 0; y < volumeHeight; ++y)
|
||||
{
|
||||
for(uint16_t x = 0; x < volumeWidth; ++x)
|
||||
{
|
||||
volIter.setPosition(x,y,z);
|
||||
VolumeType::VoxelType value = volIter.getVoxel();
|
||||
stream.write(reinterpret_cast<char*>(&value), sizeof(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Finished
|
||||
if(progressListener)
|
||||
{
|
||||
progressListener->onProgressUpdated(1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
//Note: we don't do much error handling in here - exceptions will simply be propergated up to the caller.
|
||||
//FIXME - think about pointer ownership issues. Or could return volume by value if the copy constructor is shallow
|
||||
template< typename VolumeType >
|
||||
polyvox_shared_ptr< VolumeType > loadVolumeRle(std::istream& stream, VolumeSerializationProgressListener* progressListener)
|
||||
{
|
||||
assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'loadVolume()' ASAP.
|
||||
|
||||
//Read volume dimensions
|
||||
uint8_t volumeWidthPower = 0;
|
||||
uint8_t volumeHeightPower = 0;
|
||||
uint8_t volumeDepthPower = 0;
|
||||
stream.read(reinterpret_cast<char*>(&volumeWidthPower), sizeof(volumeWidthPower));
|
||||
stream.read(reinterpret_cast<char*>(&volumeHeightPower), sizeof(volumeHeightPower));
|
||||
stream.read(reinterpret_cast<char*>(&volumeDepthPower), sizeof(volumeDepthPower));
|
||||
|
||||
uint16_t volumeWidth = 0x0001 << volumeWidthPower;
|
||||
uint16_t volumeHeight = 0x0001 << volumeHeightPower;
|
||||
uint16_t volumeDepth = 0x0001 << volumeDepthPower;
|
||||
|
||||
//FIXME - need to support non cubic volumes
|
||||
polyvox_shared_ptr< VolumeType > volume(new LargeVolume<VolumeType::VoxelType>(volumeWidth, volumeHeight, volumeDepth));
|
||||
|
||||
//Read data
|
||||
bool firstTime = true;
|
||||
uint32_t runLength = 0;
|
||||
VolumeType::VoxelType value;
|
||||
stream.read(reinterpret_cast<char*>(&value), sizeof(value));
|
||||
stream.read(reinterpret_cast<char*>(&runLength), sizeof(runLength));
|
||||
for(uint16_t z = 0; z < volumeDepth; ++z)
|
||||
{
|
||||
//Update progress once per slice.
|
||||
if(progressListener)
|
||||
{
|
||||
float fProgress = static_cast<float>(z) / static_cast<float>(volumeDepth);
|
||||
progressListener->onProgressUpdated(fProgress);
|
||||
}
|
||||
|
||||
for(uint16_t y = 0; y < volumeHeight; ++y)
|
||||
{
|
||||
for(uint16_t x = 0; x < volumeWidth; ++x)
|
||||
{
|
||||
if(runLength != 0)
|
||||
{
|
||||
volume->setVoxelAt(x,y,z,value);
|
||||
runLength--;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.read(reinterpret_cast<char*>(&value), sizeof(value));
|
||||
stream.read(reinterpret_cast<char*>(&runLength), sizeof(runLength));
|
||||
|
||||
volume->setVoxelAt(x,y,z,value);
|
||||
runLength--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Finished
|
||||
if(progressListener)
|
||||
{
|
||||
progressListener->onProgressUpdated(1.0f);
|
||||
}
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
template< typename VolumeType >
|
||||
void saveVolumeRle(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener)
|
||||
{
|
||||
assert(false); //THIS FUNCTION IS DEPRECATED. REMOVE THIS ASSERT TO CONTINUE, BUT SWITCH TO 'saveVolume()' ASAP.
|
||||
|
||||
//Write volume dimensions
|
||||
uint16_t volumeWidth = volume.getWidth();
|
||||
uint16_t volumeHeight = volume.getHeight();
|
||||
uint16_t volumeDepth = volume.getDepth();
|
||||
|
||||
uint8_t volumeWidthPower = logBase2(volumeWidth);
|
||||
uint8_t volumeHeightPower = logBase2(volumeHeight);
|
||||
uint8_t volumeDepthPower = logBase2(volumeDepth);
|
||||
|
||||
stream.write(reinterpret_cast<char*>(&volumeWidthPower), sizeof(volumeWidthPower));
|
||||
stream.write(reinterpret_cast<char*>(&volumeHeightPower), sizeof(volumeHeightPower));
|
||||
stream.write(reinterpret_cast<char*>(&volumeDepthPower), sizeof(volumeDepthPower));
|
||||
|
||||
//Write data
|
||||
VolumeType::Sampler volIter(&volume);
|
||||
VolumeType::VoxelType current;
|
||||
uint32_t runLength = 0;
|
||||
bool firstTime = true;
|
||||
for(uint16_t z = 0; z < volumeDepth; ++z)
|
||||
{
|
||||
//Update progress once per slice.
|
||||
if(progressListener)
|
||||
{
|
||||
float fProgress = static_cast<float>(z) / static_cast<float>(volumeDepth);
|
||||
progressListener->onProgressUpdated(fProgress);
|
||||
}
|
||||
|
||||
for(uint16_t y = 0; y < volumeHeight; ++y)
|
||||
{
|
||||
for(uint16_t x = 0; x < volumeWidth; ++x)
|
||||
{
|
||||
volIter.setPosition(x,y,z);
|
||||
VolumeType::VoxelType value = volIter.getVoxel();
|
||||
if(firstTime)
|
||||
{
|
||||
current = value;
|
||||
runLength = 1;
|
||||
firstTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(value == current)
|
||||
{
|
||||
runLength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.write(reinterpret_cast<char*>(¤t), sizeof(current));
|
||||
stream.write(reinterpret_cast<char*>(&runLength), sizeof(runLength));
|
||||
current = value;
|
||||
runLength = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stream.write(reinterpret_cast<char*>(¤t), sizeof(current));
|
||||
stream.write(reinterpret_cast<char*>(&runLength), sizeof(runLength));
|
||||
|
||||
//Finished
|
||||
if(progressListener)
|
||||
{
|
||||
progressListener->onProgressUpdated(1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// New version of load/save code with versioning
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template< typename VolumeType >
|
||||
bool loadVolume(std::istream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener)
|
||||
{
|
||||
char pIdentifier[8];
|
||||
stream.read(pIdentifier, 7);
|
||||
pIdentifier[7] = '\0'; //Set the null terminator
|
||||
if(strcmp(pIdentifier, "PolyVox") != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t uVersion;
|
||||
stream.read(reinterpret_cast<char*>(&uVersion), sizeof(uVersion));
|
||||
|
||||
switch(uVersion)
|
||||
{
|
||||
case 0:
|
||||
return loadVersion0(stream, volume, progressListener);
|
||||
//Return means no need to break...
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template< typename VolumeType >
|
||||
bool saveVolume(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener)
|
||||
{
|
||||
char pIdentifier[] = "PolyVox";
|
||||
stream.write(pIdentifier, 7);
|
||||
|
||||
uint16_t uVersion = 0;
|
||||
stream.write(reinterpret_cast<const char*>(&uVersion), sizeof(uVersion));
|
||||
|
||||
return saveVersion0(stream, volume, progressListener);
|
||||
}
|
||||
|
||||
//Note: we don't do much error handling in here - exceptions will simply be propergated up to the caller.
|
||||
//FIXME - think about pointer ownership issues. Or could return volume by value if the copy constructor is shallow
|
||||
template< typename VolumeType >
|
||||
bool loadVersion0(std::istream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener)
|
||||
{
|
||||
//Read volume dimensions
|
||||
uint16_t volumeWidth = 0;
|
||||
uint16_t volumeHeight = 0;
|
||||
uint16_t volumeDepth = 0;
|
||||
stream.read(reinterpret_cast<char*>(&volumeWidth), sizeof(volumeWidth));
|
||||
stream.read(reinterpret_cast<char*>(&volumeHeight), sizeof(volumeHeight));
|
||||
stream.read(reinterpret_cast<char*>(&volumeDepth), sizeof(volumeDepth));
|
||||
|
||||
//Resize the volume
|
||||
//HACK - Forces block size to 32. This functions needs reworking anyway due to large volume support.
|
||||
volume.resize(Region(Vector3DInt32(0,0,0), Vector3DInt32(volumeWidth-1, volumeHeight-1, volumeDepth-1)), 32);
|
||||
|
||||
//Read data
|
||||
bool firstTime = true;
|
||||
uint32_t runLength = 0;
|
||||
VolumeType::VoxelType value;
|
||||
stream.read(reinterpret_cast<char*>(&value), sizeof(value));
|
||||
stream.read(reinterpret_cast<char*>(&runLength), sizeof(runLength));
|
||||
for(uint16_t z = 0; z < volumeDepth; ++z)
|
||||
{
|
||||
//Update progress once per slice.
|
||||
if(progressListener)
|
||||
{
|
||||
float fProgress = static_cast<float>(z) / static_cast<float>(volumeDepth);
|
||||
progressListener->onProgressUpdated(fProgress);
|
||||
}
|
||||
|
||||
for(uint16_t y = 0; y < volumeHeight; ++y)
|
||||
{
|
||||
for(uint16_t x = 0; x < volumeWidth; ++x)
|
||||
{
|
||||
if(runLength != 0)
|
||||
{
|
||||
volume.setVoxelAt(x,y,z,value);
|
||||
runLength--;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.read(reinterpret_cast<char*>(&value), sizeof(value));
|
||||
stream.read(reinterpret_cast<char*>(&runLength), sizeof(runLength));
|
||||
|
||||
volume.setVoxelAt(x,y,z,value);
|
||||
runLength--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Finished
|
||||
if(progressListener)
|
||||
{
|
||||
progressListener->onProgressUpdated(1.0f);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template< typename VolumeType >
|
||||
bool saveVersion0(std::ostream& stream, VolumeType& volume, VolumeSerializationProgressListener* progressListener)
|
||||
{
|
||||
//Write volume dimensions
|
||||
uint16_t volumeWidth = volume.getWidth();
|
||||
uint16_t volumeHeight = volume.getHeight();
|
||||
uint16_t volumeDepth = volume.getDepth();
|
||||
|
||||
stream.write(reinterpret_cast<char*>(&volumeWidth), sizeof(volumeWidth));
|
||||
stream.write(reinterpret_cast<char*>(&volumeHeight), sizeof(volumeHeight));
|
||||
stream.write(reinterpret_cast<char*>(&volumeDepth), sizeof(volumeDepth));
|
||||
|
||||
//Write data
|
||||
VolumeType::Sampler volIter(&volume);
|
||||
VolumeType::VoxelType current;
|
||||
uint32_t runLength = 0;
|
||||
bool firstTime = true;
|
||||
for(uint16_t z = 0; z < volumeDepth; ++z)
|
||||
{
|
||||
//Update progress once per slice.
|
||||
if(progressListener)
|
||||
{
|
||||
float fProgress = static_cast<float>(z) / static_cast<float>(volumeDepth);
|
||||
progressListener->onProgressUpdated(fProgress);
|
||||
}
|
||||
|
||||
for(uint16_t y = 0; y < volumeHeight; ++y)
|
||||
{
|
||||
for(uint16_t x = 0; x < volumeWidth; ++x)
|
||||
{
|
||||
volIter.setPosition(x,y,z);
|
||||
VolumeType::VoxelType value = volIter.getVoxel();
|
||||
if(firstTime)
|
||||
{
|
||||
current = value;
|
||||
runLength = 1;
|
||||
firstTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(value == current)
|
||||
{
|
||||
runLength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.write(reinterpret_cast<char*>(¤t), sizeof(current));
|
||||
stream.write(reinterpret_cast<char*>(&runLength), sizeof(runLength));
|
||||
current = value;
|
||||
runLength = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stream.write(reinterpret_cast<char*>(¤t), sizeof(current));
|
||||
stream.write(reinterpret_cast<char*>(&runLength), sizeof(runLength));
|
||||
|
||||
//Finished
|
||||
if(progressListener)
|
||||
{
|
||||
progressListener->onProgressUpdated(1.0f);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
83
3rdparty/polyvox/library/PolyVoxUtil/include/PolyVoxUtil/VolumeChangeTracker.h
vendored
Normal file
83
3rdparty/polyvox/library/PolyVoxUtil/include/PolyVoxUtil/VolumeChangeTracker.h
vendored
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_VolumeChangeTracker_H__
|
||||
#define __PolyVox_VolumeChangeTracker_H__
|
||||
|
||||
#include "Impl/Utility.h"
|
||||
|
||||
#include "PolyVoxCore/Region.h"
|
||||
#include "PolyVoxCore/SurfaceMesh.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
/// Voxel scene manager
|
||||
/// \deprecated
|
||||
template <typename VoxelType>
|
||||
class POLYVOX_DEPRECATED VolumeChangeTracker
|
||||
{
|
||||
public:
|
||||
//Constructors, etc
|
||||
VolumeChangeTracker(LargeVolume<VoxelType>* volumeDataToSet, uint16_t regionSideLength);
|
||||
~VolumeChangeTracker();
|
||||
|
||||
//Getters
|
||||
int32_t getCurrentTime(void) const;
|
||||
int32_t getLastModifiedTimeForRegion(uint16_t uX, uint16_t uY, uint16_t uZ);
|
||||
LargeVolume<VoxelType>* getWrappedVolume(void) const;
|
||||
|
||||
//Setters
|
||||
void setAllRegionsModified(void);
|
||||
void setLockedVoxelAt(uint16_t x, uint16_t y, uint16_t z, VoxelType value);
|
||||
void setVoxelAt(uint16_t x, uint16_t y, uint16_t z, VoxelType value);
|
||||
|
||||
//Others
|
||||
void lockRegion(const Region& regToLock);
|
||||
void unlockRegion(void);
|
||||
//void markRegionChanged(uint16_t firstX, uint16_t firstY, uint16_t firstZ, uint16_t lastX, uint16_t lastY, uint16_t lastZ);
|
||||
|
||||
public:
|
||||
void incrementCurrentTime(void);
|
||||
bool m_bIsLocked;
|
||||
Region m_regLastLocked;
|
||||
LargeVolume<VoxelType>* volumeData;
|
||||
|
||||
uint16_t m_uRegionSideLength;
|
||||
uint8_t m_uRegionSideLengthPower;
|
||||
uint16_t m_uVolumeWidthInRegions;
|
||||
uint16_t m_uVolumeHeightInRegions;
|
||||
uint16_t m_uVolumeDepthInRegions;
|
||||
|
||||
|
||||
//It's not what the block class was designed for, but it
|
||||
//provides a handy way of storing a 3D grid of values.
|
||||
LargeVolume<int32_t>* volRegionLastModified;
|
||||
|
||||
static uint32_t m_uCurrentTime;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxUtil/VolumeChangeTracker.inl"
|
||||
|
||||
#endif
|
212
3rdparty/polyvox/library/PolyVoxUtil/include/PolyVoxUtil/VolumeChangeTracker.inl
vendored
Normal file
212
3rdparty/polyvox/library/PolyVoxUtil/include/PolyVoxUtil/VolumeChangeTracker.inl
vendored
Normal file
@ -0,0 +1,212 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2009 David Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
uint32_t VolumeChangeTracker<VoxelType>::m_uCurrentTime = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// VolumeChangeTracker
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VolumeChangeTracker<VoxelType>::VolumeChangeTracker(LargeVolume<VoxelType>* volumeDataToSet, uint16_t regionSideLength)
|
||||
:m_bIsLocked(false)
|
||||
,volumeData(0)
|
||||
,m_uRegionSideLength(regionSideLength)
|
||||
{
|
||||
volumeData = volumeDataToSet;
|
||||
m_uVolumeWidthInRegions = volumeData->getWidth() / m_uRegionSideLength;
|
||||
m_uVolumeHeightInRegions = volumeData->getHeight() / m_uRegionSideLength;
|
||||
m_uVolumeDepthInRegions = volumeData->getDepth() / m_uRegionSideLength;
|
||||
m_uRegionSideLengthPower = PolyVox::logBase2(m_uRegionSideLength);
|
||||
|
||||
volRegionLastModified = new LargeVolume<int32_t>(m_uVolumeWidthInRegions, m_uVolumeHeightInRegions, m_uVolumeDepthInRegions, 0);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VolumeChangeTracker<VoxelType>::~VolumeChangeTracker()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void VolumeChangeTracker<VoxelType>::setAllRegionsModified(void)
|
||||
{
|
||||
incrementCurrentTime();
|
||||
for(uint16_t blockZ = 0; blockZ < m_uVolumeDepthInRegions; ++blockZ)
|
||||
{
|
||||
for(uint16_t blockY = 0; blockY < m_uVolumeHeightInRegions; ++blockY)
|
||||
{
|
||||
for(uint16_t blockX = 0; blockX < m_uVolumeWidthInRegions; ++blockX)
|
||||
{
|
||||
volRegionLastModified->setVoxelAt(blockX, blockY, blockZ, m_uCurrentTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
int32_t VolumeChangeTracker<VoxelType>::getCurrentTime(void) const
|
||||
{
|
||||
return m_uCurrentTime;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
int32_t VolumeChangeTracker<VoxelType>::getLastModifiedTimeForRegion(uint16_t uX, uint16_t uY, uint16_t uZ)
|
||||
{
|
||||
return volRegionLastModified->getVoxelAt(uX, uY, uZ);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
LargeVolume<VoxelType>* VolumeChangeTracker<VoxelType>::getWrappedVolume(void) const
|
||||
{
|
||||
return volumeData;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void VolumeChangeTracker<VoxelType>::setVoxelAt(uint16_t x, uint16_t y, uint16_t z, VoxelType value)
|
||||
{
|
||||
//Note: We increase the time stamp both at the start and the end
|
||||
//to avoid ambiguity about whether the timestamp comparison should
|
||||
//be '<' vs '<=' or '>' vs '>=' in the users code.
|
||||
incrementCurrentTime();
|
||||
|
||||
volumeData->setVoxelAt(x,y,z,value);
|
||||
|
||||
//If we are not on a boundary, just mark one region.
|
||||
if((x % m_uRegionSideLength != 0) &&
|
||||
(x % m_uRegionSideLength != m_uRegionSideLength-1) &&
|
||||
(y % m_uRegionSideLength != 0) &&
|
||||
(y % m_uRegionSideLength != m_uRegionSideLength-1) &&
|
||||
(z % m_uRegionSideLength != 0) &&
|
||||
(z % m_uRegionSideLength != m_uRegionSideLength-1))
|
||||
{
|
||||
volRegionLastModified->setVoxelAt(x >> m_uRegionSideLengthPower, y >> m_uRegionSideLengthPower, z >> m_uRegionSideLengthPower, m_uCurrentTime);
|
||||
}
|
||||
else //Mark surrounding regions as well
|
||||
{
|
||||
const uint16_t regionX = x >> m_uRegionSideLengthPower;
|
||||
const uint16_t regionY = y >> m_uRegionSideLengthPower;
|
||||
const uint16_t regionZ = z >> m_uRegionSideLengthPower;
|
||||
|
||||
const uint16_t minRegionX = (std::max)(uint16_t(0),uint16_t(regionX-1));
|
||||
const uint16_t minRegionY = (std::max)(uint16_t(0),uint16_t(regionY-1));
|
||||
const uint16_t minRegionZ = (std::max)(uint16_t(0),uint16_t(regionZ-1));
|
||||
|
||||
const uint16_t maxRegionX = (std::min)(uint16_t(m_uVolumeWidthInRegions-1),uint16_t(regionX+1));
|
||||
const uint16_t maxRegionY = (std::min)(uint16_t(m_uVolumeHeightInRegions-1),uint16_t(regionY+1));
|
||||
const uint16_t maxRegionZ = (std::min)(uint16_t(m_uVolumeDepthInRegions-1),uint16_t(regionZ+1));
|
||||
|
||||
for(uint16_t zCt = minRegionZ; zCt <= maxRegionZ; zCt++)
|
||||
{
|
||||
for(uint16_t yCt = minRegionY; yCt <= maxRegionY; yCt++)
|
||||
{
|
||||
for(uint16_t xCt = minRegionX; xCt <= maxRegionX; xCt++)
|
||||
{
|
||||
volRegionLastModified->setVoxelAt(xCt,yCt,zCt,m_uCurrentTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Increment time stamp. See earlier note.
|
||||
incrementCurrentTime();
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void VolumeChangeTracker<VoxelType>::setLockedVoxelAt(uint16_t x, uint16_t y, uint16_t z, VoxelType value)
|
||||
{
|
||||
assert(m_bIsLocked);
|
||||
|
||||
//FIXME - rather than creating a iterator each time we should have one stored
|
||||
/*Sampler<VoxelType> iterVol(*volumeData);
|
||||
iterVol.setPosition(x,y,z);
|
||||
iterVol.setVoxel(value);*/
|
||||
volumeData->setVoxelAt(x,y,z,value);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void VolumeChangeTracker<VoxelType>::lockRegion(const Region& regToLock)
|
||||
{
|
||||
if(m_bIsLocked)
|
||||
{
|
||||
throw std::logic_error("A region is already locked. Please unlock it before locking another.");
|
||||
}
|
||||
|
||||
m_regLastLocked = regToLock;
|
||||
m_bIsLocked = true;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void VolumeChangeTracker<VoxelType>::unlockRegion(void)
|
||||
{
|
||||
if(!m_bIsLocked)
|
||||
{
|
||||
throw std::logic_error("No region is locked. You must lock a region before you can unlock it.");
|
||||
}
|
||||
|
||||
//Note: We increase the time stamp both at the start and the end
|
||||
//to avoid ambiguity about whether the timestamp comparison should
|
||||
//be '<' vs '<=' or '>' vs '>=' in the users code.
|
||||
incrementCurrentTime();
|
||||
|
||||
const uint16_t firstRegionX = m_regLastLocked.getLowerCorner().getX() >> m_uRegionSideLengthPower;
|
||||
const uint16_t firstRegionY = m_regLastLocked.getLowerCorner().getY() >> m_uRegionSideLengthPower;
|
||||
const uint16_t firstRegionZ = m_regLastLocked.getLowerCorner().getZ() >> m_uRegionSideLengthPower;
|
||||
|
||||
const uint16_t lastRegionX = m_regLastLocked.getUpperCorner().getX() >> m_uRegionSideLengthPower;
|
||||
const uint16_t lastRegionY = m_regLastLocked.getUpperCorner().getY() >> m_uRegionSideLengthPower;
|
||||
const uint16_t lastRegionZ = m_regLastLocked.getUpperCorner().getZ() >> m_uRegionSideLengthPower;
|
||||
|
||||
for(uint16_t zCt = firstRegionZ; zCt <= lastRegionZ; zCt++)
|
||||
{
|
||||
for(uint16_t yCt = firstRegionY; yCt <= lastRegionY; yCt++)
|
||||
{
|
||||
for(uint16_t xCt = firstRegionX; xCt <= lastRegionX; xCt++)
|
||||
{
|
||||
volRegionLastModified->setVoxelAt(xCt,yCt,zCt,m_uCurrentTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_bIsLocked = false;
|
||||
|
||||
//Increment time stamp. See earlier note.
|
||||
incrementCurrentTime();
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void VolumeChangeTracker<VoxelType>::incrementCurrentTime(void)
|
||||
{
|
||||
//Increment the current time.
|
||||
uint32_t time = m_uCurrentTime++;
|
||||
|
||||
//Watch out for wraparound. Hopefully this will never happen
|
||||
//as we have a pretty big counter, but it's best to be sure...
|
||||
assert(time < m_uCurrentTime);
|
||||
if(time >= m_uCurrentTime)
|
||||
{
|
||||
throw std::overflow_error("The VolumeChangeTracker time has overflowed.");
|
||||
}
|
||||
}
|
||||
}
|
16
3rdparty/polyvox/library/PolyVoxUtil/source/Dummy.cpp
vendored
Normal file
16
3rdparty/polyvox/library/PolyVoxUtil/source/Dummy.cpp
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
class POLYVOX_API DummyClass
|
||||
{
|
||||
public:
|
||||
int getx(void);
|
||||
int x;
|
||||
};
|
||||
|
||||
int DummyClass::getx(void)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
25
3rdparty/polyvox/library/polyvox.qhcp.in
vendored
Normal file
25
3rdparty/polyvox/library/polyvox.qhcp.in
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!-- This file defines a collection of Qt Help files as well as some amount of the build process -->
|
||||
<QHelpCollectionProject version="1.0">
|
||||
<assistant>
|
||||
<title>PolyVox Documentation</title>
|
||||
<homePage>qthelp://com.volumesoffun.polyvox/api/index.html</homePage>
|
||||
<startPage>qthelp://com.volumesoffun.polyvox/api/index.html</startPage>
|
||||
<!-- Disable the documentation manager so that there's no option to add more docs to this shell instance -->
|
||||
<enableDocumentationManager>false</enableDocumentationManager>
|
||||
<cacheDirectory>volumesoffun/polyvox</cacheDirectory>
|
||||
</assistant>
|
||||
<docFiles>
|
||||
<!-- This section says that polyvox.qch will be created from index.qhp when qcollectiongenerator is run -->
|
||||
<generate>
|
||||
<file>
|
||||
<input>../html/index.qhp</input>
|
||||
<output>polyvox.qch</output>
|
||||
</file>
|
||||
</generate>
|
||||
<!-- We then add the Qt Compressed Help file to the collection -->
|
||||
<register>
|
||||
<file>polyvox.qch</file>
|
||||
</register>
|
||||
</docFiles>
|
||||
</QHelpCollectionProject>
|
14
3rdparty/polyvox/polyvox_version.txt
vendored
Normal file
14
3rdparty/polyvox/polyvox_version.txt
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
polyvox-0.2.1
|
||||
|
||||
Stripped out:
|
||||
- examples
|
||||
- documentation
|
||||
- tests
|
||||
- library/bindings
|
||||
|
||||
Stripped out the previous things from CMakeLists.txt
|
||||
|
||||
Stripped out floody messages from CMakeLists.txt
|
||||
|
||||
Various changes in CMakeLists.txt on various subdirectory levels.
|
||||
|
@ -11,11 +11,13 @@ project(buildat)
|
||||
add_subdirectory("3rdparty/cereal")
|
||||
add_subdirectory("3rdparty/c55lib")
|
||||
add_subdirectory("3rdparty/smallsha1")
|
||||
add_subdirectory("3rdparty/polyvox")
|
||||
|
||||
include_directories("src")
|
||||
include_directories("3rdparty/cereal/include")
|
||||
include_directories("3rdparty/c55lib")
|
||||
include_directories("3rdparty/smallsha1")
|
||||
include_directories("3rdparty/polyvox/library/PolyVoxCore/include")
|
||||
|
||||
#
|
||||
# Global options
|
||||
@ -100,6 +102,7 @@ if(BUILD_CLIENT)
|
||||
target_link_libraries(${CLIENT_EXE_NAME}
|
||||
c55lib
|
||||
smallsha1
|
||||
PolyVoxCore
|
||||
${ABSOLUTE_PATH_LIBS}
|
||||
${LINK_LIBS_ONLY}
|
||||
)
|
||||
@ -125,6 +128,7 @@ if(BUILD_SERVER)
|
||||
src/impl/module.cpp
|
||||
src/impl/sha1.cpp
|
||||
src/impl/packet_stream.cpp
|
||||
src/impl/voxel.cpp
|
||||
)
|
||||
if(WIN32)
|
||||
set(SERVER_CORE_SRCS ${SERVER_CORE_SRCS} src/impl/windows/file_watch.cpp)
|
||||
@ -137,6 +141,7 @@ if(BUILD_SERVER)
|
||||
target_link_libraries(${SERVER_CORE_NAME}
|
||||
c55lib
|
||||
smallsha1
|
||||
PolyVoxCore
|
||||
)
|
||||
if(WIN32)
|
||||
target_link_libraries(${SERVER_CORE_NAME} wsock32 ws2_32)
|
||||
|
Loading…
x
Reference in New Issue
Block a user